1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
23 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
24 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
25 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
26 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
27 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
28 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
29 import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
30 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
31 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
32 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
33 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
34 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
35 import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
36 
37 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
38 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
39 import static com.android.server.wm.ActivityRecord.State.RESUMED;
40 import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
41 import static com.android.server.wm.WindowContainer.POSITION_TOP;
42 
43 import static com.google.common.truth.Truth.assertThat;
44 
45 import static org.junit.Assert.assertEquals;
46 import static org.junit.Assert.assertFalse;
47 import static org.junit.Assert.assertNotNull;
48 import static org.junit.Assert.assertNull;
49 import static org.junit.Assert.assertSame;
50 import static org.junit.Assert.assertTrue;
51 import static org.mockito.ArgumentMatchers.anyInt;
52 import static org.mockito.ArgumentMatchers.eq;
53 import static org.mockito.Mockito.never;
54 import static org.mockito.Mockito.verify;
55 
56 import android.app.ActivityOptions;
57 import android.platform.test.annotations.Presubmit;
58 
59 import androidx.test.filters.SmallTest;
60 
61 import com.android.server.wm.LaunchParamsController.LaunchParams;
62 
63 import org.junit.Test;
64 import org.junit.runner.RunWith;
65 
66 import java.util.List;
67 
68 /**
69  * Tests for the {@link TaskDisplayArea} container.
70  *
71  * Build/Install/Run:
72  *  atest WmTests:TaskDisplayAreaTests
73  */
74 @SmallTest
75 @Presubmit
76 @RunWith(WindowTestRunner.class)
77 public class TaskDisplayAreaTests extends WindowTestsBase {
78 
79     @Test
getLaunchRootTask_checksLaunchAdjacentFlagRoot()80     public void getLaunchRootTask_checksLaunchAdjacentFlagRoot() {
81         final Task rootTask = createTask(
82                 mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
83         rootTask.mCreatedByOrganizer = true;
84         final Task adjacentRootTask = createTask(
85                 mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
86         adjacentRootTask.mCreatedByOrganizer = true;
87         final TaskDisplayArea taskDisplayArea = rootTask.getDisplayArea();
88         adjacentRootTask.setAdjacentTaskFragment(rootTask);
89 
90         taskDisplayArea.setLaunchAdjacentFlagRootTask(adjacentRootTask);
91         Task actualRootTask = taskDisplayArea.getLaunchRootTask(
92                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, null /* options */,
93                 null /* sourceTask */, FLAG_ACTIVITY_LAUNCH_ADJACENT);
94         assertSame(adjacentRootTask, actualRootTask.getRootTask());
95 
96         taskDisplayArea.setLaunchAdjacentFlagRootTask(null);
97         actualRootTask = taskDisplayArea.getLaunchRootTask(WINDOWING_MODE_UNDEFINED,
98                 ACTIVITY_TYPE_STANDARD, null /* options */, null /* sourceTask */,
99                 FLAG_ACTIVITY_LAUNCH_ADJACENT);
100         assertNull(actualRootTask);
101     }
102 
103     @Test
getLaunchRootTask_checksFocusedRootTask()104     public void getLaunchRootTask_checksFocusedRootTask() {
105         final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
106         final Task rootTask = createTaskWithActivity(
107                 taskDisplayArea,
108                 WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD, ON_TOP, true);
109         rootTask.mCreatedByOrganizer = true;
110 
111         final Task adjacentRootTask = createTask(
112                 mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
113         adjacentRootTask.mCreatedByOrganizer = true;
114         adjacentRootTask.setAdjacentTaskFragment(rootTask);
115 
116         taskDisplayArea.setLaunchRootTask(rootTask,
117                 new int[]{WINDOWING_MODE_MULTI_WINDOW}, new int[]{ACTIVITY_TYPE_STANDARD});
118 
119         Task actualRootTask = taskDisplayArea.getLaunchRootTask(
120                 WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD, null /* options */,
121                 null /* sourceTask */, 0 /*launchFlags*/);
122         assertTrue(actualRootTask.isFocusedRootTaskOnDisplay());
123     }
124 
125     @Test
getLaunchRootTask_fromLaunchAdjacentFlagRoot_checksAdjacentRoot()126     public void getLaunchRootTask_fromLaunchAdjacentFlagRoot_checksAdjacentRoot() {
127         final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
128         final Task rootTask = createTask(
129                 mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
130         rootTask.mCreatedByOrganizer = true;
131         final Task adjacentRootTask = createTask(
132                 mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
133         adjacentRootTask.mCreatedByOrganizer = true;
134         final TaskDisplayArea taskDisplayArea = rootTask.getDisplayArea();
135         adjacentRootTask.setAdjacentTaskFragment(rootTask);
136 
137         taskDisplayArea.setLaunchAdjacentFlagRootTask(adjacentRootTask);
138         final Task actualRootTask = taskDisplayArea.getLaunchRootTask(
139                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, null /* options */,
140                 adjacentRootTask /* sourceTask */, FLAG_ACTIVITY_LAUNCH_ADJACENT);
141 
142         assertSame(rootTask, actualRootTask.getRootTask());
143     }
144 
145     @Test
getOrCreateLaunchRootRespectsResolvedWindowingMode()146     public void getOrCreateLaunchRootRespectsResolvedWindowingMode() {
147         final Task rootTask = createTask(
148                 mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
149         rootTask.mCreatedByOrganizer = true;
150         final TaskDisplayArea taskDisplayArea = rootTask.getDisplayArea();
151         taskDisplayArea.setLaunchRootTask(
152                 rootTask, new int[]{WINDOWING_MODE_FREEFORM}, new int[]{ACTIVITY_TYPE_STANDARD});
153 
154         final Task candidateRootTask = createTask(
155                 mDisplayContent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
156         final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
157         final LaunchParams launchParams = new LaunchParams();
158         launchParams.mWindowingMode = WINDOWING_MODE_FREEFORM;
159 
160         final Task actualRootTask = taskDisplayArea.getOrCreateRootTask(
161                 activity, null /* options */, candidateRootTask, null /* sourceTask */,
162                 launchParams, 0 /* launchFlags */, ACTIVITY_TYPE_STANDARD, true /* onTop */);
163         assertSame(rootTask, actualRootTask.getRootTask());
164     }
165 
166     @Test
getOrCreateLaunchRootUsesActivityOptionsWindowingMode()167     public void getOrCreateLaunchRootUsesActivityOptionsWindowingMode() {
168         final Task rootTask = createTask(
169                 mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
170         rootTask.mCreatedByOrganizer = true;
171         final TaskDisplayArea taskDisplayArea = rootTask.getDisplayArea();
172         taskDisplayArea.setLaunchRootTask(
173                 rootTask, new int[]{WINDOWING_MODE_FREEFORM}, new int[]{ACTIVITY_TYPE_STANDARD});
174 
175         final Task candidateRootTask = createTask(
176                 mDisplayContent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
177         final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
178         final ActivityOptions options = ActivityOptions.makeBasic();
179         options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
180 
181         final Task actualRootTask = taskDisplayArea.getOrCreateRootTask(
182                 activity, options, candidateRootTask, null /* sourceTask */,
183                 null /* launchParams */, 0 /* launchFlags */, ACTIVITY_TYPE_STANDARD,
184                 true /* onTop */);
185         assertSame(rootTask, actualRootTask.getRootTask());
186     }
187 
188     @Test
testActivityWithZBoost_taskDisplayAreaDoesNotMoveUp()189     public void testActivityWithZBoost_taskDisplayAreaDoesNotMoveUp() {
190         final Task rootTask = createTask(mDisplayContent);
191         final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
192         final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
193         task.addChild(activity, 0 /* addPos */);
194         final TaskDisplayArea taskDisplayArea = activity.getDisplayArea();
195         activity.mNeedsAnimationBoundsLayer = true;
196         activity.mNeedsZBoost = true;
197         spyOn(taskDisplayArea.mSurfaceAnimator);
198 
199         mDisplayContent.assignChildLayers(mTransaction);
200 
201         assertThat(activity.needsZBoost()).isTrue();
202         assertThat(taskDisplayArea.needsZBoost()).isFalse();
203         verify(taskDisplayArea.mSurfaceAnimator, never()).setLayer(eq(mTransaction), anyInt());
204     }
205 
206     @Test
testRootTaskPositionChildAt()207     public void testRootTaskPositionChildAt() {
208         Task pinnedTask = createTask(
209                 mDisplayContent, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
210         // Root task should contain visible app window to be considered visible.
211         assertFalse(pinnedTask.isVisible());
212         final ActivityRecord pinnedApp = createNonAttachedActivityRecord(mDisplayContent);
213         pinnedTask.addChild(pinnedApp, 0 /* addPos */);
214         assertTrue(pinnedTask.isVisible());
215 
216         // Test that always-on-top root task can't be moved to position other than top.
217         final Task rootTask1 = createTask(mDisplayContent);
218         final Task rootTask2 = createTask(mDisplayContent);
219 
220         final WindowContainer taskContainer = rootTask1.getParent();
221 
222         final int rootTask1Pos = taskContainer.mChildren.indexOf(rootTask1);
223         final int rootTask2Pos = taskContainer.mChildren.indexOf(rootTask2);
224         final int pinnedTaskPos = taskContainer.mChildren.indexOf(pinnedTask);
225         assertThat(pinnedTaskPos).isGreaterThan(rootTask2Pos);
226         assertThat(rootTask2Pos).isGreaterThan(rootTask1Pos);
227 
228         taskContainer.positionChildAt(WindowContainer.POSITION_BOTTOM, pinnedTask, false);
229         assertEquals(taskContainer.mChildren.get(rootTask1Pos), rootTask1);
230         assertEquals(taskContainer.mChildren.get(rootTask2Pos), rootTask2);
231         assertEquals(taskContainer.mChildren.get(pinnedTaskPos), pinnedTask);
232 
233         taskContainer.positionChildAt(1, pinnedTask, false);
234         assertEquals(taskContainer.mChildren.get(rootTask1Pos), rootTask1);
235         assertEquals(taskContainer.mChildren.get(rootTask2Pos), rootTask2);
236         assertEquals(taskContainer.mChildren.get(pinnedTaskPos), pinnedTask);
237     }
238 
239     @Test
testRootTaskPositionBelowPinnedRootTask()240     public void testRootTaskPositionBelowPinnedRootTask() {
241         Task pinnedTask = createTask(
242                 mDisplayContent, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
243         // Root task should contain visible app window to be considered visible.
244         assertFalse(pinnedTask.isVisible());
245         final ActivityRecord pinnedApp = createNonAttachedActivityRecord(mDisplayContent);
246         pinnedTask.addChild(pinnedApp, 0 /* addPos */);
247         assertTrue(pinnedTask.isVisible());
248 
249         // Test that no root task can be above pinned root task.
250         final Task rootTask1 = createTask(mDisplayContent);
251 
252         final WindowContainer taskContainer = rootTask1.getParent();
253 
254         final int rootTaskPos = taskContainer.mChildren.indexOf(rootTask1);
255         final int pinnedTaskPos = taskContainer.mChildren.indexOf(pinnedTask);
256         assertThat(pinnedTaskPos).isGreaterThan(rootTaskPos);
257 
258         taskContainer.positionChildAt(WindowContainer.POSITION_TOP, rootTask1, false);
259         assertEquals(taskContainer.mChildren.get(rootTaskPos), rootTask1);
260         assertEquals(taskContainer.mChildren.get(pinnedTaskPos), pinnedTask);
261 
262         taskContainer.positionChildAt(taskContainer.mChildren.size() - 1, rootTask1, false);
263         assertEquals(taskContainer.mChildren.get(rootTaskPos), rootTask1);
264         assertEquals(taskContainer.mChildren.get(pinnedTaskPos), pinnedTask);
265     }
266 
267     @Test
testDisplayPositionWithPinnedRootTask()268     public void testDisplayPositionWithPinnedRootTask() {
269         // Make sure the display is trusted display which capable to move the root task to top.
270         spyOn(mDisplayContent);
271         doReturn(true).when(mDisplayContent).isTrusted();
272 
273         // Allow child root task to move to top.
274         mDisplayContent.mDontMoveToTop = false;
275 
276         // The display contains pinned root task that was added in {@link #setUp}.
277         final Task rootTask = createTask(mDisplayContent);
278         final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
279 
280         // Add another display at top.
281         mWm.mRoot.positionChildAt(WindowContainer.POSITION_TOP, createNewDisplay(),
282                 false /* includingParents */);
283 
284         // Move the task of {@code mDisplayContent} to top.
285         rootTask.positionChildAt(WindowContainer.POSITION_TOP, task, true /* includingParents */);
286         final int indexOfDisplayWithPinnedRootTask = mWm.mRoot.mChildren.indexOf(mDisplayContent);
287 
288         assertEquals("The testing DisplayContent should be moved to top with task",
289                 mWm.mRoot.getChildCount() - 1, indexOfDisplayWithPinnedRootTask);
290     }
291 
292     @Test
testMovingChildTaskOnTop()293     public void testMovingChildTaskOnTop() {
294         // Make sure the display is trusted display which capable to move the root task to top.
295         spyOn(mDisplayContent);
296         doReturn(true).when(mDisplayContent).isTrusted();
297 
298         // Allow child root task to move to top.
299         mDisplayContent.mDontMoveToTop = false;
300 
301         // The display contains pinned root task that was added in {@link #setUp}.
302         Task rootTask = createTask(mDisplayContent);
303         Task task = createTaskInRootTask(rootTask, 0 /* userId */);
304 
305         // Add another display at top.
306         mWm.mRoot.positionChildAt(WindowContainer.POSITION_TOP, createNewDisplay(),
307                 false /* includingParents */);
308 
309         // Ensure that original display ({@code mDisplayContent}) is not on top.
310         assertEquals("Testing DisplayContent should not be on the top",
311                 mWm.mRoot.getChildCount() - 2, mWm.mRoot.mChildren.indexOf(mDisplayContent));
312 
313         // Move the task of {@code mDisplayContent} to top.
314         rootTask.positionChildAt(WindowContainer.POSITION_TOP, task, true /* includingParents */);
315 
316         // Ensure that original display ({@code mDisplayContent}) is now on the top.
317         assertEquals("The testing DisplayContent should be moved to top with task",
318                 mWm.mRoot.getChildCount() - 1, mWm.mRoot.mChildren.indexOf(mDisplayContent));
319     }
320 
321     @Test
testDontMovingChildTaskOnTop()322     public void testDontMovingChildTaskOnTop() {
323         // Make sure the display is trusted display which capable to move the root task to top.
324         spyOn(mDisplayContent);
325         doReturn(true).when(mDisplayContent).isTrusted();
326 
327         // Allow child root task to move to top.
328         mDisplayContent.mDontMoveToTop = true;
329 
330         // The display contains pinned root task that was added in {@link #setUp}.
331         Task rootTask = createTask(mDisplayContent);
332         Task task = createTaskInRootTask(rootTask, 0 /* userId */);
333 
334         // Add another display at top.
335         mWm.mRoot.positionChildAt(WindowContainer.POSITION_TOP, createNewDisplay(),
336                 false /* includingParents */);
337 
338         // Ensure that original display ({@code mDisplayContent}) is not on top.
339         assertEquals("Testing DisplayContent should not be on the top",
340                 mWm.mRoot.getChildCount() - 2, mWm.mRoot.mChildren.indexOf(mDisplayContent));
341 
342         // Try moving the task of {@code mDisplayContent} to top.
343         rootTask.positionChildAt(WindowContainer.POSITION_TOP, task, true /* includingParents */);
344 
345         // Ensure that original display ({@code mDisplayContent}) hasn't moved and is not
346         // on the top.
347         assertEquals("The testing DisplayContent should not be moved to top with task",
348                 mWm.mRoot.getChildCount() - 2, mWm.mRoot.mChildren.indexOf(mDisplayContent));
349     }
350 
351     @Test
testReuseTaskAsRootTask()352     public void testReuseTaskAsRootTask() {
353         final Task candidateTask = createTask(mDisplayContent);
354         List<Integer> activityTypesWithReusableRootTask = List.of(ACTIVITY_TYPE_STANDARD,
355                 ACTIVITY_TYPE_RECENTS);
356         for (Integer type : activityTypesWithReusableRootTask) {
357             assertGetOrCreateRootTask(WINDOWING_MODE_FULLSCREEN, type, candidateTask,
358                     true /* reuseCandidate */);
359             assertGetOrCreateRootTask(WINDOWING_MODE_UNDEFINED, type, candidateTask,
360                     true /* reuseCandidate */);
361             assertGetOrCreateRootTask(WINDOWING_MODE_FREEFORM, type, candidateTask,
362                     true /* reuseCandidate */);
363             assertGetOrCreateRootTask(WINDOWING_MODE_MULTI_WINDOW, type, candidateTask,
364                     true /* reuseCandidate */);
365             assertGetOrCreateRootTask(WINDOWING_MODE_PINNED, type, candidateTask,
366                     true /* reuseCandidate */);
367         }
368 
369         final int windowingMode = WINDOWING_MODE_FULLSCREEN;
370         assertGetOrCreateRootTask(windowingMode, ACTIVITY_TYPE_HOME, candidateTask,
371                 false /* reuseCandidate */);
372         assertGetOrCreateRootTask(windowingMode, ACTIVITY_TYPE_ASSISTANT, candidateTask,
373                 false /* reuseCandidate */);
374         assertGetOrCreateRootTask(windowingMode, ACTIVITY_TYPE_DREAM, candidateTask,
375                 false /* reuseCandidate */);
376     }
377 
378     @Test
testGetOrientation_nonResizableHomeTaskWithHomeActivityPendingVisibilityChange()379     public void testGetOrientation_nonResizableHomeTaskWithHomeActivityPendingVisibilityChange() {
380         final RootWindowContainer rootWindowContainer = mWm.mAtmService.mRootWindowContainer;
381         final TaskDisplayArea defaultTaskDisplayArea =
382                 rootWindowContainer.getDefaultTaskDisplayArea();
383 
384         final Task rootHomeTask = defaultTaskDisplayArea.getRootHomeTask();
385         rootHomeTask.mResizeMode = RESIZE_MODE_UNRESIZEABLE;
386 
387         final Task primarySplitTask = new TaskBuilder(mSupervisor)
388                 .setTaskDisplayArea(defaultTaskDisplayArea)
389                 .setWindowingMode(WINDOWING_MODE_MULTI_WINDOW)
390                 .setActivityType(ACTIVITY_TYPE_STANDARD)
391                 .setOnTop(true)
392                 .setCreateActivity(true)
393                 .build();
394         ActivityRecord primarySplitActivity = primarySplitTask.getTopNonFinishingActivity();
395         assertNotNull(primarySplitActivity);
396         primarySplitActivity.setState(RESUMED,
397                 "testGetOrientation_nonResizableHomeTaskWithHomeActivityPendingVisibilityChange");
398 
399         ActivityRecord homeActivity = rootHomeTask.getTopNonFinishingActivity();
400         if (homeActivity == null) {
401             homeActivity = new ActivityBuilder(mWm.mAtmService)
402                     .setParentTask(rootHomeTask).setCreateTask(true).build();
403         }
404         homeActivity.setVisible(false);
405         homeActivity.setVisibleRequested(true);
406         assertFalse(rootHomeTask.isVisible());
407 
408         assertEquals(defaultTaskDisplayArea.getOrientation(), rootHomeTask.getOrientation());
409     }
410 
411     @Test
testIsLastFocused()412     public void testIsLastFocused() {
413         final TaskDisplayArea firstTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
414         final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
415                 mDisplayContent, mRootWindowContainer.mWmService, "TestTaskDisplayArea",
416                 FEATURE_VENDOR_FIRST);
417         final Task firstRootTask = firstTaskDisplayArea.createRootTask(
418                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
419         final Task secondRootTask = secondTaskDisplayArea.createRootTask(
420                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
421         final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
422                 .setTask(firstRootTask).build();
423         final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
424                 .setTask(secondRootTask).build();
425 
426         // Activity on TDA1 is focused
427         mDisplayContent.setFocusedApp(firstActivity);
428 
429         final int testOrientation = SCREEN_ORIENTATION_PORTRAIT;
430 
431         assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue();
432         assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
433 
434         // No focused app, TDA1 is still recorded as last focused.
435         mDisplayContent.setFocusedApp(null);
436 
437         assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue();
438         assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
439 
440         // Activity on TDA2 is focused
441         mDisplayContent.setFocusedApp(secondActivity);
442 
443         assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
444         assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue();
445     }
446 
447     @Test
testCanSpecifyOrientation()448     public void testCanSpecifyOrientation() {
449         final TaskDisplayArea firstTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
450         final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
451                 mDisplayContent, mRootWindowContainer.mWmService, "TestTaskDisplayArea",
452                 FEATURE_VENDOR_FIRST);
453         final Task firstRootTask = firstTaskDisplayArea.createRootTask(
454                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
455         final Task secondRootTask = secondTaskDisplayArea.createRootTask(
456                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
457         final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
458                 .setTask(firstRootTask).build();
459         final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
460                 .setTask(secondRootTask).build();
461         firstTaskDisplayArea.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
462         secondTaskDisplayArea.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
463 
464         final int testOrientation = SCREEN_ORIENTATION_PORTRAIT;
465 
466         // Activity on TDA1 is focused, but TDA1 cannot specify orientation because
467         // ignoreOrientationRequest is true
468         // Activity on TDA2 has ignoreOrientationRequest false but it doesn't have focus so it
469         // cannot specify orientation
470         mDisplayContent.setFocusedApp(firstActivity);
471 
472         assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
473         assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
474 
475         // Activity on TDA1 is not focused, and so it cannot specify orientation
476         // Activity on TDA2 is focused, and it can specify orientation because
477         // ignoreOrientationRequest is false
478         mDisplayContent.setFocusedApp(secondActivity);
479 
480         assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
481         assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue();
482     }
483 
484     @Test
testCanSpecifyOrientationNoSensor()485     public void testCanSpecifyOrientationNoSensor() {
486         final TaskDisplayArea firstTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
487         final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
488                 mDisplayContent, mRootWindowContainer.mWmService, "TestTaskDisplayArea",
489                 FEATURE_VENDOR_FIRST);
490         final Task firstRootTask = firstTaskDisplayArea.createRootTask(
491                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
492         final Task secondRootTask = secondTaskDisplayArea.createRootTask(
493                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
494         final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
495                 .setTask(firstRootTask).build();
496         final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
497                 .setTask(secondRootTask).build();
498         firstTaskDisplayArea.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
499         secondTaskDisplayArea.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
500 
501         final int testOrientation = SCREEN_ORIENTATION_NOSENSOR;
502 
503         // ignoreOrientationRequest is always false for SCREEN_ORIENTATION_NOSENSOR so
504         // only the TDAs with focus can specify orientations
505         mDisplayContent.setFocusedApp(firstActivity);
506 
507         assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue();
508         assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
509 
510         mDisplayContent.setFocusedApp(secondActivity);
511 
512         assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
513         assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue();
514     }
515 
516     @Test
testCanSpecifyOrientationLocked()517     public void testCanSpecifyOrientationLocked() {
518         final TaskDisplayArea firstTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
519         final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
520                 mDisplayContent, mRootWindowContainer.mWmService, "TestTaskDisplayArea",
521                 FEATURE_VENDOR_FIRST);
522         final Task firstRootTask = firstTaskDisplayArea.createRootTask(
523                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
524         final Task secondRootTask = secondTaskDisplayArea.createRootTask(
525                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
526         final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
527                 .setTask(firstRootTask).build();
528         final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
529                 .setTask(secondRootTask).build();
530         firstTaskDisplayArea.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
531         secondTaskDisplayArea.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
532 
533         final int testOrientation = SCREEN_ORIENTATION_LOCKED;
534 
535         // ignoreOrientationRequest is always false for SCREEN_ORIENTATION_NOSENSOR so
536         // only the TDAs with focus can specify orientations
537         mDisplayContent.setFocusedApp(firstActivity);
538 
539         assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue();
540         assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
541 
542         mDisplayContent.setFocusedApp(secondActivity);
543 
544         assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
545         assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue();
546     }
547 
548     @Test
549     @UseTestDisplay
testRemove_reparentToDefault()550     public void testRemove_reparentToDefault() {
551         final Task task = createTask(mDisplayContent);
552         final TaskDisplayArea displayArea = task.getDisplayArea();
553         displayArea.remove();
554         assertTrue(displayArea.isRemoved());
555         assertFalse(displayArea.hasChild());
556 
557         final RootWindowContainer rootWindowContainer = mWm.mAtmService.mRootWindowContainer;
558         final TaskDisplayArea defaultTaskDisplayArea =
559                 rootWindowContainer.getDefaultTaskDisplayArea();
560         assertTrue(defaultTaskDisplayArea.mChildren.contains(task));
561     }
562 
563     @Test
564     @UseTestDisplay
testRemove_rootTaskCreatedByOrganizer()565     public void testRemove_rootTaskCreatedByOrganizer() {
566         final Task task = createTask(mDisplayContent);
567         task.mCreatedByOrganizer = true;
568         final TaskDisplayArea displayArea = task.getDisplayArea();
569         displayArea.remove();
570         assertTrue(displayArea.isRemoved());
571         assertFalse(displayArea.hasChild());
572 
573         final RootWindowContainer rootWindowContainer = mWm.mAtmService.mRootWindowContainer;
574         final TaskDisplayArea defaultTaskDisplayArea =
575                 rootWindowContainer.getDefaultTaskDisplayArea();
576         assertFalse(defaultTaskDisplayArea.mChildren.contains(task));
577     }
578 
assertGetOrCreateRootTask(int windowingMode, int activityType, Task candidateTask, boolean reuseCandidate)579     private void assertGetOrCreateRootTask(int windowingMode, int activityType, Task candidateTask,
580             boolean reuseCandidate) {
581         final TaskDisplayArea taskDisplayArea = candidateTask.getDisplayArea();
582         final Task rootTask = taskDisplayArea.getOrCreateRootTask(windowingMode, activityType,
583                 false /* onTop */, candidateTask /* candidateTask */, null /* sourceTask */,
584                 null /* activityOptions */, 0 /* launchFlags */);
585         assertEquals(reuseCandidate, rootTask == candidateTask);
586     }
587 
588     @Test
testGetOrCreateRootHomeTask_defaultDisplay()589     public void testGetOrCreateRootHomeTask_defaultDisplay() {
590         TaskDisplayArea defaultTaskDisplayArea = mWm.mRoot.getDefaultTaskDisplayArea();
591 
592         // Remove the current home root task if it exists so a new one can be created below.
593         Task homeTask = defaultTaskDisplayArea.getRootHomeTask();
594         if (homeTask != null) {
595             defaultTaskDisplayArea.removeChild(homeTask);
596         }
597         assertNull(defaultTaskDisplayArea.getRootHomeTask());
598 
599         assertNotNull(defaultTaskDisplayArea.getOrCreateRootHomeTask());
600     }
601 
602     @Test
testGetOrCreateRootHomeTask_supportedSecondaryDisplay()603     public void testGetOrCreateRootHomeTask_supportedSecondaryDisplay() {
604         DisplayContent display = createNewDisplay();
605         doReturn(true).when(display).supportsSystemDecorations();
606 
607         // Remove the current home root task if it exists so a new one can be created below.
608         TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
609         Task homeTask = taskDisplayArea.getRootHomeTask();
610         if (homeTask != null) {
611             taskDisplayArea.removeChild(homeTask);
612         }
613         assertNull(taskDisplayArea.getRootHomeTask());
614 
615         assertNotNull(taskDisplayArea.getOrCreateRootHomeTask());
616     }
617 
618     @Test
testGetOrCreateRootHomeTask_unsupportedSystemDecorations()619     public void testGetOrCreateRootHomeTask_unsupportedSystemDecorations() {
620         DisplayContent display = createNewDisplay();
621         TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
622         doReturn(false).when(display).supportsSystemDecorations();
623 
624         assertNull(taskDisplayArea.getRootHomeTask());
625         assertNull(taskDisplayArea.getOrCreateRootHomeTask());
626     }
627 
628     @Test
testGetOrCreateRootHomeTask_untrustedDisplay()629     public void testGetOrCreateRootHomeTask_untrustedDisplay() {
630         DisplayContent display = createNewDisplay();
631         TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
632         doReturn(false).when(display).isTrusted();
633 
634         assertNull(taskDisplayArea.getRootHomeTask());
635         assertNull(taskDisplayArea.getOrCreateRootHomeTask());
636     }
637 
638     @Test
testGetOrCreateRootHomeTask_dontMoveToTop()639     public void testGetOrCreateRootHomeTask_dontMoveToTop() {
640         DisplayContent display = createNewDisplay();
641         display.mDontMoveToTop = true;
642         TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea();
643 
644         assertNull(taskDisplayArea.getRootHomeTask());
645         assertNull(taskDisplayArea.getOrCreateRootHomeTask());
646     }
647 
648     @Test
testLastFocusedRootTaskIsUpdatedWhenMovingRootTask()649     public void testLastFocusedRootTaskIsUpdatedWhenMovingRootTask() {
650         // Create a root task at bottom.
651         final TaskDisplayArea taskDisplayAreas =
652                 mRootWindowContainer.getDefaultDisplay().getDefaultTaskDisplayArea();
653         final Task rootTask =
654                 new TaskBuilder(mSupervisor).setOnTop(!ON_TOP).setCreateActivity(true).build();
655         final Task prevFocusedRootTask = taskDisplayAreas.getFocusedRootTask();
656 
657         rootTask.moveToFront("moveRootTaskToFront");
658         // After moving the root task to front, the previous focused should be the last focused.
659         assertTrue(rootTask.isFocusedRootTaskOnDisplay());
660         assertEquals(prevFocusedRootTask, taskDisplayAreas.getLastFocusedRootTask());
661 
662         rootTask.moveToBack("moveRootTaskToBack", null /* task */);
663         // After moving the root task to back, the root task should be the last focused.
664         assertEquals(rootTask, taskDisplayAreas.getLastFocusedRootTask());
665     }
666 
667     /**
668      * This test simulates the picture-in-picture menu activity launches an activity to fullscreen
669      * root task. The fullscreen root task should be the top focused for resuming correctly.
670      */
671     @Test
testFullscreenRootTaskCanBeFocusedWhenFocusablePinnedRootTaskExists()672     public void testFullscreenRootTaskCanBeFocusedWhenFocusablePinnedRootTaskExists() {
673         // Create a pinned root task and move to front.
674         final Task pinnedRootTask = mRootWindowContainer.getDefaultTaskDisplayArea()
675                 .createRootTask(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, ON_TOP);
676         final Task pinnedTask = new TaskBuilder(mAtm.mTaskSupervisor)
677                 .setParentTask(pinnedRootTask).build();
678         new ActivityBuilder(mAtm).setActivityFlags(FLAG_ALWAYS_FOCUSABLE)
679                 .setTask(pinnedTask).build();
680         pinnedRootTask.moveToFront("movePinnedRootTaskToFront");
681 
682         // The focused root task should be the pinned root task.
683         assertTrue(pinnedRootTask.isFocusedRootTaskOnDisplay());
684 
685         // Create a fullscreen root task and move to front.
686         final Task fullscreenRootTask = createTaskWithActivity(
687                 mRootWindowContainer.getDefaultTaskDisplayArea(),
688                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, ON_TOP, true);
689         fullscreenRootTask.moveToFront("moveFullscreenRootTaskToFront");
690 
691         // The focused root task should be the fullscreen root task.
692         assertTrue(fullscreenRootTask.isFocusedRootTaskOnDisplay());
693     }
694 
695     /**
696      * Test {@link TaskDisplayArea#mPreferredTopFocusableRootTask} will be cleared when
697      * the root task is removed or moved to back, and the focused root task will be according to
698      * z-order.
699      */
700     @Test
testRootTaskShouldNotBeFocusedAfterMovingToBackOrRemoving()701     public void testRootTaskShouldNotBeFocusedAfterMovingToBackOrRemoving() {
702         // Create a display which only contains 2 root task.
703         final DisplayContent display = addNewDisplayContentAt(POSITION_TOP);
704         final Task rootTask1 = createTaskWithActivity(display.getDefaultTaskDisplayArea(),
705                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, ON_TOP, true /* twoLevelTask */);
706         final Task rootTask2 = createTaskWithActivity(display.getDefaultTaskDisplayArea(),
707                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, ON_TOP, true /* twoLevelTask */);
708 
709         // Put rootTask1 and rootTask2 on top.
710         rootTask1.moveToFront("moveRootTask1ToFront");
711         rootTask2.moveToFront("moveRootTask2ToFront");
712         assertTrue(rootTask2.isFocusedRootTaskOnDisplay());
713 
714         // rootTask1 should be focused after moving rootTask2 to back.
715         rootTask2.moveToBack("moveRootTask2ToBack", null /* task */);
716         assertTrue(rootTask1.isFocusedRootTaskOnDisplay());
717 
718         // rootTask2 should be focused after removing rootTask1.
719         rootTask1.getDisplayArea().removeRootTask(rootTask1);
720         assertTrue(rootTask2.isFocusedRootTaskOnDisplay());
721     }
722 
723     /**
724      * This test enforces that alwaysOnTop root task is placed at proper position.
725      */
726     @Test
testAlwaysOnTopRootTaskLocation()727     public void testAlwaysOnTopRootTaskLocation() {
728         final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
729         final Task alwaysOnTopRootTask = taskDisplayArea.createRootTask(WINDOWING_MODE_FREEFORM,
730                 ACTIVITY_TYPE_STANDARD, true /* onTop */);
731         final ActivityRecord activity = new ActivityBuilder(mAtm)
732                 .setTask(alwaysOnTopRootTask).build();
733         alwaysOnTopRootTask.setAlwaysOnTop(true);
734         taskDisplayArea.positionChildAt(POSITION_TOP, alwaysOnTopRootTask,
735                 false /* includingParents */);
736         assertTrue(alwaysOnTopRootTask.isAlwaysOnTop());
737         assertEquals(alwaysOnTopRootTask, taskDisplayArea.getTopRootTask());
738 
739         final Task pinnedRootTask = taskDisplayArea.createRootTask(
740                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
741         assertEquals(pinnedRootTask, taskDisplayArea.getRootPinnedTask());
742         assertEquals(pinnedRootTask, taskDisplayArea.getTopRootTask());
743 
744         final Task anotherAlwaysOnTopRootTask = taskDisplayArea.createRootTask(
745                 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
746         anotherAlwaysOnTopRootTask.setAlwaysOnTop(true);
747         taskDisplayArea.positionChildAt(POSITION_TOP, anotherAlwaysOnTopRootTask,
748                 false /* includingParents */);
749         assertTrue(anotherAlwaysOnTopRootTask.isAlwaysOnTop());
750         int topPosition = taskDisplayArea.getRootTaskCount() - 1;
751         // Ensure the new alwaysOnTop root task is put below the pinned root task, but on top of the
752         // existing alwaysOnTop root task.
753         assertEquals(topPosition - 1, getTaskIndexOf(taskDisplayArea, anotherAlwaysOnTopRootTask));
754 
755         final Task nonAlwaysOnTopRootTask = taskDisplayArea.createRootTask(
756                 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
757         assertEquals(taskDisplayArea, nonAlwaysOnTopRootTask.getDisplayArea());
758         topPosition = taskDisplayArea.getRootTaskCount() - 1;
759         // Ensure the non-alwaysOnTop root task is put below the three alwaysOnTop root tasks, but
760         // above the existing other non-alwaysOnTop root tasks.
761         assertEquals(topPosition - 3, getTaskIndexOf(taskDisplayArea, nonAlwaysOnTopRootTask));
762 
763         anotherAlwaysOnTopRootTask.setAlwaysOnTop(false);
764         taskDisplayArea.positionChildAt(POSITION_TOP, anotherAlwaysOnTopRootTask,
765                 false /* includingParents */);
766         assertFalse(anotherAlwaysOnTopRootTask.isAlwaysOnTop());
767         // Ensure, when always on top is turned off for a root task, the root task is put just below
768         // all other always on top root tasks.
769         assertEquals(topPosition - 2, getTaskIndexOf(taskDisplayArea, anotherAlwaysOnTopRootTask));
770         anotherAlwaysOnTopRootTask.setAlwaysOnTop(true);
771 
772         // Ensure always on top state changes properly when windowing mode changes.
773         anotherAlwaysOnTopRootTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
774         assertFalse(anotherAlwaysOnTopRootTask.isAlwaysOnTop());
775         assertEquals(topPosition - 2, getTaskIndexOf(taskDisplayArea, anotherAlwaysOnTopRootTask));
776         anotherAlwaysOnTopRootTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
777         assertTrue(anotherAlwaysOnTopRootTask.isAlwaysOnTop());
778         assertEquals(topPosition - 1, getTaskIndexOf(taskDisplayArea, anotherAlwaysOnTopRootTask));
779 
780         final Task dreamRootTask = taskDisplayArea.createRootTask(
781                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_DREAM, true /* onTop */);
782         assertEquals(taskDisplayArea, dreamRootTask.getDisplayArea());
783         assertTrue(dreamRootTask.isAlwaysOnTop());
784         topPosition = taskDisplayArea.getRootTaskCount() - 1;
785         // Ensure dream shows above all activities, including PiP
786         assertEquals(dreamRootTask, taskDisplayArea.getTopRootTask());
787         assertEquals(topPosition - 1, getTaskIndexOf(taskDisplayArea, pinnedRootTask));
788 
789         final Task assistRootTask = taskDisplayArea.createRootTask(
790                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */);
791         assertEquals(taskDisplayArea, assistRootTask.getDisplayArea());
792         assertFalse(assistRootTask.isAlwaysOnTop());
793         topPosition = taskDisplayArea.getRootTaskCount() - 1;
794 
795         // Ensure Assistant shows as a non-always-on-top activity when config_assistantOnTopOfDream
796         // is false and on top of everything when true.
797         final boolean isAssistantOnTop = mContext.getResources()
798                 .getBoolean(com.android.internal.R.bool.config_assistantOnTopOfDream);
799         assertEquals(isAssistantOnTop ? topPosition : topPosition - 4,
800                 getTaskIndexOf(taskDisplayArea, assistRootTask));
801     }
802 
803     /**
804      * This test verifies proper launch root based on source and candidate task for split screen.
805      * If a task is launching from a created-by-organizer task, it should be launched into the
806      * same created-by-organizer task as well. Unless, the candidate task is already positioned in
807      * the split.
808      */
809     @Test
getLaunchRootTaskInSplit()810     public void getLaunchRootTaskInSplit() {
811         final Task rootTask = createTask(
812                 mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
813         rootTask.mCreatedByOrganizer = true;
814         final Task adjacentRootTask = createTask(
815                 mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
816         adjacentRootTask.mCreatedByOrganizer = true;
817         final Task candidateTask = createTaskInRootTask(rootTask, 0 /* userId*/);
818         final TaskDisplayArea taskDisplayArea = rootTask.getDisplayArea();
819         adjacentRootTask.setAdjacentTaskFragment(rootTask);
820 
821         // Verify the launch root with candidate task
822         Task actualRootTask = taskDisplayArea.getLaunchRootTask(WINDOWING_MODE_UNDEFINED,
823                 ACTIVITY_TYPE_STANDARD, null /* options */, adjacentRootTask /* sourceTask */,
824                 0 /* launchFlags */, candidateTask);
825         assertSame(rootTask, actualRootTask);
826 
827         // Verify the launch root task without candidate task
828         actualRootTask = taskDisplayArea.getLaunchRootTask(WINDOWING_MODE_UNDEFINED,
829                 ACTIVITY_TYPE_STANDARD, null /* options */, adjacentRootTask /* sourceTask */,
830                 0 /* launchFlags */);
831         assertSame(adjacentRootTask, actualRootTask);
832 
833         final Task pinnedTask = createTask(
834                 mDisplayContent, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
835         // Verify not adjusting launch target for pinned candidate task
836         actualRootTask = taskDisplayArea.getLaunchRootTask(WINDOWING_MODE_UNDEFINED,
837                 ACTIVITY_TYPE_STANDARD, null /* options */, adjacentRootTask /* sourceTask */,
838                 0 /* launchFlags */, pinnedTask /* candidateTask */);
839         assertNull(actualRootTask);
840     }
841 }
842