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