blob: 74b0c9e915745bf171fcc221b61fb618e26cd38c [file] [log] [blame]
Bryce Leeaf691c02017-03-20 14:20:22 -07001/*
2 * Copyright (C) 2017 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
17package com.android.server.am;
18
Bryce Lee18d51592017-10-25 10:22:19 -070019import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
20import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070021import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070022import static android.view.Display.DEFAULT_DISPLAY;
Bryce Leeaf691c02017-03-20 14:20:22 -070023import static org.mockito.Mockito.mock;
Bryce Lee2a3cc462017-10-27 10:57:35 -070024import static org.mockito.Mockito.doNothing;
Bryce Lee04ab3462017-04-10 15:06:33 -070025import static org.mockito.Mockito.doReturn;
26import static org.mockito.Mockito.any;
Bryce Lee2a3cc462017-10-27 10:57:35 -070027import static org.mockito.Mockito.anyBoolean;
28import static org.mockito.Mockito.anyInt;
Bryce Lee04ab3462017-04-10 15:06:33 -070029import static org.mockito.Mockito.doAnswer;
Bryce Lee4e4a3ec2017-09-27 08:25:03 -070030import static org.mockito.Mockito.spy;
Bryce Lee04ab3462017-04-10 15:06:33 -070031
32import org.mockito.invocation.InvocationOnMock;
Bryce Leeaf691c02017-03-20 14:20:22 -070033
34import android.content.ComponentName;
35import android.content.Context;
36import android.content.Intent;
37import android.content.pm.ActivityInfo;
38import android.content.pm.ApplicationInfo;
39import android.content.res.Configuration;
40import android.graphics.Rect;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070041import android.hardware.display.DisplayManager;
Bryce Lee3115bdf2017-04-05 08:39:40 -070042import android.os.HandlerThread;
Bryce Leeaf691c02017-03-20 14:20:22 -070043import android.os.Looper;
Bryce Lee93e7f792017-10-25 15:54:55 -070044import android.service.voice.IVoiceInteractionSession;
Bryce Leeaf691c02017-03-20 14:20:22 -070045import android.support.test.InstrumentationRegistry;
46import com.android.server.AttributeCache;
47import com.android.server.wm.AppWindowContainerController;
Bryce Lee4e4a3ec2017-09-27 08:25:03 -070048import com.android.server.wm.PinnedStackWindowController;
Bryce Leeaf691c02017-03-20 14:20:22 -070049import com.android.server.wm.StackWindowController;
Bryce Lee04ab3462017-04-10 15:06:33 -070050import com.android.server.wm.TaskWindowContainerController;
Bryce Leeaf691c02017-03-20 14:20:22 -070051import com.android.server.wm.WindowManagerService;
52import com.android.server.wm.WindowTestUtils;
Bryce Lee3115bdf2017-04-05 08:39:40 -070053import org.junit.After;
Bryce Leeaf691c02017-03-20 14:20:22 -070054import org.junit.Before;
55import org.mockito.MockitoAnnotations;
56
57/**
58 * A base class to handle common operations in activity related unit tests.
59 */
60public class ActivityTestsBase {
Bryce Lee939a9a32017-10-23 10:01:21 -070061 private static boolean sOneTimeSetupDone = false;
62
Bryce Leeaf691c02017-03-20 14:20:22 -070063 private final Context mContext = InstrumentationRegistry.getContext();
Bryce Lee3115bdf2017-04-05 08:39:40 -070064 private HandlerThread mHandlerThread;
Bryce Leeaf691c02017-03-20 14:20:22 -070065
Bryce Leeaf691c02017-03-20 14:20:22 -070066 @Before
67 public void setUp() throws Exception {
Bryce Lee939a9a32017-10-23 10:01:21 -070068 if (!sOneTimeSetupDone) {
69 sOneTimeSetupDone = true;
70
71 // Allows to mock package local classes and methods
72 System.setProperty("dexmaker.share_classloader", "true");
73 MockitoAnnotations.initMocks(this);
74 }
Bryce Lee3115bdf2017-04-05 08:39:40 -070075 mHandlerThread = new HandlerThread("ActivityTestsBaseThread");
76 mHandlerThread.start();
77 }
Bryce Leeaf691c02017-03-20 14:20:22 -070078
Bryce Lee3115bdf2017-04-05 08:39:40 -070079 @After
80 public void tearDown() {
81 mHandlerThread.quitSafely();
Bryce Leeaf691c02017-03-20 14:20:22 -070082 }
83
84 protected ActivityManagerService createActivityManagerService() {
Bryce Lee93e7f792017-10-25 15:54:55 -070085 final ActivityManagerService service =
86 setupActivityManagerService(new TestActivityManagerService(mContext));
87 AttributeCache.init(mContext);
88 return service;
Winson Chung3f0e59a2017-10-25 10:19:05 -070089 }
90
91 protected ActivityManagerService setupActivityManagerService(ActivityManagerService service) {
92 service = spy(service);
Bryce Lee4e4a3ec2017-09-27 08:25:03 -070093 service.mWindowManager = prepareMockWindowManager();
Bryce Lee840c5662017-04-13 10:02:51 -070094 return service;
Bryce Leeaf691c02017-03-20 14:20:22 -070095 }
96
Bryce Lee18d51592017-10-25 10:22:19 -070097 /**
98 * Builder for creating new activities.
99 */
100 protected static class ActivityBuilder {
101 // An id appended to the end of the component name to make it unique
102 private static int sCurrentActivityId = 0;
Bryce Lee9f6affd2017-09-01 09:18:35 -0700103
Bryce Lee18d51592017-10-25 10:22:19 -0700104 // Default package name
Bryce Lee93e7f792017-10-25 15:54:55 -0700105 static final String DEFAULT_PACKAGE = "com.foo";
Bryce Leeaf691c02017-03-20 14:20:22 -0700106
Bryce Lee18d51592017-10-25 10:22:19 -0700107 // Default base activity name
108 private static final String DEFAULT_BASE_ACTIVITY_NAME = ".BarActivity";
109
110 private final ActivityManagerService mService;
111
112 private ComponentName mComponent;
113 private TaskRecord mTaskRecord;
114 private int mUid;
115 private boolean mCreateTask;
116 private ActivityStack mStack;
117
118 ActivityBuilder(ActivityManagerService service) {
119 mService = service;
Bryce Leeaf691c02017-03-20 14:20:22 -0700120 }
121
Bryce Lee18d51592017-10-25 10:22:19 -0700122 ActivityBuilder setComponent(ComponentName component) {
123 mComponent = component;
124 return this;
125 }
126
127 ActivityBuilder setTask(TaskRecord task) {
128 mTaskRecord = task;
129 return this;
130 }
131
132 ActivityBuilder setStack(ActivityStack stack) {
133 mStack = stack;
134 return this;
135 }
136
137 ActivityBuilder setCreateTask(boolean createTask) {
138 mCreateTask = createTask;
139 return this;
140 }
141
142 ActivityBuilder setUid(int uid) {
143 mUid = uid;
144 return this;
145 }
146
147 ActivityRecord build() {
148 if (mComponent == null) {
149 final int id = sCurrentActivityId++;
150 mComponent = ComponentName.createRelative(DEFAULT_PACKAGE,
151 DEFAULT_BASE_ACTIVITY_NAME + id);
152 }
153
154 if (mCreateTask) {
155 mTaskRecord = new TaskBuilder(mService.mStackSupervisor)
156 .setComponent(mComponent)
157 .setStack(mStack).build();
158 }
159
160 Intent intent = new Intent();
161 intent.setComponent(mComponent);
162 final ActivityInfo aInfo = new ActivityInfo();
163 aInfo.applicationInfo = new ApplicationInfo();
164 aInfo.applicationInfo.packageName = mComponent.getPackageName();
165 aInfo.applicationInfo.uid = mUid;
Bryce Lee18d51592017-10-25 10:22:19 -0700166 final ActivityRecord activity = new ActivityRecord(mService, null /* caller */,
167 0 /* launchedFromPid */, 0, null, intent, null,
168 aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
169 0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
170 mService.mStackSupervisor, null /* options */, null /* sourceRecord */);
171 activity.mWindowContainerController = mock(AppWindowContainerController.class);
172
173 if (mTaskRecord != null) {
174 mTaskRecord.addActivityToTop(activity);
175 }
176
177 return activity;
178 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700179 }
180
Bryce Lee18d51592017-10-25 10:22:19 -0700181 /**
182 * Builder for creating new tasks.
183 */
184 protected static class TaskBuilder {
185 private final ActivityStackSupervisor mSupervisor;
Winson Chung1dbc8112017-09-28 18:05:31 -0700186
Bryce Lee18d51592017-10-25 10:22:19 -0700187 private ComponentName mComponent;
188 private String mPackage;
189 private int mFlags = 0;
190 private int mTaskId = 0;
Bryce Lee93e7f792017-10-25 15:54:55 -0700191 private IVoiceInteractionSession mVoiceSession;
Bryce Leeaf691c02017-03-20 14:20:22 -0700192
Bryce Lee18d51592017-10-25 10:22:19 -0700193 private ActivityStack mStack;
Bryce Leeaf691c02017-03-20 14:20:22 -0700194
Bryce Lee18d51592017-10-25 10:22:19 -0700195 TaskBuilder(ActivityStackSupervisor supervisor) {
196 mSupervisor = supervisor;
197 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700198
Bryce Lee18d51592017-10-25 10:22:19 -0700199 TaskBuilder setComponent(ComponentName component) {
200 mComponent = component;
201 return this;
202 }
203
204 TaskBuilder setPackage(String packageName) {
205 mPackage = packageName;
206 return this;
207 }
208
Bryce Lee93e7f792017-10-25 15:54:55 -0700209 TaskBuilder setVoiceSession(IVoiceInteractionSession session) {
210 mVoiceSession = session;
211 return this;
212 }
213
Bryce Lee18d51592017-10-25 10:22:19 -0700214 TaskBuilder setFlags(int flags) {
215 mFlags = flags;
216 return this;
217 }
218
219 TaskBuilder setTaskId(int taskId) {
220 mTaskId = taskId;
221 return this;
222 }
223
224 TaskBuilder setStack(ActivityStack stack) {
225 mStack = stack;
226 return this;
227 }
228
229 TaskRecord build() {
230 if (mStack == null) {
231 mStack = mSupervisor.getDefaultDisplay().createStack(
232 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
233 }
234
235 final ActivityInfo aInfo = new ActivityInfo();
236 aInfo.applicationInfo = new ApplicationInfo();
237 aInfo.applicationInfo.packageName = mPackage;
238
239 Intent intent = new Intent();
240 intent.setComponent(mComponent);
241 intent.setFlags(mFlags);
242
243 final TaskRecord task = new TaskRecord(mSupervisor.mService, mTaskId, aInfo,
Bryce Lee93e7f792017-10-25 15:54:55 -0700244 intent /*intent*/, mVoiceSession, null /*_voiceInteractor*/);
Bryce Lee18d51592017-10-25 10:22:19 -0700245 mSupervisor.setFocusStackUnchecked("test", mStack);
246 mStack.addTask(task, true, "creating test task");
247 task.setStack(mStack);
248 task.setWindowContainerController(mock(TaskWindowContainerController.class));
249
250 return task;
251 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700252 }
253
254 /**
255 * An {@link ActivityManagerService} subclass which provides a test
256 * {@link ActivityStackSupervisor}.
257 */
258 protected static class TestActivityManagerService extends ActivityManagerService {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700259 TestActivityManagerService(Context context) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700260 super(context);
Bryce Lee04ab3462017-04-10 15:06:33 -0700261 mSupportsMultiWindow = true;
262 mSupportsMultiDisplay = true;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700263 mSupportsSplitScreenMultiWindow = true;
264 mSupportsFreeformWindowManagement = true;
265 mSupportsPictureInPicture = true;
Bryce Lee6a0754a2017-10-10 17:53:50 -0700266 mWindowManager = WindowTestUtils.getMockWindowManagerService();
Bryce Leeaf691c02017-03-20 14:20:22 -0700267 }
268
269 @Override
Bryce Lee2a3cc462017-10-27 10:57:35 -0700270 final protected ActivityStackSupervisor createStackSupervisor() {
271 final ActivityStackSupervisor supervisor = spy(createTestSupervisor());
272
273 // No home stack is set.
274 doNothing().when(supervisor).moveHomeStackToFront(any());
275 doReturn(true).when(supervisor).moveHomeStackTaskToTop(any());
276 // Invoked during {@link ActivityStack} creation.
277 doNothing().when(supervisor).updateUIDsPresentOnDisplay();
278 // Always keep things awake.
279 doReturn(true).when(supervisor).hasAwakeDisplay();
280 // Called when moving activity to pinned stack.
281 doNothing().when(supervisor).ensureActivitiesVisibleLocked(any(), anyInt(), anyBoolean());
282 // Do not schedule idle timeouts
283 doNothing().when(supervisor).scheduleIdleTimeoutLocked(any());
284
285 supervisor.initialize();
286
287 return supervisor;
288 }
289
290 protected ActivityStackSupervisor createTestSupervisor() {
Bryce Lee3115bdf2017-04-05 08:39:40 -0700291 return new TestActivityStackSupervisor(this, mHandlerThread.getLooper());
Bryce Leeaf691c02017-03-20 14:20:22 -0700292 }
Bryce Lee29a649d2017-08-18 13:52:31 -0700293
294 @Override
295 void updateUsageStats(ActivityRecord component, boolean resumed) {
296 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700297 }
298
299 /**
300 * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on
301 * setup not available in the test environment. Also specifies an injector for
302 */
303 protected static class TestActivityStackSupervisor extends ActivityStackSupervisor {
Bryce Lee2a3cc462017-10-27 10:57:35 -0700304 private ActivityDisplay mDisplay;
Bryce Lee943ebe72017-05-04 10:19:07 -0700305
Bryce Leeaf691c02017-03-20 14:20:22 -0700306 public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
307 super(service, looper);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700308 mDisplayManager =
309 (DisplayManager) mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
Bryce Lee04ab3462017-04-10 15:06:33 -0700310 mWindowManager = prepareMockWindowManager();
Bryce Lee2a3cc462017-10-27 10:57:35 -0700311 }
312
313 @Override
314 public void initialize() {
315 super.initialize();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700316 mDisplay = new TestActivityDisplay(this, DEFAULT_DISPLAY);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700317 attachDisplay(mDisplay);
Bryce Lee04ab3462017-04-10 15:06:33 -0700318 }
319
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700320 @Override
321 ActivityDisplay getDefaultDisplay() {
322 return mDisplay;
323 }
324
Bryce Lee2a3cc462017-10-27 10:57:35 -0700325 // Just return the current front task. This is called internally so we cannot use spy to mock this out.
Bryce Lee04ab3462017-04-10 15:06:33 -0700326 @Override
327 ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus) {
328 return mFocusedStack;
329 }
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700330 }
331
332 private static class TestActivityDisplay extends ActivityDisplay {
333
334 private final ActivityStackSupervisor mSupervisor;
335 TestActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
336 super(supervisor, displayId);
337 mSupervisor = supervisor;
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700338 }
339
340 @Override
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700341 <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
342 int stackId, boolean onTop) {
343 if (windowingMode == WINDOWING_MODE_PINNED) {
344 return (T) new PinnedActivityStack(this, stackId, mSupervisor, onTop) {
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700345 @Override
346 Rect getDefaultPictureInPictureBounds(float aspectRatio) {
347 return new Rect(50, 50, 100, 100);
348 }
Bryce Lee4e4a3ec2017-09-27 08:25:03 -0700349
350 @Override
351 PinnedStackWindowController createStackWindowController(int displayId,
352 boolean onTop, Rect outBounds) {
353 return mock(PinnedStackWindowController.class);
354 }
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700355 };
356 } else {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700357 return (T) new TestActivityStack(
358 this, stackId, mSupervisor, windowingMode, activityType, onTop);
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700359 }
Bryce Lee04ab3462017-04-10 15:06:33 -0700360 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700361 }
362
Bryce Lee04ab3462017-04-10 15:06:33 -0700363 private static WindowManagerService prepareMockWindowManager() {
Bryce Lee4e4a3ec2017-09-27 08:25:03 -0700364 final WindowManagerService service = WindowTestUtils.getMockWindowManagerService();
Bryce Lee04ab3462017-04-10 15:06:33 -0700365
366 doAnswer((InvocationOnMock invocationOnMock) -> {
367 final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
368 if (runnable != null) {
369 runnable.run();
370 }
371 return null;
372 }).when(service).inSurfaceTransaction(any());
373
374 return service;
375 }
376
Bryce Leeaf691c02017-03-20 14:20:22 -0700377 /**
Bryce Lee4e4a3ec2017-09-27 08:25:03 -0700378 * Overrided of {@link ActivityStack} that tracks test metrics, such as the number of times a
Bryce Leeaf691c02017-03-20 14:20:22 -0700379 * method is called. Note that its functionality depends on the implementations of the
380 * construction arguments.
381 */
382 protected static class TestActivityStack<T extends StackWindowController>
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700383 extends ActivityStack<T> {
Bryce Leeaf691c02017-03-20 14:20:22 -0700384 private int mOnActivityRemovedFromStackCount = 0;
385 private T mContainerController;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700386
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700387 static final int IS_TRANSLUCENT_UNSET = 0;
388 static final int IS_TRANSLUCENT_FALSE = 1;
389 static final int IS_TRANSLUCENT_TRUE = 2;
390 private int mIsTranslucent = IS_TRANSLUCENT_UNSET;
391
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700392 TestActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700393 int windowingMode, int activityType, boolean onTop) {
394 super(display, stackId, supervisor, windowingMode, activityType, onTop);
Bryce Leeaf691c02017-03-20 14:20:22 -0700395 }
396
397 @Override
398 void onActivityRemovedFromStack(ActivityRecord r) {
399 mOnActivityRemovedFromStackCount++;
400 super.onActivityRemovedFromStack(r);
401 }
402
403 // Returns the number of times {@link #onActivityRemovedFromStack} has been called
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700404 int onActivityRemovedFromStackInvocationCount() {
Bryce Leeaf691c02017-03-20 14:20:22 -0700405 return mOnActivityRemovedFromStackCount;
406 }
407
408 @Override
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700409 protected T createStackWindowController(int displayId, boolean onTop, Rect outBounds) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700410 mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController();
411 return mContainerController;
412 }
413
414 @Override
415 T getWindowContainerController() {
416 return mContainerController;
417 }
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700418
419 void setIsTranslucent(boolean isTranslucent) {
420 mIsTranslucent = isTranslucent ? IS_TRANSLUCENT_TRUE : IS_TRANSLUCENT_FALSE;
421 }
422
423 @Override
Wale Ogunwale66e16852017-10-19 13:35:52 -0700424 boolean isStackTranslucent(ActivityRecord starting) {
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700425 switch (mIsTranslucent) {
426 case IS_TRANSLUCENT_TRUE:
427 return true;
428 case IS_TRANSLUCENT_FALSE:
429 return false;
430 case IS_TRANSLUCENT_UNSET:
431 default:
Wale Ogunwale66e16852017-10-19 13:35:52 -0700432 return super.isStackTranslucent(starting);
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700433 }
434 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700435 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700436}