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