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