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