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