blob: 6caa60b5a01008bcc15712e0f2c39b42c678af4e [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
Andrii Kulianb1cdb102017-07-13 15:33:06 -070019import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070020import static android.view.Display.DEFAULT_DISPLAY;
Bryce Leeaf691c02017-03-20 14:20:22 -070021import static org.mockito.Mockito.mock;
Bryce Lee04ab3462017-04-10 15:06:33 -070022import static org.mockito.Mockito.doReturn;
23import static org.mockito.Mockito.any;
24import static org.mockito.Mockito.doAnswer;
25
26import org.mockito.invocation.InvocationOnMock;
Bryce Leeaf691c02017-03-20 14:20:22 -070027
28import android.content.ComponentName;
29import android.content.Context;
30import android.content.Intent;
31import android.content.pm.ActivityInfo;
32import android.content.pm.ApplicationInfo;
33import android.content.res.Configuration;
34import android.graphics.Rect;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070035import android.hardware.display.DisplayManager;
Bryce Lee3115bdf2017-04-05 08:39:40 -070036import android.os.HandlerThread;
Bryce Leeaf691c02017-03-20 14:20:22 -070037import android.os.Looper;
38import android.support.test.InstrumentationRegistry;
39import com.android.server.AttributeCache;
40import com.android.server.wm.AppWindowContainerController;
41import com.android.server.wm.StackWindowController;
42
Bryce Lee04ab3462017-04-10 15:06:33 -070043import com.android.server.wm.TaskWindowContainerController;
Bryce Leeaf691c02017-03-20 14:20:22 -070044import com.android.server.wm.WindowManagerService;
45import com.android.server.wm.WindowTestUtils;
Bryce Lee3115bdf2017-04-05 08:39:40 -070046import org.junit.After;
Bryce Leeaf691c02017-03-20 14:20:22 -070047import org.junit.Before;
48import org.mockito.MockitoAnnotations;
49
50/**
51 * A base class to handle common operations in activity related unit tests.
52 */
53public class ActivityTestsBase {
54 private final Context mContext = InstrumentationRegistry.getContext();
Bryce Lee3115bdf2017-04-05 08:39:40 -070055 private HandlerThread mHandlerThread;
Bryce Leeaf691c02017-03-20 14:20:22 -070056
57 // Grabbing an instance of {@link WindowManagerService} creates it if not present so this must
58 // be called at before any tests.
59 private final WindowManagerService mWms = WindowTestUtils.getWindowManagerService(mContext);
60
61 @Before
62 public void setUp() throws Exception {
63 MockitoAnnotations.initMocks(this);
Bryce Lee3115bdf2017-04-05 08:39:40 -070064 mHandlerThread = new HandlerThread("ActivityTestsBaseThread");
65 mHandlerThread.start();
66 }
Bryce Leeaf691c02017-03-20 14:20:22 -070067
Bryce Lee3115bdf2017-04-05 08:39:40 -070068 @After
69 public void tearDown() {
70 mHandlerThread.quitSafely();
Bryce Leeaf691c02017-03-20 14:20:22 -070071 }
72
73 protected ActivityManagerService createActivityManagerService() {
Bryce Lee840c5662017-04-13 10:02:51 -070074 final ActivityManagerService service = new TestActivityManagerService(mContext);
Bryce Lee04ab3462017-04-10 15:06:33 -070075 service.mWindowManager = WindowTestUtils.getMockWindowManagerService();
Bryce Lee840c5662017-04-13 10:02:51 -070076 return service;
Bryce Leeaf691c02017-03-20 14:20:22 -070077 }
78
Bryce Lee04ab3462017-04-10 15:06:33 -070079 protected static ActivityStack createActivityStack(ActivityManagerService service,
Bryce Leeaf691c02017-03-20 14:20:22 -070080 int stackId, int displayId, boolean onTop) {
81 if (service.mStackSupervisor instanceof TestActivityStackSupervisor) {
Bryce Lee04ab3462017-04-10 15:06:33 -070082 return ((TestActivityStackSupervisor) service.mStackSupervisor)
Andrii Kulianb1cdb102017-07-13 15:33:06 -070083 .createTestStack(stackId, onTop);
Bryce Leeaf691c02017-03-20 14:20:22 -070084 }
85
86 return null;
87 }
88
89 protected static ActivityRecord createActivity(ActivityManagerService service,
90 ComponentName component, TaskRecord task) {
Bryce Lee9f6affd2017-09-01 09:18:35 -070091 return createActivity(service, component, task, 0 /* userId */);
92 }
93
94 protected static ActivityRecord createActivity(ActivityManagerService service,
95 ComponentName component, TaskRecord task, int uid) {
Bryce Leeaf691c02017-03-20 14:20:22 -070096 Intent intent = new Intent();
97 intent.setComponent(component);
98 final ActivityInfo aInfo = new ActivityInfo();
99 aInfo.applicationInfo = new ApplicationInfo();
100 aInfo.applicationInfo.packageName = component.getPackageName();
Bryce Lee9f6affd2017-09-01 09:18:35 -0700101 aInfo.applicationInfo.uid = uid;
Bryce Leeaf691c02017-03-20 14:20:22 -0700102 AttributeCache.init(service.mContext);
103 final ActivityRecord activity = new ActivityRecord(service, null /* caller */,
104 0 /* launchedFromPid */, 0, null, intent, null,
105 aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
106 0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700107 service.mStackSupervisor, null /* options */, null /* sourceRecord */);
Bryce Leeaf691c02017-03-20 14:20:22 -0700108 activity.mWindowContainerController = mock(AppWindowContainerController.class);
109
110 if (task != null) {
111 task.addActivityToTop(activity);
112 }
113
114 return activity;
115 }
116
117 protected static TaskRecord createTask(ActivityManagerService service,
Bryce Lee04ab3462017-04-10 15:06:33 -0700118 ComponentName component, int stackId) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700119 final ActivityInfo aInfo = new ActivityInfo();
120 aInfo.applicationInfo = new ApplicationInfo();
121 aInfo.applicationInfo.packageName = component.getPackageName();
122
123 Intent intent = new Intent();
124 intent.setComponent(component);
125
126 final TaskRecord task = new TaskRecord(service, 0, aInfo, intent /*intent*/,
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200127 null /*_taskDescription*/);
Bryce Lee04ab3462017-04-10 15:06:33 -0700128 final ActivityStack stack = service.mStackSupervisor.getStack(stackId,
129 true /*createStaticStackIfNeeded*/, true /*onTop*/);
Andrii Kulian3a1619d2017-07-07 14:38:09 -0700130 service.mStackSupervisor.setFocusStackUnchecked("test", stack);
Bryce Leeaf691c02017-03-20 14:20:22 -0700131 stack.addTask(task, true, "creating test task");
132 task.setStack(stack);
Bryce Lee04ab3462017-04-10 15:06:33 -0700133 task.setWindowContainerController(mock(TaskWindowContainerController.class));
Bryce Leeaf691c02017-03-20 14:20:22 -0700134
135 return task;
136 }
137
Bryce Lee04ab3462017-04-10 15:06:33 -0700138
Bryce Leeaf691c02017-03-20 14:20:22 -0700139 /**
140 * An {@link ActivityManagerService} subclass which provides a test
141 * {@link ActivityStackSupervisor}.
142 */
143 protected static class TestActivityManagerService extends ActivityManagerService {
144 public TestActivityManagerService(Context context) {
145 super(context);
Bryce Lee04ab3462017-04-10 15:06:33 -0700146 mSupportsMultiWindow = true;
147 mSupportsMultiDisplay = true;
148 mWindowManager = WindowTestUtils.getWindowManagerService(context);
Bryce Leeaf691c02017-03-20 14:20:22 -0700149 }
150
151 @Override
152 protected ActivityStackSupervisor createStackSupervisor() {
Bryce Lee3115bdf2017-04-05 08:39:40 -0700153 return new TestActivityStackSupervisor(this, mHandlerThread.getLooper());
Bryce Leeaf691c02017-03-20 14:20:22 -0700154 }
Bryce Lee29a649d2017-08-18 13:52:31 -0700155
156 @Override
157 void updateUsageStats(ActivityRecord component, boolean resumed) {
158 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700159 }
160
161 /**
162 * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on
163 * setup not available in the test environment. Also specifies an injector for
164 */
165 protected static class TestActivityStackSupervisor extends ActivityStackSupervisor {
Bryce Lee943ebe72017-05-04 10:19:07 -0700166 private final ActivityDisplay mDisplay;
Bryce Lee1533b2b2017-09-14 17:06:41 -0700167 private boolean mLastResizeable;
Bryce Lee943ebe72017-05-04 10:19:07 -0700168
Bryce Leeaf691c02017-03-20 14:20:22 -0700169 public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
170 super(service, looper);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700171 mDisplayManager =
172 (DisplayManager) mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
Bryce Lee04ab3462017-04-10 15:06:33 -0700173 mWindowManager = prepareMockWindowManager();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700174 mDisplay = new ActivityDisplay(this, DEFAULT_DISPLAY);
175 attachDisplay(mDisplay);
Bryce Lee04ab3462017-04-10 15:06:33 -0700176 }
177
Bryce Lee1533b2b2017-09-14 17:06:41 -0700178 // TODO: Use Mockito spy instead. Currently not possible due to TestActivityStackSupervisor
179 // access to ActivityDisplay
180 @Override
181 boolean canPlaceEntityOnDisplay(int displayId, boolean resizeable, int callingPid,
182 int callingUid, ActivityInfo activityInfo) {
183 mLastResizeable = resizeable;
184 return super.canPlaceEntityOnDisplay(displayId, resizeable, callingPid, callingUid,
185 activityInfo);
186 }
187
188 // TODO: remove and use Mockito verify once {@link #canPlaceEntityOnDisplay} override is
189 // removed.
190 public boolean getLastResizeableFromCanPlaceEntityOnDisplay() {
191 return mLastResizeable;
192 }
193
Bryce Lee04ab3462017-04-10 15:06:33 -0700194 // No home stack is set.
195 @Override
196 void moveHomeStackToFront(String reason) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700197 }
198
Bryce Lee3345c4e2017-04-25 07:40:41 -0700199 @Override
200 boolean moveHomeStackTaskToTop(String reason) {
201 return true;
202 }
203
Bryce Leeaf691c02017-03-20 14:20:22 -0700204 // Invoked during {@link ActivityStack} creation.
205 @Override
206 void updateUIDsPresentOnDisplay() {
207 }
208
Bryce Lee04ab3462017-04-10 15:06:33 -0700209 // Just return the current front task.
210 @Override
211 ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus) {
212 return mFocusedStack;
213 }
214
215 // Called when moving activity to pinned stack.
216 @Override
217 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
218 boolean preserveWindows) {
219 }
220
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700221 <T extends ActivityStack> T createTestStack(int stackId, boolean onTop) {
222 return (T) createStack(stackId, mDisplay, onTop);
223 }
224
225 @Override
226 ActivityStack createStack(int stackId, ActivityDisplay display, boolean onTop) {
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700227 if (stackId == PINNED_STACK_ID) {
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700228 return new PinnedActivityStack(display, stackId, this, onTop) {
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700229 @Override
230 Rect getDefaultPictureInPictureBounds(float aspectRatio) {
231 return new Rect(50, 50, 100, 100);
232 }
233 };
234 } else {
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700235 return new TestActivityStack(display, stackId, this, onTop);
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700236 }
Bryce Lee04ab3462017-04-10 15:06:33 -0700237 }
238
239 @Override
240 protected <T extends ActivityStack> T getStack(int stackId,
241 boolean createStaticStackIfNeeded, boolean createOnTop) {
242 final T stack = super.getStack(stackId, createStaticStackIfNeeded, createOnTop);
243
244 if (stack != null || !createStaticStackIfNeeded) {
245 return stack;
246 }
247
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700248 return createTestStack(stackId, createOnTop);
Bryce Leeaf691c02017-03-20 14:20:22 -0700249 }
David Stevens9440dc82017-03-16 19:00:20 -0700250
251 // Always keep things awake
252 @Override
253 boolean hasAwakeDisplay() {
254 return true;
255 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700256 }
257
Bryce Lee04ab3462017-04-10 15:06:33 -0700258 private static WindowManagerService prepareMockWindowManager() {
259 final WindowManagerService service = mock(WindowManagerService.class);
260
261 doAnswer((InvocationOnMock invocationOnMock) -> {
262 final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
263 if (runnable != null) {
264 runnable.run();
265 }
266 return null;
267 }).when(service).inSurfaceTransaction(any());
268
269 return service;
270 }
271
272 protected interface ActivityStackReporter {
273 int onActivityRemovedFromStackInvocationCount();
274 }
275
Bryce Leeaf691c02017-03-20 14:20:22 -0700276 /**
277 * Override of {@link ActivityStack} that tracks test metrics, such as the number of times a
278 * method is called. Note that its functionality depends on the implementations of the
279 * construction arguments.
280 */
281 protected static class TestActivityStack<T extends StackWindowController>
Bryce Lee04ab3462017-04-10 15:06:33 -0700282 extends ActivityStack<T> implements ActivityStackReporter {
Bryce Leeaf691c02017-03-20 14:20:22 -0700283 private int mOnActivityRemovedFromStackCount = 0;
284 private T mContainerController;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700285 TestActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
286 boolean onTop) {
287 super(display, stackId, supervisor, onTop);
Bryce Leeaf691c02017-03-20 14:20:22 -0700288 }
289
290 @Override
291 void onActivityRemovedFromStack(ActivityRecord r) {
292 mOnActivityRemovedFromStackCount++;
293 super.onActivityRemovedFromStack(r);
294 }
295
296 // Returns the number of times {@link #onActivityRemovedFromStack} has been called
Bryce Lee04ab3462017-04-10 15:06:33 -0700297 @Override
Bryce Leeaf691c02017-03-20 14:20:22 -0700298 public int onActivityRemovedFromStackInvocationCount() {
299 return mOnActivityRemovedFromStackCount;
300 }
301
302 @Override
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700303 protected T createStackWindowController(int displayId, boolean onTop, Rect outBounds) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700304 mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController();
305 return mContainerController;
306 }
307
308 @Override
309 T getWindowContainerController() {
310 return mContainerController;
311 }
312 }
313
Bryce Lee04ab3462017-04-10 15:06:33 -0700314
Bryce Leeaf691c02017-03-20 14:20:22 -0700315 protected static class ActivityStackBuilder {
316 private boolean mOnTop = true;
317 private int mStackId = 0;
318 private int mDisplayId = 1;
319
320 private final ActivityManagerService mService;
321
322 public ActivityStackBuilder(ActivityManagerService ams) {
323 mService = ams;
324 }
325
326 public ActivityStackBuilder setOnTop(boolean onTop) {
327 mOnTop = onTop;
328 return this;
329 }
330
331 public ActivityStackBuilder setStackId(int id) {
332 mStackId = id;
333 return this;
334 }
335
336 public ActivityStackBuilder setDisplayId(int id) {
337 mDisplayId = id;
338 return this;
339 }
340
Bryce Lee04ab3462017-04-10 15:06:33 -0700341 public ActivityStack build() {
Bryce Leeaf691c02017-03-20 14:20:22 -0700342 return createActivityStack(mService, mStackId, mDisplayId, mOnTop);
343 }
344 }
345}