blob: 08270844203290a6d17d1af98857be08202e0ba6 [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
19import static org.mockito.Mockito.mock;
Bryce Lee04ab3462017-04-10 15:06:33 -070020import static org.mockito.Mockito.doReturn;
21import static org.mockito.Mockito.any;
22import static org.mockito.Mockito.doAnswer;
23
24import org.mockito.invocation.InvocationOnMock;
Bryce Leeaf691c02017-03-20 14:20:22 -070025
Bryce Lee840c5662017-04-13 10:02:51 -070026import android.app.ActivityManager;
Bryce Leeaf691c02017-03-20 14:20:22 -070027import android.content.ComponentName;
28import android.content.Context;
29import android.content.Intent;
30import android.content.pm.ActivityInfo;
31import android.content.pm.ApplicationInfo;
32import android.content.res.Configuration;
33import android.graphics.Rect;
Bryce Lee3115bdf2017-04-05 08:39:40 -070034import android.os.HandlerThread;
Bryce Leeaf691c02017-03-20 14:20:22 -070035import android.os.Looper;
36import android.support.test.InstrumentationRegistry;
37import com.android.server.AttributeCache;
38import com.android.server.wm.AppWindowContainerController;
39import com.android.server.wm.StackWindowController;
40
Bryce Lee04ab3462017-04-10 15:06:33 -070041import com.android.server.wm.TaskWindowContainerController;
Bryce Leeaf691c02017-03-20 14:20:22 -070042import com.android.server.wm.WindowManagerService;
43import com.android.server.wm.WindowTestUtils;
Bryce Lee3115bdf2017-04-05 08:39:40 -070044import org.junit.After;
Bryce Leeaf691c02017-03-20 14:20:22 -070045import org.junit.Before;
46import org.mockito.MockitoAnnotations;
47
48/**
49 * A base class to handle common operations in activity related unit tests.
50 */
51public class ActivityTestsBase {
52 private final Context mContext = InstrumentationRegistry.getContext();
Bryce Lee3115bdf2017-04-05 08:39:40 -070053 private HandlerThread mHandlerThread;
Bryce Leeaf691c02017-03-20 14:20:22 -070054
55 // Grabbing an instance of {@link WindowManagerService} creates it if not present so this must
56 // be called at before any tests.
57 private final WindowManagerService mWms = WindowTestUtils.getWindowManagerService(mContext);
58
59 @Before
60 public void setUp() throws Exception {
61 MockitoAnnotations.initMocks(this);
Bryce Lee3115bdf2017-04-05 08:39:40 -070062 mHandlerThread = new HandlerThread("ActivityTestsBaseThread");
63 mHandlerThread.start();
64 }
Bryce Leeaf691c02017-03-20 14:20:22 -070065
Bryce Lee3115bdf2017-04-05 08:39:40 -070066 @After
67 public void tearDown() {
68 mHandlerThread.quitSafely();
Bryce Leeaf691c02017-03-20 14:20:22 -070069 }
70
71 protected ActivityManagerService createActivityManagerService() {
Bryce Lee840c5662017-04-13 10:02:51 -070072 final ActivityManagerService service = new TestActivityManagerService(mContext);
Bryce Lee04ab3462017-04-10 15:06:33 -070073 service.mWindowManager = WindowTestUtils.getMockWindowManagerService();
Bryce Lee840c5662017-04-13 10:02:51 -070074 return service;
Bryce Leeaf691c02017-03-20 14:20:22 -070075 }
76
Bryce Lee04ab3462017-04-10 15:06:33 -070077 protected static ActivityStack createActivityStack(ActivityManagerService service,
Bryce Leeaf691c02017-03-20 14:20:22 -070078 int stackId, int displayId, boolean onTop) {
79 if (service.mStackSupervisor instanceof TestActivityStackSupervisor) {
Bryce Lee04ab3462017-04-10 15:06:33 -070080 return ((TestActivityStackSupervisor) service.mStackSupervisor)
Bryce Lee840c5662017-04-13 10:02:51 -070081 .createTestStack(service, stackId, onTop);
Bryce Leeaf691c02017-03-20 14:20:22 -070082 }
83
84 return null;
85 }
86
87 protected static ActivityRecord createActivity(ActivityManagerService service,
88 ComponentName component, TaskRecord task) {
89 Intent intent = new Intent();
90 intent.setComponent(component);
91 final ActivityInfo aInfo = new ActivityInfo();
92 aInfo.applicationInfo = new ApplicationInfo();
93 aInfo.applicationInfo.packageName = component.getPackageName();
94 AttributeCache.init(service.mContext);
95 final ActivityRecord activity = new ActivityRecord(service, null /* caller */,
96 0 /* launchedFromPid */, 0, null, intent, null,
97 aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
98 0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
99 service.mStackSupervisor, null /* container */, null /* options */,
100 null /* sourceRecord */);
101 activity.mWindowContainerController = mock(AppWindowContainerController.class);
102
103 if (task != null) {
104 task.addActivityToTop(activity);
105 }
106
107 return activity;
108 }
109
110 protected static TaskRecord createTask(ActivityManagerService service,
Bryce Lee04ab3462017-04-10 15:06:33 -0700111 ComponentName component, int stackId) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700112 final ActivityInfo aInfo = new ActivityInfo();
113 aInfo.applicationInfo = new ApplicationInfo();
114 aInfo.applicationInfo.packageName = component.getPackageName();
115
116 Intent intent = new Intent();
117 intent.setComponent(component);
118
119 final TaskRecord task = new TaskRecord(service, 0, aInfo, intent /*intent*/,
Bryce Lee840c5662017-04-13 10:02:51 -0700120 null /*_taskDescription*/, new ActivityManager.TaskThumbnailInfo());
Bryce Lee04ab3462017-04-10 15:06:33 -0700121 final ActivityStack stack = service.mStackSupervisor.getStack(stackId,
122 true /*createStaticStackIfNeeded*/, true /*onTop*/);
Bryce Leeaf691c02017-03-20 14:20:22 -0700123 stack.addTask(task, true, "creating test task");
124 task.setStack(stack);
Bryce Lee04ab3462017-04-10 15:06:33 -0700125 task.setWindowContainerController(mock(TaskWindowContainerController.class));
Bryce Leeaf691c02017-03-20 14:20:22 -0700126
127 return task;
128 }
129
Bryce Lee04ab3462017-04-10 15:06:33 -0700130
Bryce Leeaf691c02017-03-20 14:20:22 -0700131 /**
132 * An {@link ActivityManagerService} subclass which provides a test
133 * {@link ActivityStackSupervisor}.
134 */
135 protected static class TestActivityManagerService extends ActivityManagerService {
136 public TestActivityManagerService(Context context) {
137 super(context);
Bryce Lee04ab3462017-04-10 15:06:33 -0700138 mSupportsMultiWindow = true;
139 mSupportsMultiDisplay = true;
140 mWindowManager = WindowTestUtils.getWindowManagerService(context);
Bryce Leeaf691c02017-03-20 14:20:22 -0700141 }
142
143 @Override
144 protected ActivityStackSupervisor createStackSupervisor() {
Bryce Lee3115bdf2017-04-05 08:39:40 -0700145 return new TestActivityStackSupervisor(this, mHandlerThread.getLooper());
Bryce Leeaf691c02017-03-20 14:20:22 -0700146 }
147 }
148
149 /**
150 * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on
151 * setup not available in the test environment. Also specifies an injector for
152 */
153 protected static class TestActivityStackSupervisor extends ActivityStackSupervisor {
154 public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
155 super(service, looper);
Bryce Lee04ab3462017-04-10 15:06:33 -0700156 mWindowManager = prepareMockWindowManager();
157 }
158
159 // No home stack is set.
160 @Override
161 void moveHomeStackToFront(String reason) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700162 }
163
164 // Invoked during {@link ActivityStack} creation.
165 @Override
166 void updateUIDsPresentOnDisplay() {
167 }
168
Bryce Lee04ab3462017-04-10 15:06:33 -0700169 // Just return the current front task.
170 @Override
171 ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus) {
172 return mFocusedStack;
173 }
174
175 // Called when moving activity to pinned stack.
176 @Override
177 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
178 boolean preserveWindows) {
179 }
180
181 public <T extends ActivityStack> T createTestStack(ActivityManagerService service,
182 int stackId, boolean onTop) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700183 final ActivityDisplay display = new ActivityDisplay();
184 final TestActivityContainer container =
Bryce Lee840c5662017-04-13 10:02:51 -0700185 new TestActivityContainer(service, stackId, display, onTop);
Bryce Lee04ab3462017-04-10 15:06:33 -0700186 mActivityContainers.put(stackId, container);
187 return (T) container.getStack();
188 }
189
190 @Override
191 protected <T extends ActivityStack> T getStack(int stackId,
192 boolean createStaticStackIfNeeded, boolean createOnTop) {
193 final T stack = super.getStack(stackId, createStaticStackIfNeeded, createOnTop);
194
195 if (stack != null || !createStaticStackIfNeeded) {
196 return stack;
197 }
198
199 return createTestStack(mService, stackId, createOnTop);
Bryce Leeaf691c02017-03-20 14:20:22 -0700200 }
201
202 private class TestActivityContainer extends ActivityContainer {
Bryce Lee04ab3462017-04-10 15:06:33 -0700203 private final ActivityManagerService mService;
204
Bryce Lee840c5662017-04-13 10:02:51 -0700205 private boolean mOnTop;
Bryce Lee04ab3462017-04-10 15:06:33 -0700206 private int mStackId;
207 private ActivityStack mStack;
Bryce Lee840c5662017-04-13 10:02:51 -0700208
209 TestActivityContainer(ActivityManagerService service, int stackId,
210 ActivityDisplay activityDisplay, boolean onTop) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700211 super(stackId, activityDisplay, onTop);
Bryce Lee840c5662017-04-13 10:02:51 -0700212 mService = service;
Bryce Leeaf691c02017-03-20 14:20:22 -0700213 }
214
215 @Override
216 protected void createStack(int stackId, boolean onTop) {
Bryce Lee840c5662017-04-13 10:02:51 -0700217 // normally stack creation is done here. However we need to do it on demand since
218 // we cannot set {@link mService} by the time the super constructor calling this
219 // method is invoked.
220 mOnTop = onTop;
Bryce Lee04ab3462017-04-10 15:06:33 -0700221 mStackId = stackId;
Bryce Leeaf691c02017-03-20 14:20:22 -0700222 }
223
Bryce Lee04ab3462017-04-10 15:06:33 -0700224 public ActivityStack getStack() {
Bryce Lee840c5662017-04-13 10:02:51 -0700225 if (mStack == null) {
Bryce Lee04ab3462017-04-10 15:06:33 -0700226 final RecentTasks recents =
227 new RecentTasks(mService, mService.mStackSupervisor);
228 mStack = mStackId == ActivityManager.StackId.PINNED_STACK_ID
229 ? new PinnedActivityStack(this, recents, mOnTop)
230 : new TestActivityStack(this, recents, mOnTop);
Bryce Lee840c5662017-04-13 10:02:51 -0700231 }
232
Bryce Leeaf691c02017-03-20 14:20:22 -0700233 return mStack;
234 }
235 }
236 }
237
Bryce Lee04ab3462017-04-10 15:06:33 -0700238 private static WindowManagerService prepareMockWindowManager() {
239 final WindowManagerService service = mock(WindowManagerService.class);
240
241 doAnswer((InvocationOnMock invocationOnMock) -> {
242 final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
243 if (runnable != null) {
244 runnable.run();
245 }
246 return null;
247 }).when(service).inSurfaceTransaction(any());
248
249 return service;
250 }
251
252 protected interface ActivityStackReporter {
253 int onActivityRemovedFromStackInvocationCount();
254 }
255
Bryce Leeaf691c02017-03-20 14:20:22 -0700256 /**
257 * Override of {@link ActivityStack} that tracks test metrics, such as the number of times a
258 * method is called. Note that its functionality depends on the implementations of the
259 * construction arguments.
260 */
261 protected static class TestActivityStack<T extends StackWindowController>
Bryce Lee04ab3462017-04-10 15:06:33 -0700262 extends ActivityStack<T> implements ActivityStackReporter {
Bryce Leeaf691c02017-03-20 14:20:22 -0700263 private int mOnActivityRemovedFromStackCount = 0;
264 private T mContainerController;
265 TestActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer,
266 RecentTasks recentTasks, boolean onTop) {
267 super(activityContainer, recentTasks, onTop);
268 }
269
270 @Override
271 void onActivityRemovedFromStack(ActivityRecord r) {
272 mOnActivityRemovedFromStackCount++;
273 super.onActivityRemovedFromStack(r);
274 }
275
276 // Returns the number of times {@link #onActivityRemovedFromStack} has been called
Bryce Lee04ab3462017-04-10 15:06:33 -0700277 @Override
Bryce Leeaf691c02017-03-20 14:20:22 -0700278 public int onActivityRemovedFromStackInvocationCount() {
279 return mOnActivityRemovedFromStackCount;
280 }
281
282 @Override
283 protected T createStackWindowController(int displayId, boolean onTop,
284 Rect outBounds) {
285 mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController();
286 return mContainerController;
287 }
288
289 @Override
290 T getWindowContainerController() {
291 return mContainerController;
292 }
293 }
294
Bryce Lee04ab3462017-04-10 15:06:33 -0700295
Bryce Leeaf691c02017-03-20 14:20:22 -0700296 protected static class ActivityStackBuilder {
297 private boolean mOnTop = true;
298 private int mStackId = 0;
299 private int mDisplayId = 1;
300
301 private final ActivityManagerService mService;
302
303 public ActivityStackBuilder(ActivityManagerService ams) {
304 mService = ams;
305 }
306
307 public ActivityStackBuilder setOnTop(boolean onTop) {
308 mOnTop = onTop;
309 return this;
310 }
311
312 public ActivityStackBuilder setStackId(int id) {
313 mStackId = id;
314 return this;
315 }
316
317 public ActivityStackBuilder setDisplayId(int id) {
318 mDisplayId = id;
319 return this;
320 }
321
Bryce Lee04ab3462017-04-10 15:06:33 -0700322 public ActivityStack build() {
Bryce Leeaf691c02017-03-20 14:20:22 -0700323 return createActivityStack(mService, mStackId, mDisplayId, mOnTop);
324 }
325 }
326}