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