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