• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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