blob: f04b6d89d51e2579860dba283406e6eb71d40193 [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;
44import android.support.test.InstrumentationRegistry;
45import com.android.server.AttributeCache;
46import com.android.server.wm.AppWindowContainerController;
Bryce Lee4e4a3ec2017-09-27 08:25:03 -070047import com.android.server.wm.PinnedStackWindowController;
Bryce Leeaf691c02017-03-20 14:20:22 -070048import com.android.server.wm.StackWindowController;
Bryce Lee04ab3462017-04-10 15:06:33 -070049import com.android.server.wm.TaskWindowContainerController;
Bryce Leeaf691c02017-03-20 14:20:22 -070050import com.android.server.wm.WindowManagerService;
51import com.android.server.wm.WindowTestUtils;
Bryce Lee3115bdf2017-04-05 08:39:40 -070052import org.junit.After;
Bryce Leeaf691c02017-03-20 14:20:22 -070053import org.junit.Before;
54import org.mockito.MockitoAnnotations;
55
56/**
57 * A base class to handle common operations in activity related unit tests.
58 */
59public class ActivityTestsBase {
Bryce Lee939a9a32017-10-23 10:01:21 -070060 private static boolean sOneTimeSetupDone = false;
61
Bryce Leeaf691c02017-03-20 14:20:22 -070062 private final Context mContext = InstrumentationRegistry.getContext();
Bryce Lee3115bdf2017-04-05 08:39:40 -070063 private HandlerThread mHandlerThread;
Bryce Leeaf691c02017-03-20 14:20:22 -070064
Bryce Leeaf691c02017-03-20 14:20:22 -070065 @Before
66 public void setUp() throws Exception {
Bryce Lee939a9a32017-10-23 10:01:21 -070067 if (!sOneTimeSetupDone) {
68 sOneTimeSetupDone = true;
69
70 // Allows to mock package local classes and methods
71 System.setProperty("dexmaker.share_classloader", "true");
72 MockitoAnnotations.initMocks(this);
73 }
Bryce Lee3115bdf2017-04-05 08:39:40 -070074 mHandlerThread = new HandlerThread("ActivityTestsBaseThread");
75 mHandlerThread.start();
76 }
Bryce Leeaf691c02017-03-20 14:20:22 -070077
Bryce Lee3115bdf2017-04-05 08:39:40 -070078 @After
79 public void tearDown() {
80 mHandlerThread.quitSafely();
Bryce Leeaf691c02017-03-20 14:20:22 -070081 }
82
83 protected ActivityManagerService createActivityManagerService() {
Winson Chung3f0e59a2017-10-25 10:19:05 -070084 return setupActivityManagerService(new TestActivityManagerService(mContext));
85 }
86
87 protected ActivityManagerService setupActivityManagerService(ActivityManagerService service) {
88 service = spy(service);
Bryce Lee4e4a3ec2017-09-27 08:25:03 -070089 service.mWindowManager = prepareMockWindowManager();
Bryce Lee840c5662017-04-13 10:02:51 -070090 return service;
Bryce Leeaf691c02017-03-20 14:20:22 -070091 }
92
Bryce Lee18d51592017-10-25 10:22:19 -070093 /**
94 * Builder for creating new activities.
95 */
96 protected static class ActivityBuilder {
97 // An id appended to the end of the component name to make it unique
98 private static int sCurrentActivityId = 0;
Bryce Lee9f6affd2017-09-01 09:18:35 -070099
Bryce Lee18d51592017-10-25 10:22:19 -0700100 // Default package name
101 private static final String DEFAULT_PACKAGE = "com.foo";
Bryce Leeaf691c02017-03-20 14:20:22 -0700102
Bryce Lee18d51592017-10-25 10:22:19 -0700103 // Default base activity name
104 private static final String DEFAULT_BASE_ACTIVITY_NAME = ".BarActivity";
105
106 private final ActivityManagerService mService;
107
108 private ComponentName mComponent;
109 private TaskRecord mTaskRecord;
110 private int mUid;
111 private boolean mCreateTask;
112 private ActivityStack mStack;
113
114 ActivityBuilder(ActivityManagerService service) {
115 mService = service;
Bryce Leeaf691c02017-03-20 14:20:22 -0700116 }
117
Bryce Lee18d51592017-10-25 10:22:19 -0700118 ActivityBuilder setComponent(ComponentName component) {
119 mComponent = component;
120 return this;
121 }
122
123 ActivityBuilder setTask(TaskRecord task) {
124 mTaskRecord = task;
125 return this;
126 }
127
128 ActivityBuilder setStack(ActivityStack stack) {
129 mStack = stack;
130 return this;
131 }
132
133 ActivityBuilder setCreateTask(boolean createTask) {
134 mCreateTask = createTask;
135 return this;
136 }
137
138 ActivityBuilder setUid(int uid) {
139 mUid = uid;
140 return this;
141 }
142
143 ActivityRecord build() {
144 if (mComponent == null) {
145 final int id = sCurrentActivityId++;
146 mComponent = ComponentName.createRelative(DEFAULT_PACKAGE,
147 DEFAULT_BASE_ACTIVITY_NAME + id);
148 }
149
150 if (mCreateTask) {
151 mTaskRecord = new TaskBuilder(mService.mStackSupervisor)
152 .setComponent(mComponent)
153 .setStack(mStack).build();
154 }
155
156 Intent intent = new Intent();
157 intent.setComponent(mComponent);
158 final ActivityInfo aInfo = new ActivityInfo();
159 aInfo.applicationInfo = new ApplicationInfo();
160 aInfo.applicationInfo.packageName = mComponent.getPackageName();
161 aInfo.applicationInfo.uid = mUid;
162 AttributeCache.init(mService.mContext);
163 final ActivityRecord activity = new ActivityRecord(mService, null /* caller */,
164 0 /* launchedFromPid */, 0, null, intent, null,
165 aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
166 0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
167 mService.mStackSupervisor, null /* options */, null /* sourceRecord */);
168 activity.mWindowContainerController = mock(AppWindowContainerController.class);
169
170 if (mTaskRecord != null) {
171 mTaskRecord.addActivityToTop(activity);
172 }
173
174 return activity;
175 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700176 }
177
Bryce Lee18d51592017-10-25 10:22:19 -0700178 /**
179 * Builder for creating new tasks.
180 */
181 protected static class TaskBuilder {
182 private final ActivityStackSupervisor mSupervisor;
Winson Chung1dbc8112017-09-28 18:05:31 -0700183
Bryce Lee18d51592017-10-25 10:22:19 -0700184 private ComponentName mComponent;
185 private String mPackage;
186 private int mFlags = 0;
187 private int mTaskId = 0;
Bryce Leeaf691c02017-03-20 14:20:22 -0700188
Bryce Lee18d51592017-10-25 10:22:19 -0700189 private ActivityStack mStack;
Bryce Leeaf691c02017-03-20 14:20:22 -0700190
Bryce Lee18d51592017-10-25 10:22:19 -0700191 TaskBuilder(ActivityStackSupervisor supervisor) {
192 mSupervisor = supervisor;
193 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700194
Bryce Lee18d51592017-10-25 10:22:19 -0700195 TaskBuilder setComponent(ComponentName component) {
196 mComponent = component;
197 return this;
198 }
199
200 TaskBuilder setPackage(String packageName) {
201 mPackage = packageName;
202 return this;
203 }
204
205 TaskBuilder setFlags(int flags) {
206 mFlags = flags;
207 return this;
208 }
209
210 TaskBuilder setTaskId(int taskId) {
211 mTaskId = taskId;
212 return this;
213 }
214
215 TaskBuilder setStack(ActivityStack stack) {
216 mStack = stack;
217 return this;
218 }
219
220 TaskRecord build() {
221 if (mStack == null) {
222 mStack = mSupervisor.getDefaultDisplay().createStack(
223 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
224 }
225
226 final ActivityInfo aInfo = new ActivityInfo();
227 aInfo.applicationInfo = new ApplicationInfo();
228 aInfo.applicationInfo.packageName = mPackage;
229
230 Intent intent = new Intent();
231 intent.setComponent(mComponent);
232 intent.setFlags(mFlags);
233
234 final TaskRecord task = new TaskRecord(mSupervisor.mService, mTaskId, aInfo,
235 intent /*intent*/, null /*_taskDescription*/);
236 mSupervisor.setFocusStackUnchecked("test", mStack);
237 mStack.addTask(task, true, "creating test task");
238 task.setStack(mStack);
239 task.setWindowContainerController(mock(TaskWindowContainerController.class));
240
241 return task;
242 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700243 }
244
245 /**
246 * An {@link ActivityManagerService} subclass which provides a test
247 * {@link ActivityStackSupervisor}.
248 */
249 protected static class TestActivityManagerService extends ActivityManagerService {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700250 TestActivityManagerService(Context context) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700251 super(context);
Bryce Lee04ab3462017-04-10 15:06:33 -0700252 mSupportsMultiWindow = true;
253 mSupportsMultiDisplay = true;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700254 mSupportsSplitScreenMultiWindow = true;
255 mSupportsFreeformWindowManagement = true;
256 mSupportsPictureInPicture = true;
Bryce Lee6a0754a2017-10-10 17:53:50 -0700257 mWindowManager = WindowTestUtils.getMockWindowManagerService();
Bryce Leeaf691c02017-03-20 14:20:22 -0700258 }
259
260 @Override
Bryce Lee2a3cc462017-10-27 10:57:35 -0700261 final protected ActivityStackSupervisor createStackSupervisor() {
262 final ActivityStackSupervisor supervisor = spy(createTestSupervisor());
263
264 // No home stack is set.
265 doNothing().when(supervisor).moveHomeStackToFront(any());
266 doReturn(true).when(supervisor).moveHomeStackTaskToTop(any());
267 // Invoked during {@link ActivityStack} creation.
268 doNothing().when(supervisor).updateUIDsPresentOnDisplay();
269 // Always keep things awake.
270 doReturn(true).when(supervisor).hasAwakeDisplay();
271 // Called when moving activity to pinned stack.
272 doNothing().when(supervisor).ensureActivitiesVisibleLocked(any(), anyInt(), anyBoolean());
273 // Do not schedule idle timeouts
274 doNothing().when(supervisor).scheduleIdleTimeoutLocked(any());
275
276 supervisor.initialize();
277
278 return supervisor;
279 }
280
281 protected ActivityStackSupervisor createTestSupervisor() {
Bryce Lee3115bdf2017-04-05 08:39:40 -0700282 return new TestActivityStackSupervisor(this, mHandlerThread.getLooper());
Bryce Leeaf691c02017-03-20 14:20:22 -0700283 }
Bryce Lee29a649d2017-08-18 13:52:31 -0700284
285 @Override
286 void updateUsageStats(ActivityRecord component, boolean resumed) {
287 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700288 }
289
290 /**
291 * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on
292 * setup not available in the test environment. Also specifies an injector for
293 */
294 protected static class TestActivityStackSupervisor extends ActivityStackSupervisor {
Bryce Lee2a3cc462017-10-27 10:57:35 -0700295 private ActivityDisplay mDisplay;
Bryce Lee943ebe72017-05-04 10:19:07 -0700296
Bryce Leeaf691c02017-03-20 14:20:22 -0700297 public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
298 super(service, looper);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700299 mDisplayManager =
300 (DisplayManager) mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
Bryce Lee04ab3462017-04-10 15:06:33 -0700301 mWindowManager = prepareMockWindowManager();
Bryce Lee2a3cc462017-10-27 10:57:35 -0700302 }
303
304 @Override
305 public void initialize() {
306 super.initialize();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700307 mDisplay = new TestActivityDisplay(this, DEFAULT_DISPLAY);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700308 attachDisplay(mDisplay);
Bryce Lee04ab3462017-04-10 15:06:33 -0700309 }
310
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700311 @Override
312 ActivityDisplay getDefaultDisplay() {
313 return mDisplay;
314 }
315
Bryce Lee2a3cc462017-10-27 10:57:35 -0700316 // 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 -0700317 @Override
318 ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus) {
319 return mFocusedStack;
320 }
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700321 }
322
323 private static class TestActivityDisplay extends ActivityDisplay {
324
325 private final ActivityStackSupervisor mSupervisor;
326 TestActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
327 super(supervisor, displayId);
328 mSupervisor = supervisor;
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700329 }
330
331 @Override
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700332 <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
333 int stackId, boolean onTop) {
334 if (windowingMode == WINDOWING_MODE_PINNED) {
335 return (T) new PinnedActivityStack(this, stackId, mSupervisor, onTop) {
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700336 @Override
337 Rect getDefaultPictureInPictureBounds(float aspectRatio) {
338 return new Rect(50, 50, 100, 100);
339 }
Bryce Lee4e4a3ec2017-09-27 08:25:03 -0700340
341 @Override
342 PinnedStackWindowController createStackWindowController(int displayId,
343 boolean onTop, Rect outBounds) {
344 return mock(PinnedStackWindowController.class);
345 }
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700346 };
347 } else {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700348 return (T) new TestActivityStack(
349 this, stackId, mSupervisor, windowingMode, activityType, onTop);
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700350 }
Bryce Lee04ab3462017-04-10 15:06:33 -0700351 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700352 }
353
Bryce Lee04ab3462017-04-10 15:06:33 -0700354 private static WindowManagerService prepareMockWindowManager() {
Bryce Lee4e4a3ec2017-09-27 08:25:03 -0700355 final WindowManagerService service = WindowTestUtils.getMockWindowManagerService();
Bryce Lee04ab3462017-04-10 15:06:33 -0700356
357 doAnswer((InvocationOnMock invocationOnMock) -> {
358 final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
359 if (runnable != null) {
360 runnable.run();
361 }
362 return null;
363 }).when(service).inSurfaceTransaction(any());
364
365 return service;
366 }
367
Bryce Leeaf691c02017-03-20 14:20:22 -0700368 /**
Bryce Lee4e4a3ec2017-09-27 08:25:03 -0700369 * Overrided of {@link ActivityStack} that tracks test metrics, such as the number of times a
Bryce Leeaf691c02017-03-20 14:20:22 -0700370 * method is called. Note that its functionality depends on the implementations of the
371 * construction arguments.
372 */
373 protected static class TestActivityStack<T extends StackWindowController>
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700374 extends ActivityStack<T> {
Bryce Leeaf691c02017-03-20 14:20:22 -0700375 private int mOnActivityRemovedFromStackCount = 0;
376 private T mContainerController;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700377
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700378 static final int IS_TRANSLUCENT_UNSET = 0;
379 static final int IS_TRANSLUCENT_FALSE = 1;
380 static final int IS_TRANSLUCENT_TRUE = 2;
381 private int mIsTranslucent = IS_TRANSLUCENT_UNSET;
382
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700383 TestActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700384 int windowingMode, int activityType, boolean onTop) {
385 super(display, stackId, supervisor, windowingMode, activityType, onTop);
Bryce Leeaf691c02017-03-20 14:20:22 -0700386 }
387
388 @Override
389 void onActivityRemovedFromStack(ActivityRecord r) {
390 mOnActivityRemovedFromStackCount++;
391 super.onActivityRemovedFromStack(r);
392 }
393
394 // Returns the number of times {@link #onActivityRemovedFromStack} has been called
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700395 int onActivityRemovedFromStackInvocationCount() {
Bryce Leeaf691c02017-03-20 14:20:22 -0700396 return mOnActivityRemovedFromStackCount;
397 }
398
399 @Override
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700400 protected T createStackWindowController(int displayId, boolean onTop, Rect outBounds) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700401 mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController();
402 return mContainerController;
403 }
404
405 @Override
406 T getWindowContainerController() {
407 return mContainerController;
408 }
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700409
410 void setIsTranslucent(boolean isTranslucent) {
411 mIsTranslucent = isTranslucent ? IS_TRANSLUCENT_TRUE : IS_TRANSLUCENT_FALSE;
412 }
413
414 @Override
Wale Ogunwale66e16852017-10-19 13:35:52 -0700415 boolean isStackTranslucent(ActivityRecord starting) {
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700416 switch (mIsTranslucent) {
417 case IS_TRANSLUCENT_TRUE:
418 return true;
419 case IS_TRANSLUCENT_FALSE:
420 return false;
421 case IS_TRANSLUCENT_UNSET:
422 default:
Wale Ogunwale66e16852017-10-19 13:35:52 -0700423 return super.isStackTranslucent(starting);
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700424 }
425 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700426 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700427}