ActivityTestsBase.java revision af691c0be7bbfea63e880dd717c51a38a0bc874a
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.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}
240