blob: c5cc2ff22abd3a1c4d569f87bb18aae651eefe3c [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;
20
21import android.content.ComponentName;
22import android.content.Context;
23import android.content.Intent;
24import android.content.pm.ActivityInfo;
25import android.content.pm.ApplicationInfo;
26import android.content.res.Configuration;
27import android.graphics.Rect;
28import android.os.Handler;
29import android.os.Looper;
30import android.support.test.InstrumentationRegistry;
31import com.android.server.AttributeCache;
32import com.android.server.wm.AppWindowContainerController;
33import com.android.server.wm.StackWindowController;
34
35import com.android.server.wm.WindowManagerService;
36import com.android.server.wm.WindowTestUtils;
37import org.junit.Before;
38import org.mockito.MockitoAnnotations;
39
40/**
41 * A base class to handle common operations in activity related unit tests.
42 */
43public class ActivityTestsBase {
44 private final Context mContext = InstrumentationRegistry.getContext();
45 private static boolean sLooperPrepared;
46 private Handler mHandler;
47
48 // Grabbing an instance of {@link WindowManagerService} creates it if not present so this must
49 // be called at before any tests.
50 private final WindowManagerService mWms = WindowTestUtils.getWindowManagerService(mContext);
51
52 @Before
53 public void setUp() throws Exception {
54 MockitoAnnotations.initMocks(this);
55
56 if (!sLooperPrepared) {
57 sLooperPrepared = true;
58 Looper.prepare();
59 }
60 }
61
62 protected ActivityManagerService createActivityManagerService() {
63 return new TestActivityManagerService(mContext);
64 }
65
66 protected static TestActivityStack createActivityStack(ActivityManagerService service,
67 int stackId, int displayId, boolean onTop) {
68 if (service.mStackSupervisor instanceof TestActivityStackSupervisor) {
69 final TestActivityStack stack = ((TestActivityStackSupervisor) service.mStackSupervisor)
70 .createTestStack(stackId, onTop);
71 return stack;
72 }
73
74 return null;
75 }
76
77 protected static ActivityRecord createActivity(ActivityManagerService service,
78 ComponentName component, TaskRecord task) {
79 Intent intent = new Intent();
80 intent.setComponent(component);
81 final ActivityInfo aInfo = new ActivityInfo();
82 aInfo.applicationInfo = new ApplicationInfo();
83 aInfo.applicationInfo.packageName = component.getPackageName();
84 AttributeCache.init(service.mContext);
85 final ActivityRecord activity = new ActivityRecord(service, null /* caller */,
86 0 /* launchedFromPid */, 0, null, intent, null,
87 aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
88 0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
89 service.mStackSupervisor, null /* container */, null /* options */,
90 null /* sourceRecord */);
91 activity.mWindowContainerController = mock(AppWindowContainerController.class);
92
93 if (task != null) {
94 task.addActivityToTop(activity);
95 }
96
97 return activity;
98 }
99
100 protected static TaskRecord createTask(ActivityManagerService service,
101 ComponentName component, ActivityStack stack) {
102 final ActivityInfo aInfo = new ActivityInfo();
103 aInfo.applicationInfo = new ApplicationInfo();
104 aInfo.applicationInfo.packageName = component.getPackageName();
105
106 Intent intent = new Intent();
107 intent.setComponent(component);
108
109 final TaskRecord task = new TaskRecord(service, 0, aInfo, intent /*intent*/,
110 null /*_taskDescription*/, null /*thumbnailInfo*/);
111 stack.addTask(task, true, "creating test task");
112 task.setStack(stack);
113 task.createWindowContainer(true, true);
114
115 return task;
116 }
117
118 /**
119 * An {@link ActivityManagerService} subclass which provides a test
120 * {@link ActivityStackSupervisor}.
121 */
122 protected static class TestActivityManagerService extends ActivityManagerService {
123 public TestActivityManagerService(Context context) {
124 super(context);
125 }
126
127 @Override
128 protected ActivityStackSupervisor createStackSupervisor() {
129 return new TestActivityStackSupervisor(this, new Handler().getLooper());
130 }
131 }
132
133 /**
134 * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on
135 * setup not available in the test environment. Also specifies an injector for
136 */
137 protected static class TestActivityStackSupervisor extends ActivityStackSupervisor {
138 public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
139 super(service, looper);
140 }
141
142 // Invoked during {@link ActivityStack} creation.
143 @Override
144 void updateUIDsPresentOnDisplay() {
145 }
146
147 public TestActivityStack createTestStack(int stackId, boolean onTop) {
148 final ActivityDisplay display = new ActivityDisplay();
149 final TestActivityContainer container =
150 new TestActivityContainer(stackId, display, onTop);
151 return container.getStack();
152 }
153
154 private class TestActivityContainer extends ActivityContainer {
155 private TestActivityStack mStack;
156 TestActivityContainer(int stackId, ActivityDisplay activityDisplay, boolean onTop) {
157 super(stackId, activityDisplay, onTop);
158 }
159
160 @Override
161 protected void createStack(int stackId, boolean onTop) {
162 mStack = new TestActivityStack(this, null /*recentTasks*/, onTop);
163 }
164
165 public TestActivityStack getStack() {
166 return mStack;
167 }
168 }
169 }
170
171 /**
172 * Override of {@link ActivityStack} that tracks test metrics, such as the number of times a
173 * method is called. Note that its functionality depends on the implementations of the
174 * construction arguments.
175 */
176 protected static class TestActivityStack<T extends StackWindowController>
177 extends ActivityStack<T> {
178 private int mOnActivityRemovedFromStackCount = 0;
179 private T mContainerController;
180 TestActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer,
181 RecentTasks recentTasks, boolean onTop) {
182 super(activityContainer, recentTasks, onTop);
183 }
184
185 @Override
186 void onActivityRemovedFromStack(ActivityRecord r) {
187 mOnActivityRemovedFromStackCount++;
188 super.onActivityRemovedFromStack(r);
189 }
190
191 // Returns the number of times {@link #onActivityRemovedFromStack} has been called
192 public int onActivityRemovedFromStackInvocationCount() {
193 return mOnActivityRemovedFromStackCount;
194 }
195
196 @Override
197 protected T createStackWindowController(int displayId, boolean onTop,
198 Rect outBounds) {
199 mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController();
200 return mContainerController;
201 }
202
203 @Override
204 T getWindowContainerController() {
205 return mContainerController;
206 }
207 }
208
209 protected static class ActivityStackBuilder {
210 private boolean mOnTop = true;
211 private int mStackId = 0;
212 private int mDisplayId = 1;
213
214 private final ActivityManagerService mService;
215
216 public ActivityStackBuilder(ActivityManagerService ams) {
217 mService = ams;
218 }
219
220 public ActivityStackBuilder setOnTop(boolean onTop) {
221 mOnTop = onTop;
222 return this;
223 }
224
225 public ActivityStackBuilder setStackId(int id) {
226 mStackId = id;
227 return this;
228 }
229
230 public ActivityStackBuilder setDisplayId(int id) {
231 mDisplayId = id;
232 return this;
233 }
234
235 public TestActivityStack build() {
236 return createActivityStack(mService, mStackId, mDisplayId, mOnTop);
237 }
238 }
239}