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