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