blob: 482d5f52815f6260cbaaa69aa3edb89feadadffe [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 Lee04ab3462017-04-10 15:06:33 -070024import static org.mockito.Mockito.doReturn;
25import static org.mockito.Mockito.any;
26import static org.mockito.Mockito.doAnswer;
Bryce Lee4e4a3ec2017-09-27 08:25:03 -070027import static org.mockito.Mockito.spy;
Bryce Lee04ab3462017-04-10 15:06:33 -070028
29import org.mockito.invocation.InvocationOnMock;
Bryce Leeaf691c02017-03-20 14:20:22 -070030
31import android.content.ComponentName;
32import android.content.Context;
33import android.content.Intent;
34import android.content.pm.ActivityInfo;
35import android.content.pm.ApplicationInfo;
36import android.content.res.Configuration;
37import android.graphics.Rect;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070038import android.hardware.display.DisplayManager;
Bryce Lee3115bdf2017-04-05 08:39:40 -070039import android.os.HandlerThread;
Bryce Leeaf691c02017-03-20 14:20:22 -070040import android.os.Looper;
41import android.support.test.InstrumentationRegistry;
42import com.android.server.AttributeCache;
43import com.android.server.wm.AppWindowContainerController;
Bryce Lee4e4a3ec2017-09-27 08:25:03 -070044import com.android.server.wm.PinnedStackWindowController;
Bryce Leeaf691c02017-03-20 14:20:22 -070045import com.android.server.wm.StackWindowController;
Bryce Lee04ab3462017-04-10 15:06:33 -070046import com.android.server.wm.TaskWindowContainerController;
Bryce Leeaf691c02017-03-20 14:20:22 -070047import com.android.server.wm.WindowManagerService;
48import com.android.server.wm.WindowTestUtils;
Bryce Lee3115bdf2017-04-05 08:39:40 -070049import org.junit.After;
Bryce Leeaf691c02017-03-20 14:20:22 -070050import org.junit.Before;
51import org.mockito.MockitoAnnotations;
52
53/**
54 * A base class to handle common operations in activity related unit tests.
55 */
56public class ActivityTestsBase {
Bryce Lee939a9a32017-10-23 10:01:21 -070057 private static boolean sOneTimeSetupDone = false;
58
Bryce Leeaf691c02017-03-20 14:20:22 -070059 private final Context mContext = InstrumentationRegistry.getContext();
Bryce Lee3115bdf2017-04-05 08:39:40 -070060 private HandlerThread mHandlerThread;
Bryce Leeaf691c02017-03-20 14:20:22 -070061
Bryce Leeaf691c02017-03-20 14:20:22 -070062 @Before
63 public void setUp() throws Exception {
Bryce Lee939a9a32017-10-23 10:01:21 -070064 if (!sOneTimeSetupDone) {
65 sOneTimeSetupDone = true;
66
67 // Allows to mock package local classes and methods
68 System.setProperty("dexmaker.share_classloader", "true");
69 MockitoAnnotations.initMocks(this);
70 }
Bryce Lee3115bdf2017-04-05 08:39:40 -070071 mHandlerThread = new HandlerThread("ActivityTestsBaseThread");
72 mHandlerThread.start();
73 }
Bryce Leeaf691c02017-03-20 14:20:22 -070074
Bryce Lee3115bdf2017-04-05 08:39:40 -070075 @After
76 public void tearDown() {
77 mHandlerThread.quitSafely();
Bryce Leeaf691c02017-03-20 14:20:22 -070078 }
79
80 protected ActivityManagerService createActivityManagerService() {
Winson Chung3f0e59a2017-10-25 10:19:05 -070081 return setupActivityManagerService(new TestActivityManagerService(mContext));
82 }
83
84 protected ActivityManagerService setupActivityManagerService(ActivityManagerService service) {
85 service = spy(service);
Bryce Lee4e4a3ec2017-09-27 08:25:03 -070086 service.mWindowManager = prepareMockWindowManager();
Bryce Lee840c5662017-04-13 10:02:51 -070087 return service;
Bryce Leeaf691c02017-03-20 14:20:22 -070088 }
89
Bryce Lee18d51592017-10-25 10:22:19 -070090 /**
91 * Builder for creating new activities.
92 */
93 protected static class ActivityBuilder {
94 // An id appended to the end of the component name to make it unique
95 private static int sCurrentActivityId = 0;
Bryce Lee9f6affd2017-09-01 09:18:35 -070096
Bryce Lee18d51592017-10-25 10:22:19 -070097 // Default package name
98 private static final String DEFAULT_PACKAGE = "com.foo";
Bryce Leeaf691c02017-03-20 14:20:22 -070099
Bryce Lee18d51592017-10-25 10:22:19 -0700100 // Default base activity name
101 private static final String DEFAULT_BASE_ACTIVITY_NAME = ".BarActivity";
102
103 private final ActivityManagerService mService;
104
105 private ComponentName mComponent;
106 private TaskRecord mTaskRecord;
107 private int mUid;
108 private boolean mCreateTask;
109 private ActivityStack mStack;
110
111 ActivityBuilder(ActivityManagerService service) {
112 mService = service;
Bryce Leeaf691c02017-03-20 14:20:22 -0700113 }
114
Bryce Lee18d51592017-10-25 10:22:19 -0700115 ActivityBuilder setComponent(ComponentName component) {
116 mComponent = component;
117 return this;
118 }
119
120 ActivityBuilder setTask(TaskRecord task) {
121 mTaskRecord = task;
122 return this;
123 }
124
125 ActivityBuilder setStack(ActivityStack stack) {
126 mStack = stack;
127 return this;
128 }
129
130 ActivityBuilder setCreateTask(boolean createTask) {
131 mCreateTask = createTask;
132 return this;
133 }
134
135 ActivityBuilder setUid(int uid) {
136 mUid = uid;
137 return this;
138 }
139
140 ActivityRecord build() {
141 if (mComponent == null) {
142 final int id = sCurrentActivityId++;
143 mComponent = ComponentName.createRelative(DEFAULT_PACKAGE,
144 DEFAULT_BASE_ACTIVITY_NAME + id);
145 }
146
147 if (mCreateTask) {
148 mTaskRecord = new TaskBuilder(mService.mStackSupervisor)
149 .setComponent(mComponent)
150 .setStack(mStack).build();
151 }
152
153 Intent intent = new Intent();
154 intent.setComponent(mComponent);
155 final ActivityInfo aInfo = new ActivityInfo();
156 aInfo.applicationInfo = new ApplicationInfo();
157 aInfo.applicationInfo.packageName = mComponent.getPackageName();
158 aInfo.applicationInfo.uid = mUid;
159 AttributeCache.init(mService.mContext);
160 final ActivityRecord activity = new ActivityRecord(mService, null /* caller */,
161 0 /* launchedFromPid */, 0, null, intent, null,
162 aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
163 0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
164 mService.mStackSupervisor, null /* options */, null /* sourceRecord */);
165 activity.mWindowContainerController = mock(AppWindowContainerController.class);
166
167 if (mTaskRecord != null) {
168 mTaskRecord.addActivityToTop(activity);
169 }
170
171 return activity;
172 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700173 }
174
Bryce Lee18d51592017-10-25 10:22:19 -0700175 /**
176 * Builder for creating new tasks.
177 */
178 protected static class TaskBuilder {
179 private final ActivityStackSupervisor mSupervisor;
Winson Chung1dbc8112017-09-28 18:05:31 -0700180
Bryce Lee18d51592017-10-25 10:22:19 -0700181 private ComponentName mComponent;
182 private String mPackage;
183 private int mFlags = 0;
184 private int mTaskId = 0;
Bryce Leeaf691c02017-03-20 14:20:22 -0700185
Bryce Lee18d51592017-10-25 10:22:19 -0700186 private ActivityStack mStack;
Bryce Leeaf691c02017-03-20 14:20:22 -0700187
Bryce Lee18d51592017-10-25 10:22:19 -0700188 TaskBuilder(ActivityStackSupervisor supervisor) {
189 mSupervisor = supervisor;
190 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700191
Bryce Lee18d51592017-10-25 10:22:19 -0700192 TaskBuilder setComponent(ComponentName component) {
193 mComponent = component;
194 return this;
195 }
196
197 TaskBuilder setPackage(String packageName) {
198 mPackage = packageName;
199 return this;
200 }
201
202 TaskBuilder setFlags(int flags) {
203 mFlags = flags;
204 return this;
205 }
206
207 TaskBuilder setTaskId(int taskId) {
208 mTaskId = taskId;
209 return this;
210 }
211
212 TaskBuilder setStack(ActivityStack stack) {
213 mStack = stack;
214 return this;
215 }
216
217 TaskRecord build() {
218 if (mStack == null) {
219 mStack = mSupervisor.getDefaultDisplay().createStack(
220 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
221 }
222
223 final ActivityInfo aInfo = new ActivityInfo();
224 aInfo.applicationInfo = new ApplicationInfo();
225 aInfo.applicationInfo.packageName = mPackage;
226
227 Intent intent = new Intent();
228 intent.setComponent(mComponent);
229 intent.setFlags(mFlags);
230
231 final TaskRecord task = new TaskRecord(mSupervisor.mService, mTaskId, aInfo,
232 intent /*intent*/, null /*_taskDescription*/);
233 mSupervisor.setFocusStackUnchecked("test", mStack);
234 mStack.addTask(task, true, "creating test task");
235 task.setStack(mStack);
236 task.setWindowContainerController(mock(TaskWindowContainerController.class));
237
238 return task;
239 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700240 }
241
242 /**
243 * An {@link ActivityManagerService} subclass which provides a test
244 * {@link ActivityStackSupervisor}.
245 */
246 protected static class TestActivityManagerService extends ActivityManagerService {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700247 TestActivityManagerService(Context context) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700248 super(context);
Bryce Lee04ab3462017-04-10 15:06:33 -0700249 mSupportsMultiWindow = true;
250 mSupportsMultiDisplay = true;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700251 mSupportsSplitScreenMultiWindow = true;
252 mSupportsFreeformWindowManagement = true;
253 mSupportsPictureInPicture = true;
Bryce Lee6a0754a2017-10-10 17:53:50 -0700254 mWindowManager = WindowTestUtils.getMockWindowManagerService();
Bryce Leeaf691c02017-03-20 14:20:22 -0700255 }
256
257 @Override
258 protected ActivityStackSupervisor createStackSupervisor() {
Bryce Lee3115bdf2017-04-05 08:39:40 -0700259 return new TestActivityStackSupervisor(this, mHandlerThread.getLooper());
Bryce Leeaf691c02017-03-20 14:20:22 -0700260 }
Bryce Lee29a649d2017-08-18 13:52:31 -0700261
262 @Override
263 void updateUsageStats(ActivityRecord component, boolean resumed) {
264 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700265 }
266
267 /**
268 * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on
269 * setup not available in the test environment. Also specifies an injector for
270 */
271 protected static class TestActivityStackSupervisor extends ActivityStackSupervisor {
Bryce Lee943ebe72017-05-04 10:19:07 -0700272 private final ActivityDisplay mDisplay;
Bryce Lee1533b2b2017-09-14 17:06:41 -0700273 private boolean mLastResizeable;
Bryce Lee943ebe72017-05-04 10:19:07 -0700274
Bryce Leeaf691c02017-03-20 14:20:22 -0700275 public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
276 super(service, looper);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700277 mDisplayManager =
278 (DisplayManager) mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
Bryce Lee04ab3462017-04-10 15:06:33 -0700279 mWindowManager = prepareMockWindowManager();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700280 mDisplay = new TestActivityDisplay(this, DEFAULT_DISPLAY);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700281 attachDisplay(mDisplay);
Bryce Lee04ab3462017-04-10 15:06:33 -0700282 }
283
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700284 @Override
285 ActivityDisplay getDefaultDisplay() {
286 return mDisplay;
287 }
288
Bryce Lee1533b2b2017-09-14 17:06:41 -0700289 // TODO: Use Mockito spy instead. Currently not possible due to TestActivityStackSupervisor
290 // access to ActivityDisplay
291 @Override
292 boolean canPlaceEntityOnDisplay(int displayId, boolean resizeable, int callingPid,
293 int callingUid, ActivityInfo activityInfo) {
294 mLastResizeable = resizeable;
295 return super.canPlaceEntityOnDisplay(displayId, resizeable, callingPid, callingUid,
296 activityInfo);
297 }
298
299 // TODO: remove and use Mockito verify once {@link #canPlaceEntityOnDisplay} override is
300 // removed.
301 public boolean getLastResizeableFromCanPlaceEntityOnDisplay() {
302 return mLastResizeable;
303 }
304
Bryce Lee04ab3462017-04-10 15:06:33 -0700305 // No home stack is set.
306 @Override
307 void moveHomeStackToFront(String reason) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700308 }
309
Bryce Lee3345c4e2017-04-25 07:40:41 -0700310 @Override
311 boolean moveHomeStackTaskToTop(String reason) {
312 return true;
313 }
314
Bryce Leeaf691c02017-03-20 14:20:22 -0700315 // Invoked during {@link ActivityStack} creation.
316 @Override
317 void updateUIDsPresentOnDisplay() {
318 }
319
Bryce Lee04ab3462017-04-10 15:06:33 -0700320 // Just return the current front task.
321 @Override
322 ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus) {
323 return mFocusedStack;
324 }
325
326 // Called when moving activity to pinned stack.
327 @Override
328 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
329 boolean preserveWindows) {
330 }
331
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700332 // Always keep things awake
333 @Override
334 boolean hasAwakeDisplay() {
335 return true;
336 }
337 }
338
339 private static class TestActivityDisplay extends ActivityDisplay {
340
341 private final ActivityStackSupervisor mSupervisor;
342 TestActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
343 super(supervisor, displayId);
344 mSupervisor = supervisor;
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700345 }
346
347 @Override
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700348 <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
349 int stackId, boolean onTop) {
350 if (windowingMode == WINDOWING_MODE_PINNED) {
351 return (T) new PinnedActivityStack(this, stackId, mSupervisor, onTop) {
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700352 @Override
353 Rect getDefaultPictureInPictureBounds(float aspectRatio) {
354 return new Rect(50, 50, 100, 100);
355 }
Bryce Lee4e4a3ec2017-09-27 08:25:03 -0700356
357 @Override
358 PinnedStackWindowController createStackWindowController(int displayId,
359 boolean onTop, Rect outBounds) {
360 return mock(PinnedStackWindowController.class);
361 }
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700362 };
363 } else {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700364 return (T) new TestActivityStack(
365 this, stackId, mSupervisor, windowingMode, activityType, onTop);
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700366 }
Bryce Lee04ab3462017-04-10 15:06:33 -0700367 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700368 }
369
Bryce Lee04ab3462017-04-10 15:06:33 -0700370 private static WindowManagerService prepareMockWindowManager() {
Bryce Lee4e4a3ec2017-09-27 08:25:03 -0700371 final WindowManagerService service = WindowTestUtils.getMockWindowManagerService();
Bryce Lee04ab3462017-04-10 15:06:33 -0700372
373 doAnswer((InvocationOnMock invocationOnMock) -> {
374 final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
375 if (runnable != null) {
376 runnable.run();
377 }
378 return null;
379 }).when(service).inSurfaceTransaction(any());
380
381 return service;
382 }
383
Bryce Leeaf691c02017-03-20 14:20:22 -0700384 /**
Bryce Lee4e4a3ec2017-09-27 08:25:03 -0700385 * Overrided of {@link ActivityStack} that tracks test metrics, such as the number of times a
Bryce Leeaf691c02017-03-20 14:20:22 -0700386 * method is called. Note that its functionality depends on the implementations of the
387 * construction arguments.
388 */
389 protected static class TestActivityStack<T extends StackWindowController>
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700390 extends ActivityStack<T> {
Bryce Leeaf691c02017-03-20 14:20:22 -0700391 private int mOnActivityRemovedFromStackCount = 0;
392 private T mContainerController;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700393
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700394 static final int IS_TRANSLUCENT_UNSET = 0;
395 static final int IS_TRANSLUCENT_FALSE = 1;
396 static final int IS_TRANSLUCENT_TRUE = 2;
397 private int mIsTranslucent = IS_TRANSLUCENT_UNSET;
398
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800399 static final int SUPPORTS_SPLIT_SCREEN_UNSET = 0;
400 static final int SUPPORTS_SPLIT_SCREEN_FALSE = 1;
401 static final int SUPPORTS_SPLIT_SCREEN_TRUE = 2;
402 private int mSupportsSplitScreen = SUPPORTS_SPLIT_SCREEN_UNSET;
403
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700404 TestActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700405 int windowingMode, int activityType, boolean onTop) {
406 super(display, stackId, supervisor, windowingMode, activityType, onTop);
Bryce Leeaf691c02017-03-20 14:20:22 -0700407 }
408
409 @Override
410 void onActivityRemovedFromStack(ActivityRecord r) {
411 mOnActivityRemovedFromStackCount++;
412 super.onActivityRemovedFromStack(r);
413 }
414
415 // Returns the number of times {@link #onActivityRemovedFromStack} has been called
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700416 int onActivityRemovedFromStackInvocationCount() {
Bryce Leeaf691c02017-03-20 14:20:22 -0700417 return mOnActivityRemovedFromStackCount;
418 }
419
420 @Override
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700421 protected T createStackWindowController(int displayId, boolean onTop, Rect outBounds) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700422 mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController();
423 return mContainerController;
424 }
425
426 @Override
427 T getWindowContainerController() {
428 return mContainerController;
429 }
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700430
431 void setIsTranslucent(boolean isTranslucent) {
432 mIsTranslucent = isTranslucent ? IS_TRANSLUCENT_TRUE : IS_TRANSLUCENT_FALSE;
433 }
434
435 @Override
Wale Ogunwale66e16852017-10-19 13:35:52 -0700436 boolean isStackTranslucent(ActivityRecord starting) {
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700437 switch (mIsTranslucent) {
438 case IS_TRANSLUCENT_TRUE:
439 return true;
440 case IS_TRANSLUCENT_FALSE:
441 return false;
442 case IS_TRANSLUCENT_UNSET:
443 default:
Wale Ogunwale66e16852017-10-19 13:35:52 -0700444 return super.isStackTranslucent(starting);
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700445 }
446 }
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800447
448 void setSupportsSplitScreen(boolean supportsSplitScreen) {
449 mSupportsSplitScreen = supportsSplitScreen
450 ? SUPPORTS_SPLIT_SCREEN_TRUE : SUPPORTS_SPLIT_SCREEN_FALSE;
451 }
452
453 @Override
454 public boolean supportsSplitScreenWindowingMode() {
455 switch (mSupportsSplitScreen) {
456 case SUPPORTS_SPLIT_SCREEN_TRUE:
457 return true;
458 case SUPPORTS_SPLIT_SCREEN_FALSE:
459 return false;
460 case SUPPORTS_SPLIT_SCREEN_UNSET:
461 default:
462 return super.supportsSplitScreenWindowingMode();
463 }
464 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700465 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700466}