• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.AppOpsManager.OP_NONE;
20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
23 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
24 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
25 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
26 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
27 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
28 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
29 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
30 import static android.os.Process.SYSTEM_UID;
31 import static android.view.View.VISIBLE;
32 import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
33 import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
34 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
35 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
36 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
37 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
38 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
39 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
40 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
41 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
42 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
43 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
44 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
45 import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
46 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
47 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
48 
49 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
50 
51 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
52 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
53 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
54 import static com.android.server.wm.StartingSurfaceController.DEBUG_ENABLE_SHELL_DRAWER;
55 import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
56 import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
57 
58 import static org.junit.Assert.assertEquals;
59 import static org.junit.Assert.assertFalse;
60 import static org.mockito.ArgumentMatchers.any;
61 import static org.mockito.ArgumentMatchers.anyBoolean;
62 import static org.mockito.Mockito.mock;
63 
64 import android.annotation.IntDef;
65 import android.annotation.NonNull;
66 import android.app.ActivityManager;
67 import android.app.ActivityOptions;
68 import android.app.IApplicationThread;
69 import android.app.WindowConfiguration;
70 import android.content.ComponentName;
71 import android.content.Context;
72 import android.content.Intent;
73 import android.content.pm.ActivityInfo;
74 import android.content.pm.ApplicationInfo;
75 import android.graphics.Rect;
76 import android.hardware.display.DisplayManager;
77 import android.os.Build;
78 import android.os.Bundle;
79 import android.os.IBinder;
80 import android.os.RemoteException;
81 import android.os.UserHandle;
82 import android.service.voice.IVoiceInteractionSession;
83 import android.util.SparseArray;
84 import android.view.Display;
85 import android.view.DisplayInfo;
86 import android.view.IDisplayWindowInsetsController;
87 import android.view.IWindow;
88 import android.view.InsetsSourceControl;
89 import android.view.InsetsState;
90 import android.view.SurfaceControl;
91 import android.view.SurfaceControl.Transaction;
92 import android.view.View;
93 import android.view.WindowManager;
94 import android.view.WindowManager.DisplayImePolicy;
95 import android.window.ITransitionPlayer;
96 import android.window.StartingWindowInfo;
97 import android.window.TransitionInfo;
98 import android.window.TransitionRequestInfo;
99 
100 import com.android.internal.policy.AttributeCache;
101 import com.android.internal.util.ArrayUtils;
102 
103 import org.junit.After;
104 import org.junit.Before;
105 import org.junit.BeforeClass;
106 import org.junit.runner.Description;
107 import org.mockito.Mockito;
108 
109 import java.lang.annotation.ElementType;
110 import java.lang.annotation.Retention;
111 import java.lang.annotation.RetentionPolicy;
112 import java.lang.annotation.Target;
113 import java.util.HashMap;
114 
115 /** Common base class for window manager unit test classes. */
116 class WindowTestsBase extends SystemServiceTestsBase {
117     final Context mContext = getInstrumentation().getTargetContext();
118 
119     // Default package name
120     static final String DEFAULT_COMPONENT_PACKAGE_NAME = "com.foo";
121 
122     // Default base activity name
123     private static final String DEFAULT_COMPONENT_CLASS_NAME = ".BarActivity";
124 
125     ActivityTaskManagerService mAtm;
126     RootWindowContainer mRootWindowContainer;
127     ActivityTaskSupervisor mSupervisor;
128     WindowManagerService mWm;
129     private final IWindow mIWindow = new TestIWindow();
130     private Session mMockSession;
131 
132     DisplayInfo mDisplayInfo = new DisplayInfo();
133     DisplayContent mDefaultDisplay;
134 
135     /**
136      * It is {@link #mDefaultDisplay} by default. If the test class or method is annotated with
137      * {@link UseTestDisplay}, it will be an additional display.
138      */
139     DisplayContent mDisplayContent;
140 
141     // The following fields are only available depending on the usage of annotation UseTestDisplay.
142     WindowState mWallpaperWindow;
143     WindowState mImeWindow;
144     WindowState mImeDialogWindow;
145     WindowState mStatusBarWindow;
146     WindowState mNotificationShadeWindow;
147     WindowState mDockedDividerWindow;
148     WindowState mNavBarWindow;
149     WindowState mAppWindow;
150     WindowState mChildAppWindowAbove;
151     WindowState mChildAppWindowBelow;
152 
153     /**
154      * Spied {@link Transaction} class than can be used to verify calls.
155      */
156     Transaction mTransaction;
157 
158     /**
159      * Whether device-specific global overrides have already been checked in
160      * {@link WindowTestsBase#setUpBase()}.
161      */
162     private static boolean sGlobalOverridesChecked;
163     /**
164      * Whether device-specific overrides have already been checked in
165      * {@link WindowTestsBase#setUpBase()} when the default display is used.
166      */
167     private static boolean sOverridesCheckedDefaultDisplay;
168     /**
169      * Whether device-specific overrides have already been checked in
170      * {@link WindowTestsBase#setUpBase()} when a {@link TestDisplayContent} is used.
171      */
172     private static boolean sOverridesCheckedTestDisplay;
173 
174     @BeforeClass
setUpOnceBase()175     public static void setUpOnceBase() {
176         AttributeCache.init(getInstrumentation().getTargetContext());
177     }
178 
179     @Before
setUpBase()180     public void setUpBase() {
181         mAtm = mSystemServicesTestRule.getActivityTaskManagerService();
182         mSupervisor = mAtm.mTaskSupervisor;
183         mRootWindowContainer = mAtm.mRootWindowContainer;
184         mWm = mSystemServicesTestRule.getWindowManagerService();
185         SystemServicesTestRule.checkHoldsLock(mWm.mGlobalLock);
186 
187         mDefaultDisplay = mWm.mRoot.getDefaultDisplay();
188         mTransaction = mSystemServicesTestRule.mTransaction;
189         mMockSession = mock(Session.class);
190 
191         mContext.getSystemService(DisplayManager.class)
192                 .getDisplay(Display.DEFAULT_DISPLAY).getDisplayInfo(mDisplayInfo);
193 
194         // Only create an additional test display for annotated test class/method because it may
195         // significantly increase the execution time.
196         final Description description = mSystemServicesTestRule.getDescription();
197         UseTestDisplay testDisplayAnnotation = description.getAnnotation(UseTestDisplay.class);
198         if (testDisplayAnnotation == null) {
199             testDisplayAnnotation = description.getTestClass().getAnnotation(UseTestDisplay.class);
200         }
201         if (testDisplayAnnotation != null) {
202             createTestDisplay(testDisplayAnnotation);
203         } else {
204             mDisplayContent = mDefaultDisplay;
205         }
206 
207         // Ensure letterbox aspect ratio is not overridden on any device target.
208         // {@link com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio}, is set
209         // on some device form factors.
210         mAtm.mWindowManager.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(0);
211         // Ensure letterbox position multiplier is not overridden on any device target.
212         // {@link com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier},
213         // may be set on some device form factors.
214         mAtm.mWindowManager.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(0.5f);
215 
216         checkDeviceSpecificOverridesNotApplied();
217     }
218 
219     @After
tearDown()220     public void tearDown() throws Exception {
221         // Revert back to device overrides.
222         mAtm.mWindowManager.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(
223                 mContext.getResources().getFloat(
224                         com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio));
225         mAtm.mWindowManager.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(
226                 mContext.getResources().getFloat(
227                     com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier));
228     }
229 
230     /**
231      * Check that device-specific overrides are not applied. Only need to check once during entire
232      * test run for each case: global overrides, default display, and test display.
233      */
checkDeviceSpecificOverridesNotApplied()234     private void checkDeviceSpecificOverridesNotApplied() {
235         // Check global overrides
236         if (!sGlobalOverridesChecked) {
237             assertEquals(0, mWm.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio(),
238                     0 /* delta */);
239             sGlobalOverridesChecked = true;
240         }
241         // Check display-specific overrides
242         if (!sOverridesCheckedDefaultDisplay && mDisplayContent == mDefaultDisplay) {
243             assertFalse(mDisplayContent.getIgnoreOrientationRequest());
244             sOverridesCheckedDefaultDisplay = true;
245         } else if (!sOverridesCheckedTestDisplay && mDisplayContent instanceof TestDisplayContent) {
246             assertFalse(mDisplayContent.getIgnoreOrientationRequest());
247             sOverridesCheckedTestDisplay = true;
248         }
249     }
250 
createTestDisplay(UseTestDisplay annotation)251     private void createTestDisplay(UseTestDisplay annotation) {
252         beforeCreateTestDisplay();
253         mDisplayContent = createNewDisplayWithImeSupport(DISPLAY_IME_POLICY_LOCAL);
254 
255         final boolean addAll = annotation.addAllCommonWindows();
256         final @CommonTypes int[] requestedWindows = annotation.addWindows();
257 
258         if (addAll || ArrayUtils.contains(requestedWindows, W_WALLPAPER)) {
259             mWallpaperWindow = createCommonWindow(null, TYPE_WALLPAPER, "wallpaperWindow");
260         }
261         if (addAll || ArrayUtils.contains(requestedWindows, W_INPUT_METHOD)) {
262             mImeWindow = createCommonWindow(null, TYPE_INPUT_METHOD, "mImeWindow");
263             mDisplayContent.mInputMethodWindow = mImeWindow;
264         }
265         if (addAll || ArrayUtils.contains(requestedWindows, W_INPUT_METHOD_DIALOG)) {
266             mImeDialogWindow = createCommonWindow(null, TYPE_INPUT_METHOD_DIALOG,
267                     "mImeDialogWindow");
268         }
269         if (addAll || ArrayUtils.contains(requestedWindows, W_STATUS_BAR)) {
270             mStatusBarWindow = createCommonWindow(null, TYPE_STATUS_BAR, "mStatusBarWindow");
271         }
272         if (addAll || ArrayUtils.contains(requestedWindows, W_NOTIFICATION_SHADE)) {
273             mNotificationShadeWindow = createCommonWindow(null, TYPE_NOTIFICATION_SHADE,
274                     "mNotificationShadeWindow");
275         }
276         if (addAll || ArrayUtils.contains(requestedWindows, W_NAVIGATION_BAR)) {
277             mNavBarWindow = createCommonWindow(null, TYPE_NAVIGATION_BAR, "mNavBarWindow");
278         }
279         if (addAll || ArrayUtils.contains(requestedWindows, W_DOCK_DIVIDER)) {
280             mDockedDividerWindow = createCommonWindow(null, TYPE_DOCK_DIVIDER,
281                     "mDockedDividerWindow");
282         }
283         final boolean addAboveApp = ArrayUtils.contains(requestedWindows, W_ABOVE_ACTIVITY);
284         final boolean addBelowApp = ArrayUtils.contains(requestedWindows, W_BELOW_ACTIVITY);
285         if (addAll || addAboveApp || addBelowApp
286                 || ArrayUtils.contains(requestedWindows, W_ACTIVITY)) {
287             mAppWindow = createCommonWindow(null, TYPE_BASE_APPLICATION, "mAppWindow");
288         }
289         if (addAll || addAboveApp) {
290             mChildAppWindowAbove = createCommonWindow(mAppWindow, TYPE_APPLICATION_ATTACHED_DIALOG,
291                     "mChildAppWindowAbove");
292         }
293         if (addAll || addBelowApp) {
294             mChildAppWindowBelow = createCommonWindow(mAppWindow, TYPE_APPLICATION_MEDIA_OVERLAY,
295                     "mChildAppWindowBelow");
296         }
297 
298         mDisplayContent.getInsetsPolicy().setRemoteInsetsControllerControlsSystemBars(false);
299 
300         // Adding a display will cause freezing the display. Make sure to wait until it's
301         // unfrozen to not run into race conditions with the tests.
302         waitUntilHandlersIdle();
303     }
304 
beforeCreateTestDisplay()305     void beforeCreateTestDisplay() {
306         // Called before display is created.
307     }
308 
createCommonWindow(WindowState parent, int type, String name)309     private WindowState createCommonWindow(WindowState parent, int type, String name) {
310         final WindowState win = createWindow(parent, type, name);
311         // Prevent common windows from been IME targets.
312         win.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
313         return win;
314     }
315 
createWindowToken( DisplayContent dc, int windowingMode, int activityType, int type)316     private WindowToken createWindowToken(
317             DisplayContent dc, int windowingMode, int activityType, int type) {
318         if (type == TYPE_WALLPAPER) {
319             return createWallpaperToken(dc);
320         }
321         if (type < FIRST_APPLICATION_WINDOW || type > LAST_APPLICATION_WINDOW) {
322             return createTestWindowToken(type, dc);
323         }
324 
325         return createActivityRecord(dc, windowingMode, activityType);
326     }
327 
createWallpaperToken(DisplayContent dc)328     private WindowToken createWallpaperToken(DisplayContent dc) {
329         return new WallpaperWindowToken(mWm, mock(IBinder.class), true /* explicit */, dc,
330                 true /* ownerCanManageAppTokens */);
331     }
332 
createAppWindow(Task task, int type, String name)333     WindowState createAppWindow(Task task, int type, String name) {
334         final ActivityRecord activity = createNonAttachedActivityRecord(task.getDisplayContent());
335         task.addChild(activity, 0);
336         return createWindow(null, type, activity, name);
337     }
338 
339     // TODO: Move these calls to a builder?
createWindow(WindowState parent, int type, DisplayContent dc, String name, IWindow iwindow)340     WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name,
341             IWindow iwindow) {
342         final WindowToken token = createWindowToken(
343                 dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type);
344         return createWindow(parent, type, token, name, 0 /* ownerId */,
345                 false /* ownerCanAddInternalSystemWindow */, iwindow);
346     }
347 
createWindow(WindowState parent, int type, String name)348     WindowState createWindow(WindowState parent, int type, String name) {
349         return (parent == null)
350                 ? createWindow(parent, type, mDisplayContent, name)
351                 : createWindow(parent, type, parent.mToken, name);
352     }
353 
createWindow(WindowState parent, int type, String name, int ownerId)354     WindowState createWindow(WindowState parent, int type, String name, int ownerId) {
355         return (parent == null)
356                 ? createWindow(parent, type, mDisplayContent, name, ownerId)
357                 : createWindow(parent, type, parent.mToken, name, ownerId);
358     }
359 
createWindow(WindowState parent, int windowingMode, int activityType, int type, DisplayContent dc, String name)360     WindowState createWindow(WindowState parent, int windowingMode, int activityType,
361             int type, DisplayContent dc, String name) {
362         final WindowToken token = createWindowToken(dc, windowingMode, activityType, type);
363         return createWindow(parent, type, token, name);
364     }
365 
createWindow(WindowState parent, int type, DisplayContent dc, String name)366     WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name) {
367         return createWindow(
368                 parent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type, dc, name);
369     }
370 
createWindow(WindowState parent, int type, DisplayContent dc, String name, int ownerId)371     WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name,
372             int ownerId) {
373         final WindowToken token = createWindowToken(
374                 dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type);
375         return createWindow(parent, type, token, name, ownerId);
376     }
377 
createWindow(WindowState parent, int type, DisplayContent dc, String name, boolean ownerCanAddInternalSystemWindow)378     WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name,
379             boolean ownerCanAddInternalSystemWindow) {
380         final WindowToken token = createWindowToken(
381                 dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type);
382         return createWindow(parent, type, token, name, 0 /* ownerId */,
383                 ownerCanAddInternalSystemWindow);
384     }
385 
createWindow(WindowState parent, int type, WindowToken token, String name)386     WindowState createWindow(WindowState parent, int type, WindowToken token, String name) {
387         return createWindow(parent, type, token, name, 0 /* ownerId */,
388                 false /* ownerCanAddInternalSystemWindow */);
389     }
390 
createWindow(WindowState parent, int type, WindowToken token, String name, int ownerId)391     WindowState createWindow(WindowState parent, int type, WindowToken token, String name,
392             int ownerId) {
393         return createWindow(parent, type, token, name, ownerId,
394                 false /* ownerCanAddInternalSystemWindow */);
395     }
396 
createWindow(WindowState parent, int type, WindowToken token, String name, int ownerId, boolean ownerCanAddInternalSystemWindow)397     WindowState createWindow(WindowState parent, int type, WindowToken token, String name,
398             int ownerId, boolean ownerCanAddInternalSystemWindow) {
399         return createWindow(parent, type, token, name, ownerId, ownerCanAddInternalSystemWindow,
400                 mIWindow);
401     }
402 
createWindow(WindowState parent, int type, WindowToken token, String name, int ownerId, boolean ownerCanAddInternalSystemWindow, IWindow iwindow)403     WindowState createWindow(WindowState parent, int type, WindowToken token, String name,
404             int ownerId, boolean ownerCanAddInternalSystemWindow, IWindow iwindow) {
405         return createWindow(parent, type, token, name, ownerId, UserHandle.getUserId(ownerId),
406                 ownerCanAddInternalSystemWindow, mWm, mMockSession, iwindow,
407                 mSystemServicesTestRule.getPowerManagerWrapper());
408     }
409 
createWindow(WindowState parent, int type, WindowToken token, String name, int ownerId, int userId, boolean ownerCanAddInternalSystemWindow, WindowManagerService service, Session session, IWindow iWindow, WindowState.PowerManagerWrapper powerManagerWrapper)410     static WindowState createWindow(WindowState parent, int type, WindowToken token,
411             String name, int ownerId, int userId, boolean ownerCanAddInternalSystemWindow,
412             WindowManagerService service, Session session, IWindow iWindow,
413             WindowState.PowerManagerWrapper powerManagerWrapper) {
414         SystemServicesTestRule.checkHoldsLock(service.mGlobalLock);
415 
416         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
417         attrs.setTitle(name);
418         attrs.packageName = "test";
419 
420         final WindowState w = new WindowState(service, session, iWindow, token, parent,
421                 OP_NONE, attrs, VISIBLE, ownerId, userId,
422                 ownerCanAddInternalSystemWindow,
423                 powerManagerWrapper);
424         // TODO: Probably better to make this call in the WindowState ctor to avoid errors with
425         // adding it to the token...
426         token.addWindow(w);
427         return w;
428     }
429 
makeWindowVisible(WindowState... windows)430     static void makeWindowVisible(WindowState... windows) {
431         for (WindowState win : windows) {
432             win.mViewVisibility = View.VISIBLE;
433             win.mRelayoutCalled = true;
434             win.mHasSurface = true;
435             win.mHidden = false;
436             win.show(false /* doAnimation */, false /* requestAnim */);
437         }
438     }
439 
makeWindowVisibleAndDrawn(WindowState... windows)440     static void makeWindowVisibleAndDrawn(WindowState... windows) {
441         makeWindowVisible(windows);
442         for (WindowState win : windows) {
443             win.mWinAnimator.mDrawState = HAS_DRAWN;
444         }
445     }
446 
447     /**
448      * Gets the order of the given {@link Task} as its z-order in the hierarchy below this TDA.
449      * The Task can be a direct child of a child TaskDisplayArea. {@code -1} if not found.
450      */
getTaskIndexOf(TaskDisplayArea taskDisplayArea, Task task)451     static int getTaskIndexOf(TaskDisplayArea taskDisplayArea, Task task) {
452         int index = 0;
453         final int childCount = taskDisplayArea.getChildCount();
454         for (int i = 0; i < childCount; i++) {
455             final WindowContainer wc = taskDisplayArea.getChildAt(i);
456             if (wc.asTask() != null) {
457                 if (wc.asTask() == task) {
458                     return index;
459                 }
460                 index++;
461             } else {
462                 final TaskDisplayArea tda = wc.asTaskDisplayArea();
463                 final int subIndex = getTaskIndexOf(tda, task);
464                 if (subIndex > -1) {
465                     return index + subIndex;
466                 } else {
467                     index += tda.getRootTaskCount();
468                 }
469             }
470         }
471         return -1;
472     }
473 
474     /** Creates a {@link TaskDisplayArea} right above the default one. */
createTaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name, int displayAreaFeature)475     static TaskDisplayArea createTaskDisplayArea(DisplayContent displayContent,
476             WindowManagerService service, String name, int displayAreaFeature) {
477         final TaskDisplayArea newTaskDisplayArea = new TaskDisplayArea(
478                 displayContent, service, name, displayAreaFeature);
479         final TaskDisplayArea defaultTaskDisplayArea = displayContent.getDefaultTaskDisplayArea();
480 
481         // Insert the new TDA to the correct position.
482         defaultTaskDisplayArea.getParent().addChild(newTaskDisplayArea,
483                 defaultTaskDisplayArea.getParent().mChildren.indexOf(defaultTaskDisplayArea)
484                         + 1);
485         return newTaskDisplayArea;
486     }
487 
488     /**
489      *  Creates a {@link Task} with a simple {@link ActivityRecord} and adds to the given
490      *  {@link TaskDisplayArea}.
491      */
createTaskWithActivity(TaskDisplayArea taskDisplayArea, int windowingMode, int activityType, boolean onTop, boolean twoLevelTask)492     Task createTaskWithActivity(TaskDisplayArea taskDisplayArea,
493             int windowingMode, int activityType, boolean onTop, boolean twoLevelTask) {
494         return createTask(taskDisplayArea, windowingMode, activityType,
495                 onTop, true /* createActivity */, twoLevelTask);
496     }
497 
498     /** Creates a {@link Task} and adds to the given {@link DisplayContent}. */
createTask(DisplayContent dc)499     Task createTask(DisplayContent dc) {
500         return createTask(dc.getDefaultTaskDisplayArea(),
501                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
502     }
503 
createTask(DisplayContent dc, int windowingMode, int activityType)504     Task createTask(DisplayContent dc, int windowingMode, int activityType) {
505         return createTask(dc.getDefaultTaskDisplayArea(), windowingMode, activityType);
506     }
507 
createTask(TaskDisplayArea taskDisplayArea, int windowingMode, int activityType)508     Task createTask(TaskDisplayArea taskDisplayArea, int windowingMode, int activityType) {
509         return createTask(taskDisplayArea, windowingMode, activityType,
510                 true /* onTop */, false /* createActivity */, false /* twoLevelTask */);
511     }
512 
513     /** Creates a {@link Task} and adds to the given {@link TaskDisplayArea}. */
createTask(TaskDisplayArea taskDisplayArea, int windowingMode, int activityType, boolean onTop, boolean createActivity, boolean twoLevelTask)514     Task createTask(TaskDisplayArea taskDisplayArea, int windowingMode, int activityType,
515             boolean onTop, boolean createActivity, boolean twoLevelTask) {
516         final TaskBuilder builder = new TaskBuilder(mSupervisor)
517                 .setTaskDisplayArea(taskDisplayArea)
518                 .setWindowingMode(windowingMode)
519                 .setActivityType(activityType)
520                 .setOnTop(onTop)
521                 .setCreateActivity(createActivity);
522         if (twoLevelTask) {
523             return builder
524                     .setCreateParentTask(true)
525                     .build()
526                     .getRootTask();
527         } else {
528             return builder.build();
529         }
530     }
531 
532     /** Creates a {@link Task} and adds to the given root {@link Task}. */
createTaskInRootTask(Task rootTask, int userId)533     Task createTaskInRootTask(Task rootTask, int userId) {
534         final Task task = new TaskBuilder(rootTask.mTaskSupervisor)
535                 .setUserId(userId)
536                 .setParentTask(rootTask)
537                 .build();
538         return task;
539     }
540 
541     /** Creates an {@link ActivityRecord}. */
createNonAttachedActivityRecord(DisplayContent dc)542     static ActivityRecord createNonAttachedActivityRecord(DisplayContent dc) {
543         final ActivityRecord activity = new ActivityBuilder(dc.mWmService.mAtmService)
544                 .setOnTop(true)
545                 .build();
546         postCreateActivitySetup(activity, dc);
547         return activity;
548     }
549 
550     /**
551      * Creates an {@link ActivityRecord} and adds it to a new created {@link Task}.
552      * [Task] - [ActivityRecord]
553      */
createActivityRecord(DisplayContent dc)554     ActivityRecord createActivityRecord(DisplayContent dc) {
555         return createActivityRecord(dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
556     }
557 
558     /**
559      * Creates an {@link ActivityRecord} and adds it to a new created {@link Task}.
560      * [Task] - [ActivityRecord]
561      */
createActivityRecord(DisplayContent dc, int windowingMode, int activityType)562     ActivityRecord createActivityRecord(DisplayContent dc, int windowingMode,
563             int activityType) {
564         final Task task = createTask(dc, windowingMode, activityType);
565         return createActivityRecord(dc, task);
566     }
567 
568     /**
569      *  Creates an {@link ActivityRecord} and adds it to the specified {@link Task}.
570      * [Task] - [ActivityRecord]
571      */
createActivityRecord(Task task)572     static ActivityRecord createActivityRecord(Task task) {
573         return createActivityRecord(task.getDisplayContent(), task);
574     }
575 
576     /**
577      * Creates an {@link ActivityRecord} and adds it to the specified {@link Task}.
578      * [Task] - [ActivityRecord]
579      */
createActivityRecord(DisplayContent dc, Task task)580     static ActivityRecord createActivityRecord(DisplayContent dc, Task task) {
581         final ActivityRecord activity = new ActivityBuilder(dc.mWmService.mAtmService)
582                 .setTask(task)
583                 .setOnTop(true)
584                 .build();
585         postCreateActivitySetup(activity, dc);
586         return activity;
587     }
588 
589     /**
590      * Creates an {@link ActivityRecord} and adds it to a new created {@link Task}.
591      * Then adds the new created {@link Task} to a new created parent {@link Task}
592      * [Task1] - [Task2] - [ActivityRecord]
593      */
createActivityRecordWithParentTask(DisplayContent dc, int windowingMode, int activityType)594     ActivityRecord createActivityRecordWithParentTask(DisplayContent dc, int windowingMode,
595             int activityType) {
596         final Task task = createTask(dc, windowingMode, activityType);
597         return createActivityRecordWithParentTask(task);
598     }
599 
600     /**
601      * Creates an {@link ActivityRecord} and adds it to a new created {@link Task}.
602      * Then adds the new created {@link Task} to the specified parent {@link Task}
603      * [Task1] - [Task2] - [ActivityRecord]
604      */
createActivityRecordWithParentTask(Task parentTask)605     static ActivityRecord createActivityRecordWithParentTask(Task parentTask) {
606         final ActivityRecord activity = new ActivityBuilder(parentTask.mAtmService)
607                 .setParentTask(parentTask)
608                 .setCreateTask(true)
609                 .setOnTop(true)
610                 .build();
611         postCreateActivitySetup(activity, parentTask.getDisplayContent());
612         return activity;
613     }
614 
postCreateActivitySetup(ActivityRecord activity, DisplayContent dc)615     private static void postCreateActivitySetup(ActivityRecord activity, DisplayContent dc) {
616         activity.onDisplayChanged(dc);
617         activity.setOccludesParent(true);
618         activity.setVisible(true);
619         activity.mVisibleRequested = true;
620     }
621 
622     /** Creates a {@link DisplayContent} that supports IME and adds it to the system. */
createNewDisplay()623     DisplayContent createNewDisplay() {
624         return createNewDisplayWithImeSupport(DISPLAY_IME_POLICY_LOCAL);
625     }
626 
627     /** Creates a {@link DisplayContent} and adds it to the system. */
createNewDisplayWithImeSupport(@isplayImePolicy int imePolicy)628     private DisplayContent createNewDisplayWithImeSupport(@DisplayImePolicy int imePolicy) {
629         return createNewDisplay(mDisplayInfo, imePolicy);
630     }
631 
632     /** Creates a {@link DisplayContent} that supports IME and adds it to the system. */
createNewDisplay(DisplayInfo info)633     DisplayContent createNewDisplay(DisplayInfo info) {
634         return createNewDisplay(info, DISPLAY_IME_POLICY_LOCAL);
635     }
636 
637     /** Creates a {@link DisplayContent} and adds it to the system. */
createNewDisplay(DisplayInfo info, @DisplayImePolicy int imePolicy)638     private DisplayContent createNewDisplay(DisplayInfo info, @DisplayImePolicy int imePolicy) {
639         final DisplayContent display =
640                 new TestDisplayContent.Builder(mAtm, info).build();
641         final DisplayContent dc = display.mDisplayContent;
642         // this display can show IME.
643         dc.mWmService.mDisplayWindowSettings.setDisplayImePolicy(dc, imePolicy);
644         return dc;
645     }
646 
647     /**
648      * Creates a {@link DisplayContent} with given display state and adds it to the system.
649      *
650      * @param displayState For initializing the state of the display. See
651      *                     {@link Display#getState()}.
652      */
createNewDisplay(int displayState)653     DisplayContent createNewDisplay(int displayState) {
654         // Leverage main display info & initialize it with display state for given displayId.
655         DisplayInfo displayInfo = new DisplayInfo();
656         displayInfo.copyFrom(mDisplayInfo);
657         displayInfo.state = displayState;
658         return createNewDisplay(displayInfo, DISPLAY_IME_POLICY_LOCAL);
659     }
660 
661     /** Creates a {@link TestWindowState} */
createWindowState(WindowManager.LayoutParams attrs, WindowToken token)662     TestWindowState createWindowState(WindowManager.LayoutParams attrs, WindowToken token) {
663         SystemServicesTestRule.checkHoldsLock(mWm.mGlobalLock);
664 
665         return new TestWindowState(mWm, mMockSession, mIWindow, attrs, token);
666     }
667 
668     /** Creates a {@link DisplayContent} as parts of simulate display info for test. */
createMockSimulatedDisplay()669     DisplayContent createMockSimulatedDisplay() {
670         DisplayInfo displayInfo = new DisplayInfo();
671         displayInfo.copyFrom(mDisplayInfo);
672         displayInfo.type = Display.TYPE_VIRTUAL;
673         displayInfo.ownerUid = SYSTEM_UID;
674         return createNewDisplay(displayInfo, DISPLAY_IME_POLICY_FALLBACK_DISPLAY);
675     }
676 
createDisplayWindowInsetsController()677     IDisplayWindowInsetsController createDisplayWindowInsetsController() {
678         return new IDisplayWindowInsetsController.Stub() {
679 
680             @Override
681             public void insetsChanged(InsetsState insetsState) throws RemoteException {
682             }
683 
684             @Override
685             public void insetsControlChanged(InsetsState insetsState,
686                     InsetsSourceControl[] insetsSourceControls) throws RemoteException {
687             }
688 
689             @Override
690             public void showInsets(int i, boolean b) throws RemoteException {
691             }
692 
693             @Override
694             public void hideInsets(int i, boolean b) throws RemoteException {
695             }
696 
697             @Override
698             public void topFocusedWindowChanged(String packageName) {
699             }
700         };
701     }
702 
703     /**
704      * Avoids rotating screen disturbed by some conditions. It is usually used for the default
705      * display that is not the instance of {@link TestDisplayContent} (it bypasses the conditions).
706      *
707      * @see DisplayRotation#updateRotationUnchecked
708      */
unblockDisplayRotation(DisplayContent dc)709     void unblockDisplayRotation(DisplayContent dc) {
710         mWm.stopFreezingDisplayLocked();
711         // The rotation animation won't actually play, it needs to be cleared manually.
712         dc.setRotationAnimation(null);
713     }
714 
715     // The window definition for UseTestDisplay#addWindows. The test can declare to add only
716     // necessary windows, that avoids adding unnecessary overhead of unused windows.
717     static final int W_NOTIFICATION_SHADE = TYPE_NOTIFICATION_SHADE;
718     static final int W_STATUS_BAR = TYPE_STATUS_BAR;
719     static final int W_NAVIGATION_BAR = TYPE_NAVIGATION_BAR;
720     static final int W_INPUT_METHOD_DIALOG = TYPE_INPUT_METHOD_DIALOG;
721     static final int W_INPUT_METHOD = TYPE_INPUT_METHOD;
722     static final int W_DOCK_DIVIDER = TYPE_DOCK_DIVIDER;
723     static final int W_ABOVE_ACTIVITY = TYPE_APPLICATION_ATTACHED_DIALOG;
724     static final int W_ACTIVITY = TYPE_BASE_APPLICATION;
725     static final int W_BELOW_ACTIVITY = TYPE_APPLICATION_MEDIA_OVERLAY;
726     static final int W_WALLPAPER = TYPE_WALLPAPER;
727 
728     /** The common window types supported by {@link UseTestDisplay}. */
729     @Retention(RetentionPolicy.RUNTIME)
730     @IntDef(value = {
731             W_NOTIFICATION_SHADE,
732             W_STATUS_BAR,
733             W_NAVIGATION_BAR,
734             W_INPUT_METHOD_DIALOG,
735             W_INPUT_METHOD,
736             W_DOCK_DIVIDER,
737             W_ABOVE_ACTIVITY,
738             W_ACTIVITY,
739             W_BELOW_ACTIVITY,
740             W_WALLPAPER,
741     })
742     @interface CommonTypes {
743     }
744 
745     /**
746      * The annotation for class and method (higher priority) to create a non-default display that
747      * will be assigned to {@link #mDisplayContent}. It is used if the test needs
748      * <ul>
749      * <li>Pure empty display.</li>
750      * <li>Configured common windows.</li>
751      * <li>Independent and customizable orientation.</li>
752      * <li>Cross display operation.</li>
753      * </ul>
754      *
755      * @see TestDisplayContent
756      * @see #createTestDisplay
757      **/
758     @Target({ ElementType.METHOD, ElementType.TYPE })
759     @Retention(RetentionPolicy.RUNTIME)
760     @interface UseTestDisplay {
addAllCommonWindows()761         boolean addAllCommonWindows() default false;
addWindows()762         @CommonTypes int[] addWindows() default {};
763     }
764 
765     /** Creates and adds a {@link TestDisplayContent} to supervisor at the given position. */
addNewDisplayContentAt(int position)766     TestDisplayContent addNewDisplayContentAt(int position) {
767         return new TestDisplayContent.Builder(mAtm, 1000, 1500).setPosition(position).build();
768     }
769 
770     /** Sets the default minimum task size to 1 so that tests can use small task sizes */
removeGlobalMinSizeRestriction()771     public void removeGlobalMinSizeRestriction() {
772         mAtm.mRootWindowContainer.mDefaultMinSizeOfResizeableTaskDp = 1;
773     }
774 
775     /**
776      * Builder for creating new activities.
777      */
778     protected static class ActivityBuilder {
779         static final int DEFAULT_FAKE_UID = 12345;
780         // An id appended to the end of the component name to make it unique
781         private static int sCurrentActivityId = 0;
782 
783         private final ActivityTaskManagerService mService;
784 
785         private ComponentName mComponent;
786         private String mTargetActivity;
787         private Task mTask;
788         private String mProcessName = "name";
789         private String mAffinity;
790         private int mUid = DEFAULT_FAKE_UID;
791         private boolean mCreateTask = false;
792         private Task mParentTask;
793         private int mActivityFlags;
794         private int mLaunchMode;
795         private int mResizeMode = RESIZE_MODE_RESIZEABLE;
796         private float mMaxAspectRatio;
797         private float mMinAspectRatio;
798         private boolean mSupportsSizeChanges;
799         private int mScreenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
800         private boolean mLaunchTaskBehind = false;
801         private int mConfigChanges;
802         private int mLaunchedFromPid;
803         private int mLaunchedFromUid;
804         private WindowProcessController mWpc;
805         private Bundle mIntentExtras;
806         private boolean mOnTop = false;
807         private ActivityInfo.WindowLayout mWindowLayout;
808         private boolean mVisible = true;
809 
ActivityBuilder(ActivityTaskManagerService service)810         ActivityBuilder(ActivityTaskManagerService service) {
811             mService = service;
812         }
813 
setComponent(ComponentName component)814         ActivityBuilder setComponent(ComponentName component) {
815             mComponent = component;
816             return this;
817         }
818 
setTargetActivity(String targetActivity)819         ActivityBuilder setTargetActivity(String targetActivity) {
820             mTargetActivity = targetActivity;
821             return this;
822         }
823 
setIntentExtras(Bundle extras)824         ActivityBuilder setIntentExtras(Bundle extras) {
825             mIntentExtras = extras;
826             return this;
827         }
828 
getDefaultComponent()829         static ComponentName getDefaultComponent() {
830             return ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME,
831                     DEFAULT_COMPONENT_PACKAGE_NAME);
832         }
833 
setTask(Task task)834         ActivityBuilder setTask(Task task) {
835             mTask = task;
836             return this;
837         }
838 
setActivityFlags(int flags)839         ActivityBuilder setActivityFlags(int flags) {
840             mActivityFlags = flags;
841             return this;
842         }
843 
setLaunchMode(int launchMode)844         ActivityBuilder setLaunchMode(int launchMode) {
845             mLaunchMode = launchMode;
846             return this;
847         }
848 
setParentTask(Task parentTask)849         ActivityBuilder setParentTask(Task parentTask) {
850             mParentTask = parentTask;
851             return this;
852         }
853 
setCreateTask(boolean createTask)854         ActivityBuilder setCreateTask(boolean createTask) {
855             mCreateTask = createTask;
856             return this;
857         }
858 
setProcessName(String name)859         ActivityBuilder setProcessName(String name) {
860             mProcessName = name;
861             return this;
862         }
863 
setUid(int uid)864         ActivityBuilder setUid(int uid) {
865             mUid = uid;
866             return this;
867         }
868 
setResizeMode(int resizeMode)869         ActivityBuilder setResizeMode(int resizeMode) {
870             mResizeMode = resizeMode;
871             return this;
872         }
873 
setMaxAspectRatio(float maxAspectRatio)874         ActivityBuilder setMaxAspectRatio(float maxAspectRatio) {
875             mMaxAspectRatio = maxAspectRatio;
876             return this;
877         }
878 
setMinAspectRatio(float minAspectRatio)879         ActivityBuilder setMinAspectRatio(float minAspectRatio) {
880             mMinAspectRatio = minAspectRatio;
881             return this;
882         }
883 
setSupportsSizeChanges(boolean supportsSizeChanges)884         ActivityBuilder setSupportsSizeChanges(boolean supportsSizeChanges) {
885             mSupportsSizeChanges = supportsSizeChanges;
886             return this;
887         }
888 
setScreenOrientation(int screenOrientation)889         ActivityBuilder setScreenOrientation(int screenOrientation) {
890             mScreenOrientation = screenOrientation;
891             return this;
892         }
893 
setLaunchTaskBehind(boolean launchTaskBehind)894         ActivityBuilder setLaunchTaskBehind(boolean launchTaskBehind) {
895             mLaunchTaskBehind = launchTaskBehind;
896             return this;
897         }
898 
setConfigChanges(int configChanges)899         ActivityBuilder setConfigChanges(int configChanges) {
900             mConfigChanges = configChanges;
901             return this;
902         }
903 
setLaunchedFromPid(int pid)904         ActivityBuilder setLaunchedFromPid(int pid) {
905             mLaunchedFromPid = pid;
906             return this;
907         }
908 
setLaunchedFromUid(int uid)909         ActivityBuilder setLaunchedFromUid(int uid) {
910             mLaunchedFromUid = uid;
911             return this;
912         }
913 
setUseProcess(WindowProcessController wpc)914         ActivityBuilder setUseProcess(WindowProcessController wpc) {
915             mWpc = wpc;
916             return this;
917         }
918 
setAffinity(String affinity)919         ActivityBuilder setAffinity(String affinity) {
920             mAffinity = affinity;
921             return this;
922         }
923 
setOnTop(boolean onTop)924         ActivityBuilder setOnTop(boolean onTop) {
925             mOnTop = onTop;
926             return this;
927         }
928 
setWindowLayout(ActivityInfo.WindowLayout windowLayout)929         ActivityBuilder setWindowLayout(ActivityInfo.WindowLayout windowLayout) {
930             mWindowLayout = windowLayout;
931             return this;
932         }
933 
setVisible(boolean visible)934         ActivityBuilder setVisible(boolean visible) {
935             mVisible = visible;
936             return this;
937         }
938 
build()939         ActivityRecord build() {
940             SystemServicesTestRule.checkHoldsLock(mService.mGlobalLock);
941             try {
942                 mService.deferWindowLayout();
943                 return buildInner();
944             } finally {
945                 mService.continueWindowLayout();
946             }
947         }
948 
buildInner()949         ActivityRecord buildInner() {
950             if (mComponent == null) {
951                 final int id = sCurrentActivityId++;
952                 mComponent = ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME,
953                         DEFAULT_COMPONENT_CLASS_NAME + id);
954             }
955 
956             Intent intent = new Intent();
957             intent.setComponent(mComponent);
958             if (mIntentExtras != null) {
959                 intent.putExtras(mIntentExtras);
960             }
961             final ActivityInfo aInfo = new ActivityInfo();
962             aInfo.applicationInfo = new ApplicationInfo();
963             aInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
964             aInfo.applicationInfo.packageName = mComponent.getPackageName();
965             aInfo.applicationInfo.uid = mUid;
966             aInfo.processName = mProcessName;
967             aInfo.packageName = mComponent.getPackageName();
968             aInfo.name = mComponent.getClassName();
969             if (mTargetActivity != null) {
970                 aInfo.targetActivity = mTargetActivity;
971             }
972             aInfo.flags |= mActivityFlags;
973             aInfo.launchMode = mLaunchMode;
974             aInfo.resizeMode = mResizeMode;
975             aInfo.setMaxAspectRatio(mMaxAspectRatio);
976             aInfo.setMinAspectRatio(mMinAspectRatio);
977             aInfo.supportsSizeChanges = mSupportsSizeChanges;
978             aInfo.screenOrientation = mScreenOrientation;
979             aInfo.configChanges |= mConfigChanges;
980             aInfo.taskAffinity = mAffinity;
981             aInfo.windowLayout = mWindowLayout;
982 
983             if (mCreateTask) {
984                 mTask = new TaskBuilder(mService.mTaskSupervisor)
985                         .setComponent(mComponent)
986                         // Apply the root activity info and intent
987                         .setActivityInfo(aInfo)
988                         .setIntent(intent)
989                         .setParentTask(mParentTask).build();
990             } else if (mTask == null && mParentTask != null && DisplayContent.alwaysCreateRootTask(
991                     mParentTask.getWindowingMode(), mParentTask.getActivityType())) {
992                 // The parent task can be the task root.
993                 mTask = mParentTask;
994             }
995 
996             ActivityOptions options = null;
997             if (mLaunchTaskBehind) {
998                 options = ActivityOptions.makeTaskLaunchBehind();
999             }
1000             final ActivityRecord activity = new ActivityRecord.Builder(mService)
1001                     .setLaunchedFromPid(mLaunchedFromPid)
1002                     .setLaunchedFromUid(mLaunchedFromUid)
1003                     .setIntent(intent)
1004                     .setActivityInfo(aInfo)
1005                     .setActivityOptions(options)
1006                     .build();
1007 
1008             spyOn(activity);
1009             if (mTask != null) {
1010                 // fullscreen value is normally read from resources in ctor, so for testing we need
1011                 // to set it somewhere else since we can't mock resources.
1012                 doReturn(true).when(activity).occludesParent();
1013                 doReturn(true).when(activity).fillsParent();
1014                 mTask.addChild(activity);
1015                 if (mOnTop) {
1016                     // Move the task to front after activity is added.
1017                     // Or {@link TaskDisplayArea#mPreferredTopFocusableRootTask} could be other
1018                     // root tasks (e.g. home root task).
1019                     mTask.moveToFront("createActivity");
1020                 }
1021                 if (mVisible) {
1022                     activity.mVisibleRequested = true;
1023                     activity.setVisible(true);
1024                 }
1025             }
1026 
1027             final WindowProcessController wpc;
1028             if (mWpc != null) {
1029                 wpc = mWpc;
1030             } else {
1031                 wpc = new WindowProcessController(mService,
1032                         aInfo.applicationInfo, mProcessName, mUid,
1033                         UserHandle.getUserId(mUid), mock(Object.class),
1034                         mock(WindowProcessListener.class));
1035                 wpc.setThread(mock(IApplicationThread.class));
1036             }
1037             wpc.setThread(mock(IApplicationThread.class));
1038             activity.setProcess(wpc);
1039             doReturn(wpc).when(mService).getProcessController(
1040                     activity.processName, activity.info.applicationInfo.uid);
1041 
1042             // Resume top activities to make sure all other signals in the system are connected.
1043             mService.mRootWindowContainer.resumeFocusedTasksTopActivities();
1044             return activity;
1045         }
1046     }
1047 
1048     /**
1049      * Builder for creating new tasks.
1050      */
1051     protected static class TaskBuilder {
1052         private final ActivityTaskSupervisor mSupervisor;
1053 
1054         private TaskDisplayArea mTaskDisplayArea;
1055         private ComponentName mComponent;
1056         private String mPackage;
1057         private int mFlags = 0;
1058         private int mTaskId = -1;
1059         private int mUserId = 0;
1060         private int mWindowingMode = WINDOWING_MODE_UNDEFINED;
1061         private int mActivityType = ACTIVITY_TYPE_STANDARD;
1062         private ActivityInfo mActivityInfo;
1063         private Intent mIntent;
1064         private boolean mOnTop = true;
1065         private IVoiceInteractionSession mVoiceSession;
1066 
1067         private boolean mCreateParentTask = false;
1068         private Task mParentTask;
1069 
1070         private boolean mCreateActivity = false;
1071 
TaskBuilder(ActivityTaskSupervisor supervisor)1072         TaskBuilder(ActivityTaskSupervisor supervisor) {
1073             mSupervisor = supervisor;
1074             mTaskDisplayArea = mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
1075         }
1076 
1077         /**
1078          * Set the parent {@link DisplayContent} and use the default task display area. Overrides
1079          * the task display area, if was set before.
1080          */
setDisplay(DisplayContent display)1081         TaskBuilder setDisplay(DisplayContent display) {
1082             mTaskDisplayArea = display.getDefaultTaskDisplayArea();
1083             return this;
1084         }
1085 
1086         /** Set the parent {@link TaskDisplayArea}. Overrides the display, if was set before. */
setTaskDisplayArea(TaskDisplayArea taskDisplayArea)1087         TaskBuilder setTaskDisplayArea(TaskDisplayArea taskDisplayArea) {
1088             mTaskDisplayArea = taskDisplayArea;
1089             return this;
1090         }
1091 
setComponent(ComponentName component)1092         TaskBuilder setComponent(ComponentName component) {
1093             mComponent = component;
1094             return this;
1095         }
1096 
setPackage(String packageName)1097         TaskBuilder setPackage(String packageName) {
1098             mPackage = packageName;
1099             return this;
1100         }
1101 
setFlags(int flags)1102         TaskBuilder setFlags(int flags) {
1103             mFlags = flags;
1104             return this;
1105         }
1106 
setTaskId(int taskId)1107         TaskBuilder setTaskId(int taskId) {
1108             mTaskId = taskId;
1109             return this;
1110         }
1111 
setUserId(int userId)1112         TaskBuilder setUserId(int userId) {
1113             mUserId = userId;
1114             return this;
1115         }
1116 
setWindowingMode(int windowingMode)1117         TaskBuilder setWindowingMode(int windowingMode) {
1118             mWindowingMode = windowingMode;
1119             return this;
1120         }
1121 
setActivityType(int activityType)1122         TaskBuilder setActivityType(int activityType) {
1123             mActivityType = activityType;
1124             return this;
1125         }
1126 
setActivityInfo(ActivityInfo info)1127         TaskBuilder setActivityInfo(ActivityInfo info) {
1128             mActivityInfo = info;
1129             return this;
1130         }
1131 
setIntent(Intent intent)1132         TaskBuilder setIntent(Intent intent) {
1133             mIntent = intent;
1134             return this;
1135         }
1136 
setOnTop(boolean onTop)1137         TaskBuilder setOnTop(boolean onTop) {
1138             mOnTop = onTop;
1139             return this;
1140         }
1141 
setVoiceSession(IVoiceInteractionSession session)1142         TaskBuilder setVoiceSession(IVoiceInteractionSession session) {
1143             mVoiceSession = session;
1144             return this;
1145         }
1146 
setCreateParentTask(boolean createParentTask)1147         TaskBuilder setCreateParentTask(boolean createParentTask) {
1148             mCreateParentTask = createParentTask;
1149             return this;
1150         }
1151 
setParentTask(Task parentTask)1152         TaskBuilder setParentTask(Task parentTask) {
1153             mParentTask = parentTask;
1154             return this;
1155         }
1156 
setCreateActivity(boolean createActivity)1157         TaskBuilder setCreateActivity(boolean createActivity) {
1158             mCreateActivity = createActivity;
1159             return this;
1160         }
1161 
build()1162         Task build() {
1163             SystemServicesTestRule.checkHoldsLock(mSupervisor.mService.mGlobalLock);
1164 
1165             // Create parent task.
1166             if (mParentTask == null && mCreateParentTask) {
1167                 mParentTask = mTaskDisplayArea.createRootTask(
1168                         WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
1169             }
1170             if (mParentTask != null && !Mockito.mockingDetails(mParentTask).isSpy()) {
1171                 spyOn(mParentTask);
1172             }
1173 
1174             // Create task.
1175             if (mActivityInfo == null) {
1176                 mActivityInfo = new ActivityInfo();
1177                 mActivityInfo.applicationInfo = new ApplicationInfo();
1178                 mActivityInfo.applicationInfo.packageName = mPackage;
1179             }
1180 
1181             if (mIntent == null) {
1182                 mIntent = new Intent();
1183                 if (mComponent == null) {
1184                     mComponent = ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME,
1185                             DEFAULT_COMPONENT_CLASS_NAME);
1186                 }
1187                 mIntent.setComponent(mComponent);
1188                 mIntent.setFlags(mFlags);
1189             }
1190 
1191             final Task.Builder builder = new Task.Builder(mSupervisor.mService)
1192                     .setTaskId(mTaskId >= 0 ? mTaskId : mTaskDisplayArea.getNextRootTaskId())
1193                     .setWindowingMode(mWindowingMode)
1194                     .setActivityInfo(mActivityInfo)
1195                     .setIntent(mIntent)
1196                     .setOnTop(mOnTop)
1197                     .setVoiceSession(mVoiceSession);
1198             final Task task;
1199             if (mParentTask == null) {
1200                 task = builder.setActivityType(mActivityType)
1201                         .setParent(mTaskDisplayArea)
1202                         .build();
1203             } else {
1204                 task = builder.setParent(mParentTask).build();
1205                 mParentTask.moveToFront("build-task");
1206             }
1207             spyOn(task);
1208             task.mUserId = mUserId;
1209             final Task rootTask = task.getRootTask();
1210             if (task != rootTask && !Mockito.mockingDetails(rootTask).isSpy()) {
1211                 spyOn(rootTask);
1212             }
1213             doNothing().when(rootTask).startActivityLocked(
1214                     any(), any(), anyBoolean(), anyBoolean(), any(), any());
1215 
1216             // Create child task with activity.
1217             if (mCreateActivity) {
1218                 new ActivityBuilder(mSupervisor.mService)
1219                         .setTask(task)
1220                         .build();
1221                 if (mOnTop) {
1222                     // We move the task to front again in order to regain focus after activity
1223                     // is added. Or {@link TaskDisplayArea#mPreferredTopFocusableRootTask} could be
1224                     // other root tasks (e.g. home root task).
1225                     task.moveToFront("createActivityTask");
1226                 } else {
1227                     task.moveToBack("createActivityTask", null);
1228                 }
1229             }
1230 
1231             return task;
1232         }
1233     }
1234 
1235     static class TestStartingWindowOrganizer extends WindowOrganizerTests.StubOrganizer {
1236         private final ActivityTaskManagerService mAtm;
1237         private final WindowManagerService mWMService;
1238         private final WindowState.PowerManagerWrapper mPowerManagerWrapper;
1239 
1240         private Runnable mRunnableWhenAddingSplashScreen;
1241         private final SparseArray<IBinder> mTaskAppMap = new SparseArray<>();
1242         private final HashMap<IBinder, WindowState> mAppWindowMap = new HashMap<>();
1243 
TestStartingWindowOrganizer(ActivityTaskManagerService service, WindowState.PowerManagerWrapper powerManagerWrapper)1244         TestStartingWindowOrganizer(ActivityTaskManagerService service,
1245                 WindowState.PowerManagerWrapper powerManagerWrapper) {
1246             mAtm = service;
1247             mWMService = mAtm.mWindowManager;
1248             mPowerManagerWrapper = powerManagerWrapper;
1249             if (DEBUG_ENABLE_SHELL_DRAWER) {
1250                 mAtm.mTaskOrganizerController.setDeferTaskOrgCallbacksConsumer(Runnable::run);
1251                 mAtm.mTaskOrganizerController.registerTaskOrganizer(this);
1252             }
1253         }
1254 
setRunnableWhenAddingSplashScreen(Runnable r)1255         void setRunnableWhenAddingSplashScreen(Runnable r) {
1256             if (DEBUG_ENABLE_SHELL_DRAWER) {
1257                 mRunnableWhenAddingSplashScreen = r;
1258             } else {
1259                 ((TestWindowManagerPolicy) mWMService.mPolicy).setRunnableWhenAddingSplashScreen(r);
1260             }
1261         }
1262 
1263         @Override
addStartingWindow(StartingWindowInfo info, IBinder appToken)1264         public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
1265             synchronized (mWMService.mGlobalLock) {
1266                 final ActivityRecord activity = mWMService.mRoot.getActivityRecord(
1267                         appToken);
1268                 IWindow iWindow = mock(IWindow.class);
1269                 doReturn(mock(IBinder.class)).when(iWindow).asBinder();
1270                 final WindowState window = WindowTestsBase.createWindow(null,
1271                         TYPE_APPLICATION_STARTING, activity,
1272                         "Starting window", 0 /* ownerId */, 0 /* userId*/,
1273                         false /* internalWindows */, mWMService, mock(Session.class),
1274                         iWindow,
1275                         mPowerManagerWrapper);
1276                 activity.mStartingWindow = window;
1277                 mAppWindowMap.put(appToken, window);
1278                 mTaskAppMap.put(info.taskInfo.taskId, appToken);
1279             }
1280             if (mRunnableWhenAddingSplashScreen != null) {
1281                 mRunnableWhenAddingSplashScreen.run();
1282                 mRunnableWhenAddingSplashScreen = null;
1283             }
1284         }
1285         @Override
removeStartingWindow(int taskId, SurfaceControl leash, Rect frame, boolean playRevealAnimation)1286         public void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame,
1287                 boolean playRevealAnimation) {
1288             synchronized (mWMService.mGlobalLock) {
1289                 final IBinder appToken = mTaskAppMap.get(taskId);
1290                 if (appToken != null) {
1291                     mTaskAppMap.remove(taskId);
1292                     final ActivityRecord activity = mWMService.mRoot.getActivityRecord(
1293                             appToken);
1294                     WindowState win = mAppWindowMap.remove(appToken);
1295                     activity.removeChild(win);
1296                     activity.mStartingWindow = null;
1297                 }
1298             }
1299         }
1300     }
1301 
1302     static class TestSplitOrganizer extends WindowOrganizerTests.StubOrganizer {
1303         final ActivityTaskManagerService mService;
1304         Task mPrimary;
1305         Task mSecondary;
1306         boolean mInSplit = false;
1307         // moves everything to secondary. Most tests expect this since sysui usually does it.
1308         boolean mMoveToSecondaryOnEnter = true;
1309         int mDisplayId;
1310         private static final int[] CONTROLLED_ACTIVITY_TYPES = {
1311                 ACTIVITY_TYPE_STANDARD,
1312                 ACTIVITY_TYPE_HOME,
1313                 ACTIVITY_TYPE_RECENTS,
1314                 ACTIVITY_TYPE_UNDEFINED
1315         };
1316         private static final int[] CONTROLLED_WINDOWING_MODES = {
1317                 WINDOWING_MODE_FULLSCREEN,
1318                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
1319                 WINDOWING_MODE_UNDEFINED
1320         };
TestSplitOrganizer(ActivityTaskManagerService service, DisplayContent display)1321         TestSplitOrganizer(ActivityTaskManagerService service, DisplayContent display) {
1322             mService = service;
1323             mDisplayId = display.mDisplayId;
1324             mService.mTaskOrganizerController.registerTaskOrganizer(this);
1325             mPrimary = mService.mTaskOrganizerController.createRootTask(
1326                     display, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, null);
1327             mSecondary = mService.mTaskOrganizerController.createRootTask(
1328                     display, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, null);;
1329         }
TestSplitOrganizer(ActivityTaskManagerService service)1330         TestSplitOrganizer(ActivityTaskManagerService service) {
1331             this(service, service.mTaskSupervisor.mRootWindowContainer.getDefaultDisplay());
1332         }
setMoveToSecondaryOnEnter(boolean move)1333         public void setMoveToSecondaryOnEnter(boolean move) {
1334             mMoveToSecondaryOnEnter = move;
1335         }
1336 
1337         @Override
onTaskInfoChanged(ActivityManager.RunningTaskInfo info)1338         public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
1339             if (mInSplit) {
1340                 return;
1341             }
1342             if (info.topActivityType == ACTIVITY_TYPE_UNDEFINED) {
1343                 // Not populated
1344                 return;
1345             }
1346             if (info.configuration.windowConfiguration.getWindowingMode()
1347                     != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
1348                 return;
1349             }
1350             mInSplit = true;
1351             if (!mMoveToSecondaryOnEnter) {
1352                 return;
1353             }
1354             DisplayContent dc = mService.mRootWindowContainer.getDisplayContent(mDisplayId);
1355             dc.getDefaultTaskDisplayArea().setLaunchRootTask(
1356                     mSecondary, CONTROLLED_WINDOWING_MODES, CONTROLLED_ACTIVITY_TYPES);
1357             dc.forAllRootTasks(rootTask -> {
1358                 if (!WindowConfiguration.isSplitScreenWindowingMode(rootTask.getWindowingMode())) {
1359                     rootTask.reparent(mSecondary, POSITION_BOTTOM);
1360                 }
1361             });
1362         }
1363     }
1364 
createTestWindowToken(int type, DisplayContent dc)1365     static TestWindowToken createTestWindowToken(int type, DisplayContent dc) {
1366         return createTestWindowToken(type, dc, false /* persistOnEmpty */);
1367     }
1368 
createTestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty)1369     static TestWindowToken createTestWindowToken(int type, DisplayContent dc,
1370             boolean persistOnEmpty) {
1371         SystemServicesTestRule.checkHoldsLock(dc.mWmService.mGlobalLock);
1372 
1373         return new TestWindowToken(type, dc, persistOnEmpty);
1374     }
1375 
1376     /** Used so we can gain access to some protected members of the {@link WindowToken} class */
1377     static class TestWindowToken extends WindowToken {
1378 
TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty)1379         private TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
1380             super(dc.mWmService, mock(IBinder.class), type, persistOnEmpty, dc,
1381                     false /* ownerCanManageAppTokens */);
1382         }
1383 
getWindowsCount()1384         int getWindowsCount() {
1385             return mChildren.size();
1386         }
1387 
hasWindow(WindowState w)1388         boolean hasWindow(WindowState w) {
1389             return mChildren.contains(w);
1390         }
1391     }
1392 
1393     /** Used to track resize reports. */
1394     static class TestWindowState extends WindowState {
1395         boolean mResizeReported;
1396 
TestWindowState(WindowManagerService service, Session session, IWindow window, WindowManager.LayoutParams attrs, WindowToken token)1397         TestWindowState(WindowManagerService service, Session session, IWindow window,
1398                 WindowManager.LayoutParams attrs, WindowToken token) {
1399             super(service, session, window, token, null, OP_NONE, attrs, 0, 0, 0,
1400                     false /* ownerCanAddInternalSystemWindow */);
1401         }
1402 
1403         @Override
reportResized()1404         void reportResized() {
1405             super.reportResized();
1406             mResizeReported = true;
1407         }
1408 
1409         @Override
isGoneForLayout()1410         public boolean isGoneForLayout() {
1411             return false;
1412         }
1413 
1414         @Override
updateResizingWindowIfNeeded()1415         void updateResizingWindowIfNeeded() {
1416             // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
1417             // the system that it can actually update the window.
1418             boolean hadSurface = mHasSurface;
1419             mHasSurface = true;
1420 
1421             super.updateResizingWindowIfNeeded();
1422 
1423             mHasSurface = hadSurface;
1424         }
1425     }
1426 
1427     class TestTransitionPlayer extends ITransitionPlayer.Stub {
1428         final TransitionController mController;
1429         final WindowOrganizerController mOrganizer;
1430         Transition mLastTransit = null;
1431         TransitionRequestInfo mLastRequest = null;
1432         TransitionInfo mLastReady = null;
1433 
TestTransitionPlayer(@onNull TransitionController controller, @NonNull WindowOrganizerController organizer)1434         TestTransitionPlayer(@NonNull TransitionController controller,
1435                 @NonNull WindowOrganizerController organizer) {
1436             mController = controller;
1437             mOrganizer = organizer;
1438         }
1439 
clear()1440         void clear() {
1441             mLastTransit = null;
1442             mLastReady = null;
1443             mLastRequest = null;
1444         }
1445 
1446         @Override
onTransitionReady(IBinder transitToken, TransitionInfo transitionInfo, SurfaceControl.Transaction transaction, SurfaceControl.Transaction finishT)1447         public void onTransitionReady(IBinder transitToken, TransitionInfo transitionInfo,
1448                 SurfaceControl.Transaction transaction, SurfaceControl.Transaction finishT)
1449                 throws RemoteException {
1450             mLastTransit = Transition.fromBinder(transitToken);
1451             mLastReady = transitionInfo;
1452         }
1453 
1454         @Override
requestStartTransition(IBinder transitToken, TransitionRequestInfo request)1455         public void requestStartTransition(IBinder transitToken,
1456                 TransitionRequestInfo request) throws RemoteException {
1457             mLastTransit = Transition.fromBinder(transitToken);
1458             mLastRequest = request;
1459         }
1460 
start()1461         public void start() {
1462             mOrganizer.startTransition(mLastRequest.getType(), mLastTransit, null);
1463             mLastTransit.onTransactionReady(mLastTransit.getSyncId(),
1464                     mock(SurfaceControl.Transaction.class));
1465         }
1466 
finish()1467         public void finish() {
1468             mController.finishTransition(mLastTransit);
1469         }
1470     }
1471 }
1472