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