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