1 /* 2 * Copyright (C) 2018 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.WindowConfiguration.ACTIVITY_TYPE_HOME; 20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; 21 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 22 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; 23 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; 24 import static android.view.Display.DEFAULT_DISPLAY; 25 import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS; 26 27 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 28 29 import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; 30 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean; 31 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt; 32 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString; 33 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; 34 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod; 35 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; 36 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 37 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; 38 import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset; 39 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; 40 import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING; 41 import static com.android.server.wm.ActivityStackSupervisor.ON_TOP; 42 43 import android.app.ActivityManagerInternal; 44 import android.app.ActivityOptions; 45 import android.app.AppOpsManager; 46 import android.app.IApplicationThread; 47 import android.content.ComponentName; 48 import android.content.Context; 49 import android.content.Intent; 50 import android.content.pm.ActivityInfo; 51 import android.content.pm.ApplicationInfo; 52 import android.content.pm.IPackageManager; 53 import android.content.pm.PackageManagerInternal; 54 import android.content.res.Configuration; 55 import android.graphics.Rect; 56 import android.hardware.display.DisplayManager; 57 import android.hardware.display.DisplayManagerGlobal; 58 import android.os.Handler; 59 import android.os.Looper; 60 import android.os.PowerManager; 61 import android.os.Process; 62 import android.os.UserHandle; 63 import android.service.voice.IVoiceInteractionSession; 64 import android.testing.DexmakerShareClassLoaderRule; 65 import android.view.Display; 66 import android.view.DisplayInfo; 67 68 import com.android.internal.app.IVoiceInteractor; 69 import com.android.server.AttributeCache; 70 import com.android.server.ServiceThread; 71 import com.android.server.am.ActivityManagerService; 72 import com.android.server.am.PendingIntentController; 73 import com.android.server.appop.AppOpsService; 74 import com.android.server.firewall.IntentFirewall; 75 import com.android.server.policy.PermissionPolicyInternal; 76 import com.android.server.uri.UriGrantsManagerInternal; 77 import com.android.server.wm.TaskRecord.TaskRecordFactory; 78 import com.android.server.wm.utils.MockTracker; 79 80 import org.junit.After; 81 import org.junit.Before; 82 import org.junit.BeforeClass; 83 import org.junit.Rule; 84 import org.mockito.invocation.InvocationOnMock; 85 86 import java.io.File; 87 import java.util.List; 88 89 /** 90 * A base class to handle common operations in activity related unit tests. 91 */ 92 class ActivityTestsBase { 93 private static int sNextDisplayId = DEFAULT_DISPLAY + 1; 94 95 @Rule 96 public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule = 97 new DexmakerShareClassLoaderRule(); 98 99 final Context mContext = getInstrumentation().getTargetContext(); 100 final TestInjector mTestInjector = new TestInjector(); 101 102 ActivityTaskManagerService mService; 103 RootActivityContainer mRootActivityContainer; 104 ActivityStackSupervisor mSupervisor; 105 106 private MockTracker mMockTracker; 107 108 // Default package name 109 static final String DEFAULT_COMPONENT_PACKAGE_NAME = "com.foo"; 110 111 // Default base activity name 112 private static final String DEFAULT_COMPONENT_CLASS_NAME = ".BarActivity"; 113 114 @BeforeClass setUpOnceBase()115 public static void setUpOnceBase() { 116 AttributeCache.init(getInstrumentation().getTargetContext()); 117 } 118 119 @Before setUpBase()120 public void setUpBase() { 121 mMockTracker = new MockTracker(); 122 123 mTestInjector.setUp(); 124 125 mService = new TestActivityTaskManagerService(mContext); 126 mSupervisor = mService.mStackSupervisor; 127 mRootActivityContainer = mService.mRootActivityContainer; 128 } 129 130 @After tearDownBase()131 public void tearDownBase() { 132 mTestInjector.tearDown(); 133 if (mService != null) { 134 mService.setWindowManager(null); 135 mService = null; 136 } 137 if (sMockWindowManagerService != null) { 138 reset(sMockWindowManagerService); 139 } 140 141 mMockTracker.close(); 142 mMockTracker = null; 143 } 144 145 /** Creates a {@link TestActivityDisplay}. */ createNewActivityDisplay()146 TestActivityDisplay createNewActivityDisplay() { 147 return TestActivityDisplay.create(mSupervisor, sNextDisplayId++); 148 } 149 createNewActivityDisplay(DisplayInfo info)150 TestActivityDisplay createNewActivityDisplay(DisplayInfo info) { 151 return TestActivityDisplay.create(mSupervisor, sNextDisplayId++, info); 152 } 153 154 /** Creates and adds a {@link TestActivityDisplay} to supervisor at the given position. */ addNewActivityDisplayAt(int position)155 TestActivityDisplay addNewActivityDisplayAt(int position) { 156 final TestActivityDisplay display = createNewActivityDisplay(); 157 mRootActivityContainer.addChild(display, position); 158 return display; 159 } 160 161 /** Creates and adds a {@link TestActivityDisplay} to supervisor at the given position. */ addNewActivityDisplayAt(DisplayInfo info, int position)162 TestActivityDisplay addNewActivityDisplayAt(DisplayInfo info, int position) { 163 final TestActivityDisplay display = createNewActivityDisplay(info); 164 mRootActivityContainer.addChild(display, position); 165 return display; 166 } 167 168 /** 169 * Delegates task creation to {@link #TaskBuilder} to avoid the dependency of window hierarchy 170 * when starting activity in unit tests. 171 */ mockTaskRecordFactory()172 void mockTaskRecordFactory() { 173 final TaskRecord task = new TaskBuilder(mSupervisor).setCreateStack(false).build(); 174 final TaskRecordFactory factory = mock(TaskRecordFactory.class); 175 TaskRecord.setTaskRecordFactory(factory); 176 doReturn(task).when(factory).create(any() /* service */, anyInt() /* taskId */, 177 any() /* info */, any() /* intent */, any() /* voiceSession */, 178 any() /* voiceInteractor */); 179 } 180 181 /** 182 * Builder for creating new activities. 183 */ 184 protected static class ActivityBuilder { 185 // An id appended to the end of the component name to make it unique 186 private static int sCurrentActivityId = 0; 187 188 private final ActivityTaskManagerService mService; 189 190 private ComponentName mComponent; 191 private String mTargetActivity; 192 private TaskRecord mTaskRecord; 193 private int mUid; 194 private boolean mCreateTask; 195 private ActivityStack mStack; 196 private int mActivityFlags; 197 private int mLaunchMode; 198 ActivityBuilder(ActivityTaskManagerService service)199 ActivityBuilder(ActivityTaskManagerService service) { 200 mService = service; 201 } 202 setComponent(ComponentName component)203 ActivityBuilder setComponent(ComponentName component) { 204 mComponent = component; 205 return this; 206 } 207 setTargetActivity(String targetActivity)208 ActivityBuilder setTargetActivity(String targetActivity) { 209 mTargetActivity = targetActivity; 210 return this; 211 } 212 getDefaultComponent()213 static ComponentName getDefaultComponent() { 214 return ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME, 215 DEFAULT_COMPONENT_PACKAGE_NAME); 216 } 217 setTask(TaskRecord task)218 ActivityBuilder setTask(TaskRecord task) { 219 mTaskRecord = task; 220 return this; 221 } 222 setActivityFlags(int flags)223 ActivityBuilder setActivityFlags(int flags) { 224 mActivityFlags = flags; 225 return this; 226 } 227 setLaunchMode(int launchMode)228 ActivityBuilder setLaunchMode(int launchMode) { 229 mLaunchMode = launchMode; 230 return this; 231 } 232 setStack(ActivityStack stack)233 ActivityBuilder setStack(ActivityStack stack) { 234 mStack = stack; 235 return this; 236 } 237 setCreateTask(boolean createTask)238 ActivityBuilder setCreateTask(boolean createTask) { 239 mCreateTask = createTask; 240 return this; 241 } 242 setUid(int uid)243 ActivityBuilder setUid(int uid) { 244 mUid = uid; 245 return this; 246 } 247 build()248 ActivityRecord build() { 249 if (mComponent == null) { 250 final int id = sCurrentActivityId++; 251 mComponent = ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME, 252 DEFAULT_COMPONENT_CLASS_NAME + id); 253 } 254 255 if (mCreateTask) { 256 mTaskRecord = new TaskBuilder(mService.mStackSupervisor) 257 .setComponent(mComponent) 258 .setStack(mStack).build(); 259 } 260 261 Intent intent = new Intent(); 262 intent.setComponent(mComponent); 263 final ActivityInfo aInfo = new ActivityInfo(); 264 aInfo.applicationInfo = new ApplicationInfo(); 265 aInfo.applicationInfo.packageName = mComponent.getPackageName(); 266 aInfo.applicationInfo.uid = mUid; 267 aInfo.packageName = mComponent.getPackageName(); 268 aInfo.name = mComponent.getClassName(); 269 if (mTargetActivity != null) { 270 aInfo.targetActivity = mTargetActivity; 271 } 272 aInfo.flags |= mActivityFlags; 273 aInfo.launchMode = mLaunchMode; 274 275 final ActivityRecord activity = new ActivityRecord(mService, null /* caller */, 276 0 /* launchedFromPid */, 0, null, intent, null, 277 aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */, 278 0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */, 279 mService.mStackSupervisor, null /* options */, null /* sourceRecord */); 280 spyOn(activity); 281 activity.mAppWindowToken = mock(AppWindowToken.class); 282 doCallRealMethod().when(activity.mAppWindowToken).getOrientationIgnoreVisibility(); 283 doCallRealMethod().when(activity.mAppWindowToken) 284 .setOrientation(anyInt(), any(), any()); 285 doCallRealMethod().when(activity.mAppWindowToken).setOrientation(anyInt()); 286 doNothing().when(activity).removeWindowContainer(); 287 doReturn(mock(Configuration.class)).when(activity.mAppWindowToken) 288 .getRequestedOverrideConfiguration(); 289 290 if (mTaskRecord != null) { 291 mTaskRecord.addActivityToTop(activity); 292 } 293 294 final WindowProcessController wpc = new WindowProcessController(mService, 295 mService.mContext.getApplicationInfo(), "name", 12345, 296 UserHandle.getUserId(12345), mock(Object.class), 297 mock(WindowProcessListener.class)); 298 wpc.setThread(mock(IApplicationThread.class)); 299 activity.setProcess(wpc); 300 return activity; 301 } 302 } 303 304 /** 305 * Builder for creating new tasks. 306 */ 307 protected static class TaskBuilder { 308 // Default package name 309 static final String DEFAULT_PACKAGE = "com.bar"; 310 311 private final ActivityStackSupervisor mSupervisor; 312 313 private ComponentName mComponent; 314 private String mPackage; 315 private int mFlags = 0; 316 // Task id 0 is reserved in ARC for the home app. 317 private int mTaskId = 1; 318 private int mUserId = 0; 319 private IVoiceInteractionSession mVoiceSession; 320 private boolean mCreateStack = true; 321 322 private ActivityStack mStack; 323 TaskBuilder(ActivityStackSupervisor supervisor)324 TaskBuilder(ActivityStackSupervisor supervisor) { 325 mSupervisor = supervisor; 326 } 327 setComponent(ComponentName component)328 TaskBuilder setComponent(ComponentName component) { 329 mComponent = component; 330 return this; 331 } 332 setPackage(String packageName)333 TaskBuilder setPackage(String packageName) { 334 mPackage = packageName; 335 return this; 336 } 337 338 /** 339 * Set to {@code true} by default, set to {@code false} to prevent the task from 340 * automatically creating a parent stack. 341 */ setCreateStack(boolean createStack)342 TaskBuilder setCreateStack(boolean createStack) { 343 mCreateStack = createStack; 344 return this; 345 } 346 setVoiceSession(IVoiceInteractionSession session)347 TaskBuilder setVoiceSession(IVoiceInteractionSession session) { 348 mVoiceSession = session; 349 return this; 350 } 351 setFlags(int flags)352 TaskBuilder setFlags(int flags) { 353 mFlags = flags; 354 return this; 355 } 356 setTaskId(int taskId)357 TaskBuilder setTaskId(int taskId) { 358 mTaskId = taskId; 359 return this; 360 } 361 setUserId(int userId)362 TaskBuilder setUserId(int userId) { 363 mUserId = userId; 364 return this; 365 } 366 setStack(ActivityStack stack)367 TaskBuilder setStack(ActivityStack stack) { 368 mStack = stack; 369 return this; 370 } 371 build()372 TaskRecord build() { 373 if (mStack == null && mCreateStack) { 374 mStack = mSupervisor.mRootActivityContainer.getDefaultDisplay().createStack( 375 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); 376 } 377 378 final ActivityInfo aInfo = new ActivityInfo(); 379 aInfo.applicationInfo = new ApplicationInfo(); 380 aInfo.applicationInfo.packageName = mPackage; 381 382 Intent intent = new Intent(); 383 if (mComponent == null) { 384 mComponent = ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME, 385 DEFAULT_COMPONENT_CLASS_NAME); 386 } 387 388 intent.setComponent(mComponent); 389 intent.setFlags(mFlags); 390 391 final TestTaskRecord task = new TestTaskRecord(mSupervisor.mService, mTaskId, aInfo, 392 intent /*intent*/, mVoiceSession, null /*_voiceInteractor*/); 393 task.userId = mUserId; 394 395 if (mStack != null) { 396 mStack.moveToFront("test"); 397 mStack.addTask(task, true, "creating test task"); 398 task.setStack(mStack); 399 task.setTask(); 400 mStack.getTaskStack().addChild(task.mTask, 0); 401 } 402 403 task.touchActiveTime(); 404 405 return task; 406 } 407 408 private static class TestTaskRecord extends TaskRecord { TestTaskRecord(ActivityTaskManagerService service, int taskId, ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor)409 TestTaskRecord(ActivityTaskManagerService service, int taskId, ActivityInfo info, 410 Intent intent, IVoiceInteractionSession voiceSession, 411 IVoiceInteractor voiceInteractor) { 412 super(service, taskId, info, intent, voiceSession, voiceInteractor); 413 } 414 415 @Override createTask(boolean onTop, boolean showForAllUsers)416 void createTask(boolean onTop, boolean showForAllUsers) { 417 setTask(); 418 } 419 setTask()420 void setTask() { 421 Task mockTask = mock(Task.class); 422 mockTask.mTaskRecord = this; 423 doCallRealMethod().when(mockTask).onDescendantOrientationChanged(any(), any()); 424 setTask(mock(Task.class)); 425 } 426 } 427 } 428 429 protected class TestActivityTaskManagerService extends ActivityTaskManagerService { 430 private PackageManagerInternal mPmInternal; 431 private PermissionPolicyInternal mPermissionPolicyInternal; 432 433 // ActivityStackSupervisor may be created more than once while setting up AMS and ATMS. 434 // We keep the reference in order to prevent creating it twice. 435 ActivityStackSupervisor mTestStackSupervisor; 436 437 ActivityDisplay mDefaultDisplay; 438 AppOpsService mAppOpsService; 439 TestActivityTaskManagerService(Context context)440 TestActivityTaskManagerService(Context context) { 441 super(context); 442 spyOn(this); 443 444 mUgmInternal = mock(UriGrantsManagerInternal.class); 445 mAppOpsService = mock(AppOpsService.class); 446 447 // Make sure permission checks aren't overridden. 448 doReturn(AppOpsManager.MODE_DEFAULT) 449 .when(mAppOpsService).noteOperation(anyInt(), anyInt(), anyString()); 450 451 mSupportsMultiWindow = true; 452 mSupportsMultiDisplay = true; 453 mSupportsSplitScreenMultiWindow = true; 454 mSupportsFreeformWindowManagement = true; 455 mSupportsPictureInPicture = true; 456 457 final TestActivityManagerService am = 458 new TestActivityManagerService(mTestInjector, this); 459 460 spyOn(getLifecycleManager()); 461 spyOn(getLockTaskController()); 462 doReturn(mock(IPackageManager.class)).when(this).getPackageManager(); 463 // allow background activity starts by default 464 doReturn(true).when(this).isBackgroundActivityStartsEnabled(); 465 doNothing().when(this).updateCpuStats(); 466 } 467 setup(IntentFirewall intentFirewall, PendingIntentController intentController, ActivityManagerInternal amInternal, WindowManagerService wm, Looper looper)468 void setup(IntentFirewall intentFirewall, PendingIntentController intentController, 469 ActivityManagerInternal amInternal, WindowManagerService wm, Looper looper) { 470 mAmInternal = amInternal; 471 initialize(intentFirewall, intentController, looper); 472 initRootActivityContainerMocks(wm); 473 setWindowManager(wm); 474 createDefaultDisplay(); 475 } 476 initRootActivityContainerMocks(WindowManagerService wm)477 void initRootActivityContainerMocks(WindowManagerService wm) { 478 spyOn(mRootActivityContainer); 479 mRootActivityContainer.setWindowContainer(mock(RootWindowContainer.class)); 480 mRootActivityContainer.mWindowManager = wm; 481 mRootActivityContainer.mDisplayManager = 482 (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE); 483 doNothing().when(mRootActivityContainer).setWindowManager(any()); 484 // Invoked during {@link ActivityStack} creation. 485 doNothing().when(mRootActivityContainer).updateUIDsPresentOnDisplay(); 486 // Always keep things awake. 487 doReturn(true).when(mRootActivityContainer).hasAwakeDisplay(); 488 // Called when moving activity to pinned stack. 489 doNothing().when(mRootActivityContainer).ensureActivitiesVisible(any(), anyInt(), 490 anyBoolean()); 491 } 492 createDefaultDisplay()493 void createDefaultDisplay() { 494 // Create a default display and put a home stack on it so that we'll always have 495 // something focusable. 496 mDefaultDisplay = TestActivityDisplay.create(mStackSupervisor, DEFAULT_DISPLAY); 497 spyOn(mDefaultDisplay); 498 mRootActivityContainer.addChild(mDefaultDisplay, ActivityDisplay.POSITION_TOP); 499 mDefaultDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP); 500 final TaskRecord task = new TaskBuilder(mStackSupervisor) 501 .setStack(mDefaultDisplay.getHomeStack()).build(); 502 new ActivityBuilder(this).setTask(task).build(); 503 504 doReturn(mDefaultDisplay).when(mRootActivityContainer).getDefaultDisplay(); 505 } 506 507 @Override handleIncomingUser(int callingPid, int callingUid, int userId, String name)508 int handleIncomingUser(int callingPid, int callingUid, int userId, String name) { 509 return userId; 510 } 511 512 @Override getAppOpsService()513 AppOpsService getAppOpsService() { 514 return mAppOpsService; 515 } 516 517 @Override updateCpuStats()518 void updateCpuStats() { 519 } 520 521 @Override updateBatteryStats(ActivityRecord component, boolean resumed)522 void updateBatteryStats(ActivityRecord component, boolean resumed) { 523 } 524 525 @Override updateActivityUsageStats(ActivityRecord activity, int event)526 void updateActivityUsageStats(ActivityRecord activity, int event) { 527 } 528 529 @Override createStackSupervisor()530 protected ActivityStackSupervisor createStackSupervisor() { 531 if (mTestStackSupervisor == null) { 532 mTestStackSupervisor = new TestActivityStackSupervisor(this, mH.getLooper()); 533 } 534 return mTestStackSupervisor; 535 } 536 537 @Override getPackageManagerInternalLocked()538 PackageManagerInternal getPackageManagerInternalLocked() { 539 if (mPmInternal == null) { 540 mPmInternal = mock(PackageManagerInternal.class); 541 doReturn(false) 542 .when(mPmInternal) 543 .isPermissionsReviewRequired(anyString(), anyInt()); 544 } 545 return mPmInternal; 546 } 547 548 @Override getPermissionPolicyInternal()549 PermissionPolicyInternal getPermissionPolicyInternal() { 550 if (mPermissionPolicyInternal == null) { 551 mPermissionPolicyInternal = mock(PermissionPolicyInternal.class); 552 doReturn(true).when(mPermissionPolicyInternal).checkStartActivity(any(), anyInt(), 553 any()); 554 } 555 return mPermissionPolicyInternal; 556 } 557 } 558 559 private static class TestInjector extends ActivityManagerService.Injector { 560 private ServiceThread mHandlerThread; 561 562 @Override getContext()563 public Context getContext() { 564 return getInstrumentation().getTargetContext(); 565 } 566 567 @Override getAppOpsService(File file, Handler handler)568 public AppOpsService getAppOpsService(File file, Handler handler) { 569 return null; 570 } 571 572 @Override getUiHandler(ActivityManagerService service)573 public Handler getUiHandler(ActivityManagerService service) { 574 return mHandlerThread.getThreadHandler(); 575 } 576 577 @Override isNetworkRestrictedForUid(int uid)578 public boolean isNetworkRestrictedForUid(int uid) { 579 return false; 580 } 581 setUp()582 void setUp() { 583 mHandlerThread = new ServiceThread("ActivityTestsThread", 584 Process.THREAD_PRIORITY_DEFAULT, true /* allowIo */); 585 mHandlerThread.start(); 586 } 587 tearDown()588 void tearDown() { 589 // Make sure there are no running messages and then quit the thread so the next test 590 // won't be affected. 591 mHandlerThread.getThreadHandler().runWithScissors(mHandlerThread::quit, 592 0 /* timeout */); 593 } 594 } 595 596 // TODO: Replace this with a mock object since we are no longer in AMS package. 597 /** 598 * An {@link ActivityManagerService} subclass which provides a test 599 * {@link ActivityStackSupervisor}. 600 */ 601 class TestActivityManagerService extends ActivityManagerService { 602 TestActivityManagerService(TestInjector testInjector, TestActivityTaskManagerService atm)603 TestActivityManagerService(TestInjector testInjector, TestActivityTaskManagerService atm) { 604 super(testInjector, testInjector.mHandlerThread); 605 spyOn(this); 606 607 mWindowManager = prepareMockWindowManager(); 608 mUgmInternal = mock(UriGrantsManagerInternal.class); 609 610 atm.setup(mIntentFirewall, mPendingIntentController, new LocalService(), mWindowManager, 611 testInjector.mHandlerThread.getLooper()); 612 613 mActivityTaskManager = atm; 614 mAtmInternal = atm.mInternal; 615 616 doReturn(mock(IPackageManager.class)).when(this).getPackageManager(); 617 PackageManagerInternal mockPackageManager = mock(PackageManagerInternal.class); 618 doReturn(mockPackageManager).when(this).getPackageManagerInternalLocked(); 619 doReturn(null).when(mockPackageManager).getDefaultHomeActivity(anyInt()); 620 doNothing().when(this).grantEphemeralAccessLocked(anyInt(), any(), anyInt(), anyInt()); 621 } 622 } 623 624 /** 625 * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on 626 * setup not available in the test environment. Also specifies an injector for 627 */ 628 protected class TestActivityStackSupervisor extends ActivityStackSupervisor { 629 private KeyguardController mKeyguardController; 630 TestActivityStackSupervisor(ActivityTaskManagerService service, Looper looper)631 TestActivityStackSupervisor(ActivityTaskManagerService service, Looper looper) { 632 super(service, looper); 633 spyOn(this); 634 mWindowManager = prepareMockWindowManager(); 635 mKeyguardController = mock(KeyguardController.class); 636 637 // Do not schedule idle that may touch methods outside the scope of the test. 638 doNothing().when(this).scheduleIdleLocked(); 639 doNothing().when(this).scheduleIdleTimeoutLocked(any()); 640 // unit test version does not handle launch wake lock 641 doNothing().when(this).acquireLaunchWakelock(); 642 doReturn(mKeyguardController).when(this).getKeyguardController(); 643 644 mLaunchingActivityWakeLock = mock(PowerManager.WakeLock.class); 645 646 initialize(); 647 } 648 649 @Override getKeyguardController()650 public KeyguardController getKeyguardController() { 651 return mKeyguardController; 652 } 653 654 @Override setWindowManager(WindowManagerService wm)655 void setWindowManager(WindowManagerService wm) { 656 mWindowManager = wm; 657 } 658 } 659 660 protected static class TestActivityDisplay extends ActivityDisplay { 661 private final ActivityStackSupervisor mSupervisor; 662 create(ActivityStackSupervisor supervisor, int displayId)663 static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId) { 664 return create(supervisor, displayId, new DisplayInfo()); 665 } 666 create(ActivityStackSupervisor supervisor, int displayId, DisplayInfo info)667 static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId, 668 DisplayInfo info) { 669 if (displayId == DEFAULT_DISPLAY) { 670 return new TestActivityDisplay(supervisor, 671 supervisor.mRootActivityContainer.mDisplayManager.getDisplay(displayId)); 672 } 673 final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId, 674 info, DEFAULT_DISPLAY_ADJUSTMENTS); 675 return new TestActivityDisplay(supervisor, display); 676 } 677 TestActivityDisplay(ActivityStackSupervisor supervisor, Display display)678 TestActivityDisplay(ActivityStackSupervisor supervisor, Display display) { 679 super(supervisor.mService.mRootActivityContainer, display); 680 // Normally this comes from display-properties as exposed by WM. Without that, just 681 // hard-code to FULLSCREEN for tests. 682 setWindowingMode(WINDOWING_MODE_FULLSCREEN); 683 mSupervisor = supervisor; 684 } 685 686 @SuppressWarnings("TypeParameterUnusedInFormals") 687 @Override createStackUnchecked(int windowingMode, int activityType, int stackId, boolean onTop)688 ActivityStack createStackUnchecked(int windowingMode, int activityType, 689 int stackId, boolean onTop) { 690 return new StackBuilder(mSupervisor.mRootActivityContainer).setDisplay(this) 691 .setWindowingMode(windowingMode).setActivityType(activityType) 692 .setStackId(stackId).setOnTop(onTop).setCreateActivity(false).build(); 693 } 694 695 @Override createDisplayContent()696 protected DisplayContent createDisplayContent() { 697 final DisplayContent displayContent = mock(DisplayContent.class); 698 DockedStackDividerController divider = mock(DockedStackDividerController.class); 699 doReturn(divider).when(displayContent).getDockedDividerController(); 700 return displayContent; 701 } 702 removeAllTasks()703 void removeAllTasks() { 704 for (int i = 0; i < getChildCount(); i++) { 705 final ActivityStack stack = getChildAt(i); 706 for (TaskRecord task : (List<TaskRecord>) stack.getAllTasks()) { 707 stack.removeTask(task, "removeAllTasks", REMOVE_TASK_MODE_DESTROYING); 708 } 709 } 710 } 711 } 712 713 private static WindowManagerService sMockWindowManagerService; 714 prepareMockWindowManager()715 private static WindowManagerService prepareMockWindowManager() { 716 if (sMockWindowManagerService == null) { 717 sMockWindowManagerService = mock(WindowManagerService.class); 718 } 719 720 sMockWindowManagerService.mRoot = mock(RootWindowContainer.class); 721 722 doAnswer((InvocationOnMock invocationOnMock) -> { 723 final Runnable runnable = invocationOnMock.<Runnable>getArgument(0); 724 if (runnable != null) { 725 runnable.run(); 726 } 727 return null; 728 }).when(sMockWindowManagerService).inSurfaceTransaction(any()); 729 730 return sMockWindowManagerService; 731 } 732 733 /** 734 * Overridden {@link ActivityStack} that tracks test metrics, such as the number of times a 735 * method is called. Note that its functionality depends on the implementations of the 736 * construction arguments. 737 */ 738 protected static class TestActivityStack 739 extends ActivityStack { 740 private int mOnActivityRemovedFromStackCount = 0; 741 742 static final int IS_TRANSLUCENT_UNSET = 0; 743 static final int IS_TRANSLUCENT_FALSE = 1; 744 static final int IS_TRANSLUCENT_TRUE = 2; 745 private int mIsTranslucent = IS_TRANSLUCENT_UNSET; 746 747 static final int SUPPORTS_SPLIT_SCREEN_UNSET = 0; 748 static final int SUPPORTS_SPLIT_SCREEN_FALSE = 1; 749 static final int SUPPORTS_SPLIT_SCREEN_TRUE = 2; 750 private int mSupportsSplitScreen = SUPPORTS_SPLIT_SCREEN_UNSET; 751 TestActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor, int windowingMode, int activityType, boolean onTop, boolean createActivity)752 TestActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor, 753 int windowingMode, int activityType, boolean onTop, boolean createActivity) { 754 super(display, stackId, supervisor, windowingMode, activityType, onTop); 755 if (createActivity) { 756 new ActivityBuilder(mService).setCreateTask(true).setStack(this).build(); 757 if (onTop) { 758 // We move the task to front again in order to regain focus after activity 759 // added to the stack. Or {@link ActivityDisplay#mPreferredTopFocusableStack} 760 // could be other stacks (e.g. home stack). 761 moveToFront("createActivityStack"); 762 } else { 763 moveToBack("createActivityStack", null); 764 } 765 } 766 } 767 768 @Override onActivityRemovedFromStack(ActivityRecord r)769 void onActivityRemovedFromStack(ActivityRecord r) { 770 mOnActivityRemovedFromStackCount++; 771 super.onActivityRemovedFromStack(r); 772 } 773 774 // Returns the number of times {@link #onActivityRemovedFromStack} has been called onActivityRemovedFromStackInvocationCount()775 int onActivityRemovedFromStackInvocationCount() { 776 return mOnActivityRemovedFromStackCount; 777 } 778 779 @Override createTaskStack(int displayId, boolean onTop, Rect outBounds)780 protected void createTaskStack(int displayId, boolean onTop, Rect outBounds) { 781 mTaskStack = mock(TaskStack.class); 782 783 // Primary pinned stacks require a non-empty out bounds to be set or else all tasks 784 // will be moved to the full screen stack. 785 if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { 786 outBounds.set(0, 0, 100, 100); 787 } 788 } 789 790 @Override getTaskStack()791 TaskStack getTaskStack() { 792 return mTaskStack; 793 } 794 setIsTranslucent(boolean isTranslucent)795 void setIsTranslucent(boolean isTranslucent) { 796 mIsTranslucent = isTranslucent ? IS_TRANSLUCENT_TRUE : IS_TRANSLUCENT_FALSE; 797 } 798 799 @Override isStackTranslucent(ActivityRecord starting)800 boolean isStackTranslucent(ActivityRecord starting) { 801 switch (mIsTranslucent) { 802 case IS_TRANSLUCENT_TRUE: 803 return true; 804 case IS_TRANSLUCENT_FALSE: 805 return false; 806 case IS_TRANSLUCENT_UNSET: 807 default: 808 return super.isStackTranslucent(starting); 809 } 810 } 811 setSupportsSplitScreen(boolean supportsSplitScreen)812 void setSupportsSplitScreen(boolean supportsSplitScreen) { 813 mSupportsSplitScreen = supportsSplitScreen 814 ? SUPPORTS_SPLIT_SCREEN_TRUE : SUPPORTS_SPLIT_SCREEN_FALSE; 815 } 816 817 @Override supportsSplitScreenWindowingMode()818 public boolean supportsSplitScreenWindowingMode() { 819 switch (mSupportsSplitScreen) { 820 case SUPPORTS_SPLIT_SCREEN_TRUE: 821 return true; 822 case SUPPORTS_SPLIT_SCREEN_FALSE: 823 return false; 824 case SUPPORTS_SPLIT_SCREEN_UNSET: 825 default: 826 return super.supportsSplitScreenWindowingMode(); 827 } 828 } 829 830 @Override startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity, boolean newTask, boolean keepCurTransition, ActivityOptions options)831 void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity, 832 boolean newTask, boolean keepCurTransition, 833 ActivityOptions options) { 834 } 835 } 836 837 static class StackBuilder { 838 private final RootActivityContainer mRootActivityContainer; 839 private ActivityDisplay mDisplay; 840 private int mStackId = -1; 841 private int mWindowingMode = WINDOWING_MODE_FULLSCREEN; 842 private int mActivityType = ACTIVITY_TYPE_STANDARD; 843 private boolean mOnTop = true; 844 private boolean mCreateActivity = true; 845 StackBuilder(RootActivityContainer root)846 StackBuilder(RootActivityContainer root) { 847 mRootActivityContainer = root; 848 mDisplay = mRootActivityContainer.getDefaultDisplay(); 849 } 850 setWindowingMode(int windowingMode)851 StackBuilder setWindowingMode(int windowingMode) { 852 mWindowingMode = windowingMode; 853 return this; 854 } 855 setActivityType(int activityType)856 StackBuilder setActivityType(int activityType) { 857 mActivityType = activityType; 858 return this; 859 } 860 setStackId(int stackId)861 StackBuilder setStackId(int stackId) { 862 mStackId = stackId; 863 return this; 864 } 865 setDisplay(ActivityDisplay display)866 StackBuilder setDisplay(ActivityDisplay display) { 867 mDisplay = display; 868 return this; 869 } 870 setOnTop(boolean onTop)871 StackBuilder setOnTop(boolean onTop) { 872 mOnTop = onTop; 873 return this; 874 } 875 setCreateActivity(boolean createActivity)876 StackBuilder setCreateActivity(boolean createActivity) { 877 mCreateActivity = createActivity; 878 return this; 879 } 880 881 @SuppressWarnings("TypeParameterUnusedInFormals") build()882 ActivityStack build() { 883 final int stackId = mStackId >= 0 ? mStackId : mDisplay.getNextStackId(); 884 if (mWindowingMode == WINDOWING_MODE_PINNED) { 885 return new ActivityStack(mDisplay, stackId, mRootActivityContainer.mStackSupervisor, 886 mWindowingMode, ACTIVITY_TYPE_STANDARD, mOnTop) { 887 @Override 888 Rect getDefaultPictureInPictureBounds(float aspectRatio) { 889 return new Rect(50, 50, 100, 100); 890 } 891 892 @Override 893 void createTaskStack(int displayId, boolean onTop, Rect outBounds) { 894 mTaskStack = mock(TaskStack.class); 895 } 896 }; 897 } else { 898 return new TestActivityStack(mDisplay, stackId, 899 mRootActivityContainer.mStackSupervisor, mWindowingMode, 900 mActivityType, mOnTop, mCreateActivity); 901 } 902 } 903 904 } 905 } 906