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