blob: 2e4740b57255f96fdb56423c7783c3188792c72e [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.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;
Bryce Leef3c6a472017-11-14 14:53:06 -080032
Bryce Leeaf691c02017-03-20 14:20:22 -070033import static com.android.server.wm.WindowContainer.POSITION_TOP;
Bryce Leef3c6a472017-11-14 14:53:06 -080034import static org.mockito.Mockito.any;
35import static org.mockito.Mockito.anyBoolean;
36import static org.mockito.Mockito.anyFloat;
Evan Roskyb0e38882018-04-25 12:48:54 -070037import static org.mockito.Mockito.anyInt;
Bryce Leef3c6a472017-11-14 14:53:06 -080038import static org.mockito.Mockito.doAnswer;
Bryce Leeaf691c02017-03-20 14:20:22 -070039import static org.mockito.Mockito.mock;
Bryce Lee2b17afd2017-09-21 10:38:20 -070040import static org.mockito.Mockito.when;
Bryce Leeaf691c02017-03-20 14:20:22 -070041
Bryce Leef3c6a472017-11-14 14:53:06 -080042import org.mockito.invocation.InvocationOnMock;
43
Bryce Leeaf691c02017-03-20 14:20:22 -070044/**
45 * A collection of static functions that can be referenced by other test packages to provide access
46 * to WindowManager related test functionality.
47 */
48public class WindowTestUtils {
49 public static int sNextTaskId = 0;
50
51 /**
Bryce Lee04ab3462017-04-10 15:06:33 -070052 * Retrieves an instance of a mock {@link WindowManagerService}.
53 */
54 public static WindowManagerService getMockWindowManagerService() {
Bryce Lee2b17afd2017-09-21 10:38:20 -070055 final WindowManagerService service = mock(WindowManagerService.class);
56 final WindowHashMap windowMap = new WindowHashMap();
57 when(service.getWindowManagerLock()).thenReturn(windowMap);
58 return service;
Bryce Lee04ab3462017-04-10 15:06:33 -070059 }
60
61 /**
Bryce Leeaf691c02017-03-20 14:20:22 -070062 * Creates a mock instance of {@link StackWindowController}.
63 */
64 public static StackWindowController createMockStackWindowContainerController() {
65 StackWindowController controller = mock(StackWindowController.class);
66 controller.mContainer = mock(TestTaskStack.class);
Bryce Leef3c6a472017-11-14 14:53:06 -080067
68 // many components rely on the {@link StackWindowController#adjustConfigurationForBounds}
69 // to properly set bounds values in the configuration. We must mimick those actions here.
70 doAnswer((InvocationOnMock invocationOnMock) -> {
71 final Configuration config = invocationOnMock.<Configuration>getArgument(7);
72 final Rect bounds = invocationOnMock.<Rect>getArgument(0);
73 config.windowConfiguration.setBounds(bounds);
74 return null;
75 }).when(controller).adjustConfigurationForBounds(any(), any(), any(), any(),
Evan Roskyb0e38882018-04-25 12:48:54 -070076 anyBoolean(), anyBoolean(), anyFloat(), any(), any(), anyInt());
Bryce Leef3c6a472017-11-14 14:53:06 -080077
Bryce Leeaf691c02017-03-20 14:20:22 -070078 return controller;
79 }
80
81 /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
82 public static Task createTaskInStack(WindowManagerService service, TaskStack stack,
83 int userId) {
chaviw97d28202018-02-27 16:23:53 -080084 synchronized (service.mWindowMap) {
85 final Task newTask = new Task(sNextTaskId++, stack, userId, service, 0, false,
86 new ActivityManager.TaskDescription(), null);
87 stack.addTask(newTask, POSITION_TOP);
88 return newTask;
89 }
Bryce Leeaf691c02017-03-20 14:20:22 -070090 }
91
92 /**
93 * An extension of {@link TestTaskStack}, which overrides package scoped methods that would not
94 * normally be mocked out.
95 */
96 public static class TestTaskStack extends TaskStack {
97 TestTaskStack(WindowManagerService service, int stackId) {
Wale Ogunwale704a3c02017-09-18 15:30:52 -070098 super(service, stackId, null);
Bryce Leeaf691c02017-03-20 14:20:22 -070099 }
100
101 @Override
102 void addTask(Task task, int position, boolean showForAllUsers, boolean moveParents) {
103 // Do nothing.
104 }
105 }
106
chaviw97d28202018-02-27 16:23:53 -0800107 static TestAppWindowToken createTestAppWindowToken(DisplayContent dc) {
108 synchronized (dc.mService.mWindowMap) {
109 return new TestAppWindowToken(dc);
110 }
111 }
112
Bryce Leeaf691c02017-03-20 14:20:22 -0700113 /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
114 public static class TestAppWindowToken extends AppWindowToken {
Bryce Lee00d586d2017-07-28 20:48:43 -0700115 boolean mOnTop = false;
Bryce Leeaf691c02017-03-20 14:20:22 -0700116
chaviw97d28202018-02-27 16:23:53 -0800117 private TestAppWindowToken(DisplayContent dc) {
Steven Timotiusaf03df62017-07-18 16:56:43 -0700118 super(dc.mService, new IApplicationToken.Stub() {
119 public String getName() {return null;}
Bryce Leef3c6a472017-11-14 14:53:06 -0800120 }, false, dc, true /* fillsParent */);
Bryce Leeaf691c02017-03-20 14:20:22 -0700121 }
122
123 TestAppWindowToken(WindowManagerService service, IApplicationToken token,
124 boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
125 boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
126 int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
Bryce Leef3c6a472017-11-14 14:53:06 -0800127 boolean alwaysFocusable, AppWindowContainerController controller) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700128 super(service, token, voiceInteraction, dc, inputDispatchingTimeoutNanos, fullscreen,
129 showForAllUsers, targetSdk, orientation, rotationAnimationHint, configChanges,
Bryce Leef3c6a472017-11-14 14:53:06 -0800130 launchTaskBehind, alwaysFocusable, controller);
Bryce Leeaf691c02017-03-20 14:20:22 -0700131 }
132
133 int getWindowsCount() {
134 return mChildren.size();
135 }
136
137 boolean hasWindow(WindowState w) {
138 return mChildren.contains(w);
139 }
140
141 WindowState getFirstChild() {
Jorim Jaggi612bb882017-05-16 17:11:18 +0200142 return mChildren.peekFirst();
Bryce Leeaf691c02017-03-20 14:20:22 -0700143 }
144
145 WindowState getLastChild() {
Jorim Jaggi612bb882017-05-16 17:11:18 +0200146 return mChildren.peekLast();
Bryce Leeaf691c02017-03-20 14:20:22 -0700147 }
148
149 int positionInParent() {
150 return getParent().mChildren.indexOf(this);
151 }
Bryce Lee00d586d2017-07-28 20:48:43 -0700152
153 void setIsOnTop(boolean onTop) {
154 mOnTop = onTop;
155 }
156
157 @Override
158 boolean isOnTop() {
159 return mOnTop;
160 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700161 }
162
chaviw97d28202018-02-27 16:23:53 -0800163 static TestWindowToken createTestWindowToken(int type, DisplayContent dc) {
164 return createTestWindowToken(type, dc, false /* persistOnEmpty */);
165 }
166
167 static TestWindowToken createTestWindowToken(int type, DisplayContent dc,
168 boolean persistOnEmpty) {
169 synchronized (dc.mService.mWindowMap) {
170 return new TestWindowToken(type, dc, persistOnEmpty);
171 }
172 }
173
Bryce Leeaf691c02017-03-20 14:20:22 -0700174 /* Used so we can gain access to some protected members of the {@link WindowToken} class */
175 public static class TestWindowToken extends WindowToken {
Bryce Leeaf691c02017-03-20 14:20:22 -0700176
chaviw97d28202018-02-27 16:23:53 -0800177 private TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700178 super(dc.mService, mock(IBinder.class), type, persistOnEmpty, dc,
Bryce Leeaf691c02017-03-20 14:20:22 -0700179 false /* ownerCanManageAppTokens */);
180 }
181
182 int getWindowsCount() {
183 return mChildren.size();
184 }
185
186 boolean hasWindow(WindowState w) {
187 return mChildren.contains(w);
188 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700189 }
190
191 /* Used so we can gain access to some protected members of the {@link Task} class */
192 public static class TestTask extends Task {
193 boolean mShouldDeferRemoval = false;
194 boolean mOnDisplayChangedCalled = false;
Bryce Leeaf691c02017-03-20 14:20:22 -0700195 private boolean mIsAnimating = false;
196
Bryce Leef3c6a472017-11-14 14:53:06 -0800197 TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service,
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700198 int resizeMode, boolean supportsPictureInPicture,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700199 TaskWindowContainerController controller) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800200 super(taskId, stack, userId, service, resizeMode, supportsPictureInPicture,
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700201 new ActivityManager.TaskDescription(), controller);
Bryce Leeaf691c02017-03-20 14:20:22 -0700202 }
203
204 boolean shouldDeferRemoval() {
205 return mShouldDeferRemoval;
206 }
207
208 int positionInParent() {
209 return getParent().mChildren.indexOf(this);
210 }
211
212 @Override
213 void onDisplayChanged(DisplayContent dc) {
214 super.onDisplayChanged(dc);
215 mOnDisplayChangedCalled = true;
216 }
217
218 @Override
Jorim Jaggia5e10572017-11-15 14:36:26 +0100219 boolean isSelfAnimating() {
220 return mIsAnimating;
Bryce Leeaf691c02017-03-20 14:20:22 -0700221 }
222
223 void setLocalIsAnimating(boolean isAnimating) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700224 mIsAnimating = isAnimating;
225 }
226 }
227
228 /**
229 * Used so we can gain access to some protected members of {@link TaskWindowContainerController}
230 * class.
231 */
232 public static class TestTaskWindowContainerController extends TaskWindowContainerController {
233
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700234 TestTaskWindowContainerController(WindowTestsBase testsBase) {
235 this(testsBase.createStackControllerOnDisplay(testsBase.mDisplayContent));
Bryce Leeaf691c02017-03-20 14:20:22 -0700236 }
237
238 TestTaskWindowContainerController(StackWindowController stackController) {
239 super(sNextTaskId++, new TaskWindowContainerListener() {
240 @Override
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700241 public void registerConfigurationChangeListener(
242 ConfigurationContainerListener listener) {
243
244 }
245
246 @Override
247 public void unregisterConfigurationChangeListener(
248 ConfigurationContainerListener listener) {
249
250 }
251
252 @Override
Bryce Leeaf691c02017-03-20 14:20:22 -0700253 public void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
254
255 }
256
257 @Override
258 public void requestResize(Rect bounds, int resizeMode) {
259
260 }
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700261 }, stackController, 0 /* userId */, null /* bounds */, RESIZE_MODE_UNRESIZEABLE,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700262 false /* supportsPictureInPicture */, true /* toTop*/,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700263 true /* showForAllUsers */, new ActivityManager.TaskDescription(),
264 stackController.mService);
Bryce Leeaf691c02017-03-20 14:20:22 -0700265 }
266
267 @Override
Bryce Leef3c6a472017-11-14 14:53:06 -0800268 TestTask createTask(int taskId, TaskStack stack, int userId, int resizeMode,
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700269 boolean supportsPictureInPicture, ActivityManager.TaskDescription taskDescription) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800270 return new TestTask(taskId, stack, userId, mService, resizeMode,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700271 supportsPictureInPicture, this);
Bryce Leeaf691c02017-03-20 14:20:22 -0700272 }
273 }
274
275 public static class TestAppWindowContainerController extends AppWindowContainerController {
276
277 final IApplicationToken mToken;
278
279 TestAppWindowContainerController(TestTaskWindowContainerController taskController) {
280 this(taskController, new TestIApplicationToken());
281 }
282
283 TestAppWindowContainerController(TestTaskWindowContainerController taskController,
284 IApplicationToken token) {
285 super(taskController, token, null /* listener */, 0 /* index */,
286 SCREEN_ORIENTATION_UNSPECIFIED, true /* fullscreen */,
287 true /* showForAllUsers */, 0 /* configChanges */, false /* voiceInteraction */,
288 false /* launchTaskBehind */, false /* alwaysFocusable */,
289 0 /* targetSdkVersion */, 0 /* rotationAnimationHint */,
Bryce Leef3c6a472017-11-14 14:53:06 -0800290 0 /* inputDispatchingTimeoutNanos */, taskController.mService);
Bryce Leeaf691c02017-03-20 14:20:22 -0700291 mToken = token;
292 }
293
294 @Override
295 AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
296 boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
297 boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
298 int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
Bryce Leef3c6a472017-11-14 14:53:06 -0800299 boolean alwaysFocusable, AppWindowContainerController controller) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700300 return new TestAppWindowToken(service, token, voiceInteraction, dc,
301 inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
302 orientation,
303 rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
Bryce Leef3c6a472017-11-14 14:53:06 -0800304 controller);
Bryce Leeaf691c02017-03-20 14:20:22 -0700305 }
306
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700307 AppWindowToken getAppWindowToken(DisplayContent dc) {
308 return (AppWindowToken) dc.getWindowToken(mToken.asBinder());
Bryce Leeaf691c02017-03-20 14:20:22 -0700309 }
310 }
311
312 public static class TestIApplicationToken implements IApplicationToken {
313
314 private final Binder mBinder = new Binder();
315 @Override
316 public IBinder asBinder() {
317 return mBinder;
318 }
Steven Timotiusaf03df62017-07-18 16:56:43 -0700319 @Override
320 public String getName() {
321 return null;
322 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700323 }
324
325 /** Used to track resize reports. */
326 public static class TestWindowState extends WindowState {
327 boolean resizeReported;
328
329 TestWindowState(WindowManagerService service, Session session, IWindow window,
330 WindowManager.LayoutParams attrs, WindowToken token) {
331 super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0,
332 false /* ownerCanAddInternalSystemWindow */);
333 }
334
335 @Override
336 void reportResized() {
337 super.reportResized();
338 resizeReported = true;
339 }
340
341 @Override
342 public boolean isGoneForLayoutLw() {
343 return false;
344 }
345
346 @Override
347 void updateResizingWindowIfNeeded() {
348 // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
349 // the system that it can actually update the window.
350 boolean hadSurface = mHasSurface;
351 mHasSurface = true;
352
353 super.updateResizingWindowIfNeeded();
354
355 mHasSurface = hadSurface;
356 }
357 }
358}