blob: f5cdf216f04ad17c9e1a7d2583d0caa44133cd20 [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
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070019import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
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;
Bryce Lee4e4a3ec2017-09-27 08:25:03 -070025import static org.mockito.Mockito.spy;
Bryce Lee04ab3462017-04-10 15:06:33 -070026
27import org.mockito.invocation.InvocationOnMock;
Bryce Leeaf691c02017-03-20 14:20:22 -070028
29import android.content.ComponentName;
30import android.content.Context;
31import android.content.Intent;
32import android.content.pm.ActivityInfo;
33import android.content.pm.ApplicationInfo;
34import android.content.res.Configuration;
35import android.graphics.Rect;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070036import android.hardware.display.DisplayManager;
Bryce Lee3115bdf2017-04-05 08:39:40 -070037import android.os.HandlerThread;
Bryce Leeaf691c02017-03-20 14:20:22 -070038import android.os.Looper;
39import android.support.test.InstrumentationRegistry;
40import com.android.server.AttributeCache;
41import com.android.server.wm.AppWindowContainerController;
Bryce Lee4e4a3ec2017-09-27 08:25:03 -070042import com.android.server.wm.PinnedStackWindowController;
Bryce Leeaf691c02017-03-20 14:20:22 -070043import com.android.server.wm.StackWindowController;
Bryce Lee04ab3462017-04-10 15:06:33 -070044import com.android.server.wm.TaskWindowContainerController;
Bryce Leeaf691c02017-03-20 14:20:22 -070045import com.android.server.wm.WindowManagerService;
46import com.android.server.wm.WindowTestUtils;
Bryce Lee3115bdf2017-04-05 08:39:40 -070047import org.junit.After;
Bryce Leeaf691c02017-03-20 14:20:22 -070048import org.junit.Before;
49import org.mockito.MockitoAnnotations;
50
51/**
52 * A base class to handle common operations in activity related unit tests.
53 */
54public class ActivityTestsBase {
Bryce Lee939a9a32017-10-23 10:01:21 -070055 private static boolean sOneTimeSetupDone = false;
56
Bryce Leeaf691c02017-03-20 14:20:22 -070057 private final Context mContext = InstrumentationRegistry.getContext();
Bryce Lee3115bdf2017-04-05 08:39:40 -070058 private HandlerThread mHandlerThread;
Bryce Leeaf691c02017-03-20 14:20:22 -070059
Bryce Leeaf691c02017-03-20 14:20:22 -070060 @Before
61 public void setUp() throws Exception {
Bryce Lee939a9a32017-10-23 10:01:21 -070062 if (!sOneTimeSetupDone) {
63 sOneTimeSetupDone = true;
64
65 // Allows to mock package local classes and methods
66 System.setProperty("dexmaker.share_classloader", "true");
67 MockitoAnnotations.initMocks(this);
68 }
Bryce Lee3115bdf2017-04-05 08:39:40 -070069 mHandlerThread = new HandlerThread("ActivityTestsBaseThread");
70 mHandlerThread.start();
71 }
Bryce Leeaf691c02017-03-20 14:20:22 -070072
Bryce Lee3115bdf2017-04-05 08:39:40 -070073 @After
74 public void tearDown() {
75 mHandlerThread.quitSafely();
Bryce Leeaf691c02017-03-20 14:20:22 -070076 }
77
78 protected ActivityManagerService createActivityManagerService() {
Bryce Lee4e4a3ec2017-09-27 08:25:03 -070079 final ActivityManagerService service = spy(new TestActivityManagerService(mContext));
80 service.mWindowManager = prepareMockWindowManager();
Bryce Lee840c5662017-04-13 10:02:51 -070081 return service;
Bryce Leeaf691c02017-03-20 14:20:22 -070082 }
83
Bryce Leeaf691c02017-03-20 14:20:22 -070084 protected static ActivityRecord createActivity(ActivityManagerService service,
85 ComponentName component, TaskRecord task) {
Bryce Lee9f6affd2017-09-01 09:18:35 -070086 return createActivity(service, component, task, 0 /* userId */);
87 }
88
89 protected static ActivityRecord createActivity(ActivityManagerService service,
90 ComponentName component, TaskRecord task, int uid) {
Bryce Leeaf691c02017-03-20 14:20:22 -070091 Intent intent = new Intent();
92 intent.setComponent(component);
93 final ActivityInfo aInfo = new ActivityInfo();
94 aInfo.applicationInfo = new ApplicationInfo();
95 aInfo.applicationInfo.packageName = component.getPackageName();
Bryce Lee9f6affd2017-09-01 09:18:35 -070096 aInfo.applicationInfo.uid = uid;
Bryce Leeaf691c02017-03-20 14:20:22 -070097 AttributeCache.init(service.mContext);
98 final ActivityRecord activity = new ActivityRecord(service, null /* caller */,
99 0 /* launchedFromPid */, 0, null, intent, null,
100 aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
101 0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700102 service.mStackSupervisor, null /* options */, null /* sourceRecord */);
Bryce Leeaf691c02017-03-20 14:20:22 -0700103 activity.mWindowContainerController = mock(AppWindowContainerController.class);
104
105 if (task != null) {
106 task.addActivityToTop(activity);
107 }
108
109 return activity;
110 }
111
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700112 protected static TaskRecord createTask(ActivityStackSupervisor supervisor,
113 ComponentName component, ActivityStack stack) {
Winson Chungd6aa3db2017-10-05 17:18:43 -0700114 return createTask(supervisor, component, 0 /* flags */, 0 /* taskId */, stack);
Winson Chung1dbc8112017-09-28 18:05:31 -0700115 }
116
117 protected static TaskRecord createTask(ActivityStackSupervisor supervisor,
Winson Chungd6aa3db2017-10-05 17:18:43 -0700118 ComponentName component, int flags, int taskId, ActivityStack stack) {
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);
Winson Chung1dbc8112017-09-28 18:05:31 -0700125 intent.setFlags(flags);
Bryce Leeaf691c02017-03-20 14:20:22 -0700126
Winson Chungd6aa3db2017-10-05 17:18:43 -0700127 final TaskRecord task = new TaskRecord(supervisor.mService, taskId, aInfo,
128 intent /*intent*/, null /*_taskDescription*/);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700129 supervisor.setFocusStackUnchecked("test", stack);
Bryce Leeaf691c02017-03-20 14:20:22 -0700130 stack.addTask(task, true, "creating test task");
131 task.setStack(stack);
Bryce Lee04ab3462017-04-10 15:06:33 -0700132 task.setWindowContainerController(mock(TaskWindowContainerController.class));
Bryce Leeaf691c02017-03-20 14:20:22 -0700133
134 return task;
135 }
136
137 /**
138 * An {@link ActivityManagerService} subclass which provides a test
139 * {@link ActivityStackSupervisor}.
140 */
141 protected static class TestActivityManagerService extends ActivityManagerService {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700142 TestActivityManagerService(Context context) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700143 super(context);
Bryce Lee04ab3462017-04-10 15:06:33 -0700144 mSupportsMultiWindow = true;
145 mSupportsMultiDisplay = true;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700146 mSupportsSplitScreenMultiWindow = true;
147 mSupportsFreeformWindowManagement = true;
148 mSupportsPictureInPicture = true;
Bryce Lee6a0754a2017-10-10 17:53:50 -0700149 mWindowManager = WindowTestUtils.getMockWindowManagerService();
Bryce Leeaf691c02017-03-20 14:20:22 -0700150 }
151
152 @Override
153 protected ActivityStackSupervisor createStackSupervisor() {
Bryce Lee3115bdf2017-04-05 08:39:40 -0700154 return new TestActivityStackSupervisor(this, mHandlerThread.getLooper());
Bryce Leeaf691c02017-03-20 14:20:22 -0700155 }
Bryce Lee29a649d2017-08-18 13:52:31 -0700156
157 @Override
158 void updateUsageStats(ActivityRecord component, boolean resumed) {
159 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700160 }
161
162 /**
163 * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on
164 * setup not available in the test environment. Also specifies an injector for
165 */
166 protected static class TestActivityStackSupervisor extends ActivityStackSupervisor {
Bryce Lee943ebe72017-05-04 10:19:07 -0700167 private final ActivityDisplay mDisplay;
Bryce Lee1533b2b2017-09-14 17:06:41 -0700168 private boolean mLastResizeable;
Bryce Lee943ebe72017-05-04 10:19:07 -0700169
Bryce Leeaf691c02017-03-20 14:20:22 -0700170 public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
171 super(service, looper);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700172 mDisplayManager =
173 (DisplayManager) mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
Bryce Lee04ab3462017-04-10 15:06:33 -0700174 mWindowManager = prepareMockWindowManager();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700175 mDisplay = new TestActivityDisplay(this, DEFAULT_DISPLAY);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700176 attachDisplay(mDisplay);
Bryce Lee04ab3462017-04-10 15:06:33 -0700177 }
178
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700179 @Override
180 ActivityDisplay getDefaultDisplay() {
181 return mDisplay;
182 }
183
Bryce Lee1533b2b2017-09-14 17:06:41 -0700184 // TODO: Use Mockito spy instead. Currently not possible due to TestActivityStackSupervisor
185 // access to ActivityDisplay
186 @Override
187 boolean canPlaceEntityOnDisplay(int displayId, boolean resizeable, int callingPid,
188 int callingUid, ActivityInfo activityInfo) {
189 mLastResizeable = resizeable;
190 return super.canPlaceEntityOnDisplay(displayId, resizeable, callingPid, callingUid,
191 activityInfo);
192 }
193
194 // TODO: remove and use Mockito verify once {@link #canPlaceEntityOnDisplay} override is
195 // removed.
196 public boolean getLastResizeableFromCanPlaceEntityOnDisplay() {
197 return mLastResizeable;
198 }
199
Bryce Lee04ab3462017-04-10 15:06:33 -0700200 // No home stack is set.
201 @Override
202 void moveHomeStackToFront(String reason) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700203 }
204
Bryce Lee3345c4e2017-04-25 07:40:41 -0700205 @Override
206 boolean moveHomeStackTaskToTop(String reason) {
207 return true;
208 }
209
Bryce Leeaf691c02017-03-20 14:20:22 -0700210 // Invoked during {@link ActivityStack} creation.
211 @Override
212 void updateUIDsPresentOnDisplay() {
213 }
214
Bryce Lee04ab3462017-04-10 15:06:33 -0700215 // Just return the current front task.
216 @Override
217 ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus) {
218 return mFocusedStack;
219 }
220
221 // Called when moving activity to pinned stack.
222 @Override
223 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
224 boolean preserveWindows) {
225 }
226
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700227 // Always keep things awake
228 @Override
229 boolean hasAwakeDisplay() {
230 return true;
231 }
232 }
233
234 private static class TestActivityDisplay extends ActivityDisplay {
235
236 private final ActivityStackSupervisor mSupervisor;
237 TestActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
238 super(supervisor, displayId);
239 mSupervisor = supervisor;
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700240 }
241
242 @Override
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700243 <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
244 int stackId, boolean onTop) {
245 if (windowingMode == WINDOWING_MODE_PINNED) {
246 return (T) new PinnedActivityStack(this, stackId, mSupervisor, onTop) {
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700247 @Override
248 Rect getDefaultPictureInPictureBounds(float aspectRatio) {
249 return new Rect(50, 50, 100, 100);
250 }
Bryce Lee4e4a3ec2017-09-27 08:25:03 -0700251
252 @Override
253 PinnedStackWindowController createStackWindowController(int displayId,
254 boolean onTop, Rect outBounds) {
255 return mock(PinnedStackWindowController.class);
256 }
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700257 };
258 } else {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700259 return (T) new TestActivityStack(
260 this, stackId, mSupervisor, windowingMode, activityType, onTop);
Andrii Kulianb1cdb102017-07-13 15:33:06 -0700261 }
Bryce Lee04ab3462017-04-10 15:06:33 -0700262 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700263 }
264
Bryce Lee04ab3462017-04-10 15:06:33 -0700265 private static WindowManagerService prepareMockWindowManager() {
Bryce Lee4e4a3ec2017-09-27 08:25:03 -0700266 final WindowManagerService service = WindowTestUtils.getMockWindowManagerService();
Bryce Lee04ab3462017-04-10 15:06:33 -0700267
268 doAnswer((InvocationOnMock invocationOnMock) -> {
269 final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
270 if (runnable != null) {
271 runnable.run();
272 }
273 return null;
274 }).when(service).inSurfaceTransaction(any());
275
276 return service;
277 }
278
Bryce Leeaf691c02017-03-20 14:20:22 -0700279 /**
Bryce Lee4e4a3ec2017-09-27 08:25:03 -0700280 * Overrided of {@link ActivityStack} that tracks test metrics, such as the number of times a
Bryce Leeaf691c02017-03-20 14:20:22 -0700281 * method is called. Note that its functionality depends on the implementations of the
282 * construction arguments.
283 */
284 protected static class TestActivityStack<T extends StackWindowController>
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700285 extends ActivityStack<T> {
Bryce Leeaf691c02017-03-20 14:20:22 -0700286 private int mOnActivityRemovedFromStackCount = 0;
287 private T mContainerController;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700288
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700289 static final int IS_TRANSLUCENT_UNSET = 0;
290 static final int IS_TRANSLUCENT_FALSE = 1;
291 static final int IS_TRANSLUCENT_TRUE = 2;
292 private int mIsTranslucent = IS_TRANSLUCENT_UNSET;
293
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700294 TestActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700295 int windowingMode, int activityType, boolean onTop) {
296 super(display, stackId, supervisor, windowingMode, activityType, onTop);
Bryce Leeaf691c02017-03-20 14:20:22 -0700297 }
298
299 @Override
300 void onActivityRemovedFromStack(ActivityRecord r) {
301 mOnActivityRemovedFromStackCount++;
302 super.onActivityRemovedFromStack(r);
303 }
304
305 // Returns the number of times {@link #onActivityRemovedFromStack} has been called
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700306 int onActivityRemovedFromStackInvocationCount() {
Bryce Leeaf691c02017-03-20 14:20:22 -0700307 return mOnActivityRemovedFromStackCount;
308 }
309
310 @Override
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700311 protected T createStackWindowController(int displayId, boolean onTop, Rect outBounds) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700312 mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController();
313 return mContainerController;
314 }
315
316 @Override
317 T getWindowContainerController() {
318 return mContainerController;
319 }
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700320
321 void setIsTranslucent(boolean isTranslucent) {
322 mIsTranslucent = isTranslucent ? IS_TRANSLUCENT_TRUE : IS_TRANSLUCENT_FALSE;
323 }
324
325 @Override
326 boolean isStackTranslucent(ActivityRecord starting, ActivityStack stackBehind) {
327 switch (mIsTranslucent) {
328 case IS_TRANSLUCENT_TRUE:
329 return true;
330 case IS_TRANSLUCENT_FALSE:
331 return false;
332 case IS_TRANSLUCENT_UNSET:
333 default:
334 return super.isStackTranslucent(starting, stackBehind);
335 }
336 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700337 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700338}