WindowTestUtils.java revision 612bb885bcef87034070e8e3bfc0b0e953c0f606
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.wm;
18
19import android.app.ActivityManager;
20import android.content.Context;
21import android.content.res.Configuration;
22import android.graphics.Rect;
23import android.os.Binder;
24import android.os.IBinder;
25import android.view.IApplicationToken;
26import android.view.IWindow;
27import android.view.WindowManager;
28
29import static android.app.AppOpsManager.OP_NONE;
30import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
31import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
32import static android.content.res.Configuration.EMPTY;
33import static com.android.server.wm.WindowContainer.POSITION_TOP;
34import static org.mockito.Mockito.mock;
35
36/**
37 * A collection of static functions that can be referenced by other test packages to provide access
38 * to WindowManager related test functionality.
39 */
40public class WindowTestUtils {
41    public static int sNextTaskId = 0;
42
43    /**
44     * Retrieves an instance of {@link WindowManagerService}, creating it if necessary.
45     */
46    public static WindowManagerService getWindowManagerService(Context context) {
47        return TestWindowManagerPolicy.getWindowManagerService(context);
48    }
49
50    /**
51     * Retrieves an instance of a mock {@link WindowManagerService}.
52     */
53    public static WindowManagerService getMockWindowManagerService() {
54        return mock(WindowManagerService.class);
55    }
56
57    /**
58     * Creates a mock instance of {@link StackWindowController}.
59     */
60    public static StackWindowController createMockStackWindowContainerController() {
61        StackWindowController controller = mock(StackWindowController.class);
62        controller.mContainer = mock(TestTaskStack.class);
63        return controller;
64    }
65
66    /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
67    public static Task createTaskInStack(WindowManagerService service, TaskStack stack,
68            int userId) {
69        final Task newTask = new Task(sNextTaskId++, stack, userId, service, null, EMPTY, 0, false,
70                false, new ActivityManager.TaskDescription(), null);
71        stack.addTask(newTask, POSITION_TOP);
72        return newTask;
73    }
74
75    /**
76     * An extension of {@link TestTaskStack}, which overrides package scoped methods that would not
77     * normally be mocked out.
78     */
79    public static class TestTaskStack extends TaskStack {
80        TestTaskStack(WindowManagerService service, int stackId) {
81            super(service, stackId);
82        }
83
84        @Override
85        void addTask(Task task, int position, boolean showForAllUsers, boolean moveParents) {
86            // Do nothing.
87        }
88    }
89
90    /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
91    public static class TestAppWindowToken extends AppWindowToken {
92
93        TestAppWindowToken(DisplayContent dc) {
94            super(dc.mService, new IApplicationToken.Stub() {}, false, dc, true /* fillsParent */,
95                    null /* overrideConfig */, null /* bounds */);
96        }
97
98        TestAppWindowToken(WindowManagerService service, IApplicationToken token,
99                boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
100                boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
101                int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
102                boolean alwaysFocusable, AppWindowContainerController controller,
103                Configuration overrideConfig, Rect bounds) {
104            super(service, token, voiceInteraction, dc, inputDispatchingTimeoutNanos, fullscreen,
105                    showForAllUsers, targetSdk, orientation, rotationAnimationHint, configChanges,
106                    launchTaskBehind, alwaysFocusable, controller, overrideConfig, bounds);
107        }
108
109        int getWindowsCount() {
110            return mChildren.size();
111        }
112
113        boolean hasWindow(WindowState w) {
114            return mChildren.contains(w);
115        }
116
117        WindowState getFirstChild() {
118            return mChildren.peekFirst();
119        }
120
121        WindowState getLastChild() {
122            return mChildren.peekLast();
123        }
124
125        int positionInParent() {
126            return getParent().mChildren.indexOf(this);
127        }
128    }
129
130    /* Used so we can gain access to some protected members of the {@link WindowToken} class */
131    public static class TestWindowToken extends WindowToken {
132        int adj = 0;
133
134        TestWindowToken(int type, DisplayContent dc) {
135            this(type, dc, false /* persistOnEmpty */);
136        }
137
138        TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
139            super(dc.mService, mock(IBinder.class), type, persistOnEmpty, dc,
140                    false /* ownerCanManageAppTokens */);
141        }
142
143        int getWindowsCount() {
144            return mChildren.size();
145        }
146
147        boolean hasWindow(WindowState w) {
148            return mChildren.contains(w);
149        }
150
151        @Override
152        int getAnimLayerAdjustment() {
153            return adj;
154        }
155    }
156
157    /* Used so we can gain access to some protected members of the {@link Task} class */
158    public static class TestTask extends Task {
159        boolean mShouldDeferRemoval = false;
160        boolean mOnDisplayChangedCalled = false;
161        private boolean mUseLocalIsAnimating = false;
162        private boolean mIsAnimating = false;
163
164        TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
165                Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
166                boolean homeTask, TaskWindowContainerController controller) {
167            super(taskId, stack, userId, service, bounds, overrideConfig, resizeMode,
168                    supportsPictureInPicture, homeTask, new ActivityManager.TaskDescription(),
169                    controller);
170        }
171
172        boolean shouldDeferRemoval() {
173            return mShouldDeferRemoval;
174        }
175
176        int positionInParent() {
177            return getParent().mChildren.indexOf(this);
178        }
179
180        @Override
181        void onDisplayChanged(DisplayContent dc) {
182            super.onDisplayChanged(dc);
183            mOnDisplayChangedCalled = true;
184        }
185
186        @Override
187        boolean isAnimating() {
188            return mUseLocalIsAnimating ? mIsAnimating : super.isAnimating();
189        }
190
191        void setLocalIsAnimating(boolean isAnimating) {
192            mUseLocalIsAnimating = true;
193            mIsAnimating = isAnimating;
194        }
195    }
196
197    /**
198     * Used so we can gain access to some protected members of {@link TaskWindowContainerController}
199     * class.
200     */
201    public static class TestTaskWindowContainerController extends TaskWindowContainerController {
202
203        TestTaskWindowContainerController(WindowTestsBase testsBase) {
204            this(testsBase.createStackControllerOnDisplay(testsBase.mDisplayContent));
205        }
206
207        TestTaskWindowContainerController(StackWindowController stackController) {
208            super(sNextTaskId++, new TaskWindowContainerListener() {
209                        @Override
210                        public void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
211
212                        }
213
214                        @Override
215                        public void requestResize(Rect bounds, int resizeMode) {
216
217                        }
218                    }, stackController, 0 /* userId */, null /* bounds */,
219                    EMPTY /* overrideConfig*/, RESIZE_MODE_UNRESIZEABLE,
220                    false /* supportsPictureInPicture */, false /* homeTask*/, true /* toTop*/,
221                    true /* showForAllUsers */, new ActivityManager.TaskDescription(),
222                    stackController.mService);
223        }
224
225        @Override
226        TestTask createTask(int taskId, TaskStack stack, int userId, Rect bounds,
227                Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
228                boolean homeTask, ActivityManager.TaskDescription taskDescription) {
229            return new TestTask(taskId, stack, userId, mService, bounds, overrideConfig, resizeMode,
230                    supportsPictureInPicture, homeTask, this);
231        }
232    }
233
234    public static class TestAppWindowContainerController extends AppWindowContainerController {
235
236        final IApplicationToken mToken;
237
238        TestAppWindowContainerController(TestTaskWindowContainerController taskController) {
239            this(taskController, new TestIApplicationToken());
240        }
241
242        TestAppWindowContainerController(TestTaskWindowContainerController taskController,
243                IApplicationToken token) {
244            super(taskController, token, null /* listener */, 0 /* index */,
245                    SCREEN_ORIENTATION_UNSPECIFIED, true /* fullscreen */,
246                    true /* showForAllUsers */, 0 /* configChanges */, false /* voiceInteraction */,
247                    false /* launchTaskBehind */, false /* alwaysFocusable */,
248                    0 /* targetSdkVersion */, 0 /* rotationAnimationHint */,
249                    0 /* inputDispatchingTimeoutNanos */, taskController.mService,
250                    null /* overrideConfig */, null /* bounds */);
251            mToken = token;
252        }
253
254        @Override
255        AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
256                boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
257                boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
258                int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
259                boolean alwaysFocusable, AppWindowContainerController controller,
260                Configuration overrideConfig, Rect bounds) {
261            return new TestAppWindowToken(service, token, voiceInteraction, dc,
262                    inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
263                    orientation,
264                    rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
265                    controller, overrideConfig, bounds);
266        }
267
268        AppWindowToken getAppWindowToken(DisplayContent dc) {
269            return (AppWindowToken) dc.getWindowToken(mToken.asBinder());
270        }
271    }
272
273    public static class TestIApplicationToken implements IApplicationToken {
274
275        private final Binder mBinder = new Binder();
276        @Override
277        public IBinder asBinder() {
278            return mBinder;
279        }
280    }
281
282    /** Used to track resize reports. */
283    public static class TestWindowState extends WindowState {
284        boolean resizeReported;
285
286        TestWindowState(WindowManagerService service, Session session, IWindow window,
287                WindowManager.LayoutParams attrs, WindowToken token) {
288            super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0,
289                    false /* ownerCanAddInternalSystemWindow */);
290        }
291
292        @Override
293        void reportResized() {
294            super.reportResized();
295            resizeReported = true;
296        }
297
298        @Override
299        public boolean isGoneForLayoutLw() {
300            return false;
301        }
302
303        @Override
304        void updateResizingWindowIfNeeded() {
305            // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
306            // the system that it can actually update the window.
307            boolean hadSurface = mHasSurface;
308            mHasSurface = true;
309
310            super.updateResizingWindowIfNeeded();
311
312            mHasSurface = hadSurface;
313        }
314    }
315}
316