blob: d74defcbeb7c2513fd35b76e3fa7d075d167b11a [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;
37import static org.mockito.Mockito.doAnswer;
Bryce Leeaf691c02017-03-20 14:20:22 -070038import static org.mockito.Mockito.mock;
Bryce Lee2b17afd2017-09-21 10:38:20 -070039import static org.mockito.Mockito.when;
Bryce Leeaf691c02017-03-20 14:20:22 -070040
Bryce Leef3c6a472017-11-14 14:53:06 -080041import org.mockito.invocation.InvocationOnMock;
42
Bryce Leeaf691c02017-03-20 14:20:22 -070043/**
44 * A collection of static functions that can be referenced by other test packages to provide access
45 * to WindowManager related test functionality.
46 */
47public class WindowTestUtils {
48 public static int sNextTaskId = 0;
49
50 /**
Bryce Lee04ab3462017-04-10 15:06:33 -070051 * Retrieves an instance of a mock {@link WindowManagerService}.
52 */
53 public static WindowManagerService getMockWindowManagerService() {
Bryce Lee2b17afd2017-09-21 10:38:20 -070054 final WindowManagerService service = mock(WindowManagerService.class);
55 final WindowHashMap windowMap = new WindowHashMap();
56 when(service.getWindowManagerLock()).thenReturn(windowMap);
57 return service;
Bryce Lee04ab3462017-04-10 15:06:33 -070058 }
59
60 /**
Bryce Leeaf691c02017-03-20 14:20:22 -070061 * Creates a mock instance of {@link StackWindowController}.
62 */
63 public static StackWindowController createMockStackWindowContainerController() {
64 StackWindowController controller = mock(StackWindowController.class);
65 controller.mContainer = mock(TestTaskStack.class);
Bryce Leef3c6a472017-11-14 14:53:06 -080066
67 // many components rely on the {@link StackWindowController#adjustConfigurationForBounds}
68 // to properly set bounds values in the configuration. We must mimick those actions here.
69 doAnswer((InvocationOnMock invocationOnMock) -> {
70 final Configuration config = invocationOnMock.<Configuration>getArgument(7);
71 final Rect bounds = invocationOnMock.<Rect>getArgument(0);
72 config.windowConfiguration.setBounds(bounds);
73 return null;
74 }).when(controller).adjustConfigurationForBounds(any(), any(), any(), any(),
75 anyBoolean(), anyBoolean(), anyFloat(), any(), any());
76
Bryce Leeaf691c02017-03-20 14:20:22 -070077 return controller;
78 }
79
80 /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
81 public static Task createTaskInStack(WindowManagerService service, TaskStack stack,
82 int userId) {
chaviw97d28202018-02-27 16:23:53 -080083 synchronized (service.mWindowMap) {
84 final Task newTask = new Task(sNextTaskId++, stack, userId, service, 0, false,
85 new ActivityManager.TaskDescription(), null);
86 stack.addTask(newTask, POSITION_TOP);
87 return newTask;
88 }
Bryce Leeaf691c02017-03-20 14:20:22 -070089 }
90
91 /**
92 * An extension of {@link TestTaskStack}, which overrides package scoped methods that would not
93 * normally be mocked out.
94 */
95 public static class TestTaskStack extends TaskStack {
96 TestTaskStack(WindowManagerService service, int stackId) {
Wale Ogunwale704a3c02017-09-18 15:30:52 -070097 super(service, stackId, null);
Bryce Leeaf691c02017-03-20 14:20:22 -070098 }
99
100 @Override
101 void addTask(Task task, int position, boolean showForAllUsers, boolean moveParents) {
102 // Do nothing.
103 }
104 }
105
chaviw97d28202018-02-27 16:23:53 -0800106 static TestAppWindowToken createTestAppWindowToken(DisplayContent dc) {
107 synchronized (dc.mService.mWindowMap) {
108 return new TestAppWindowToken(dc);
109 }
110 }
111
Bryce Leeaf691c02017-03-20 14:20:22 -0700112 /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
113 public static class TestAppWindowToken extends AppWindowToken {
Bryce Lee00d586d2017-07-28 20:48:43 -0700114 boolean mOnTop = false;
Bryce Leeaf691c02017-03-20 14:20:22 -0700115
chaviw97d28202018-02-27 16:23:53 -0800116 private TestAppWindowToken(DisplayContent dc) {
Steven Timotiusaf03df62017-07-18 16:56:43 -0700117 super(dc.mService, new IApplicationToken.Stub() {
118 public String getName() {return null;}
Bryce Leef3c6a472017-11-14 14:53:06 -0800119 }, false, dc, true /* fillsParent */);
Bryce Leeaf691c02017-03-20 14:20:22 -0700120 }
121
122 TestAppWindowToken(WindowManagerService service, IApplicationToken token,
123 boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
124 boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
125 int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
Bryce Leef3c6a472017-11-14 14:53:06 -0800126 boolean alwaysFocusable, AppWindowContainerController controller) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700127 super(service, token, voiceInteraction, dc, inputDispatchingTimeoutNanos, fullscreen,
128 showForAllUsers, targetSdk, orientation, rotationAnimationHint, configChanges,
Bryce Leef3c6a472017-11-14 14:53:06 -0800129 launchTaskBehind, alwaysFocusable, controller);
Bryce Leeaf691c02017-03-20 14:20:22 -0700130 }
131
132 int getWindowsCount() {
133 return mChildren.size();
134 }
135
136 boolean hasWindow(WindowState w) {
137 return mChildren.contains(w);
138 }
139
140 WindowState getFirstChild() {
Jorim Jaggi612bb882017-05-16 17:11:18 +0200141 return mChildren.peekFirst();
Bryce Leeaf691c02017-03-20 14:20:22 -0700142 }
143
144 WindowState getLastChild() {
Jorim Jaggi612bb882017-05-16 17:11:18 +0200145 return mChildren.peekLast();
Bryce Leeaf691c02017-03-20 14:20:22 -0700146 }
147
148 int positionInParent() {
149 return getParent().mChildren.indexOf(this);
150 }
Bryce Lee00d586d2017-07-28 20:48:43 -0700151
152 void setIsOnTop(boolean onTop) {
153 mOnTop = onTop;
154 }
155
156 @Override
157 boolean isOnTop() {
158 return mOnTop;
159 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700160 }
161
chaviw97d28202018-02-27 16:23:53 -0800162 static TestWindowToken createTestWindowToken(int type, DisplayContent dc) {
163 return createTestWindowToken(type, dc, false /* persistOnEmpty */);
164 }
165
166 static TestWindowToken createTestWindowToken(int type, DisplayContent dc,
167 boolean persistOnEmpty) {
168 synchronized (dc.mService.mWindowMap) {
169 return new TestWindowToken(type, dc, persistOnEmpty);
170 }
171 }
172
Bryce Leeaf691c02017-03-20 14:20:22 -0700173 /* Used so we can gain access to some protected members of the {@link WindowToken} class */
174 public static class TestWindowToken extends WindowToken {
Bryce Leeaf691c02017-03-20 14:20:22 -0700175
chaviw97d28202018-02-27 16:23:53 -0800176 private TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700177 super(dc.mService, mock(IBinder.class), type, persistOnEmpty, dc,
Bryce Leeaf691c02017-03-20 14:20:22 -0700178 false /* ownerCanManageAppTokens */);
179 }
180
181 int getWindowsCount() {
182 return mChildren.size();
183 }
184
185 boolean hasWindow(WindowState w) {
186 return mChildren.contains(w);
187 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700188 }
189
190 /* Used so we can gain access to some protected members of the {@link Task} class */
191 public static class TestTask extends Task {
192 boolean mShouldDeferRemoval = false;
193 boolean mOnDisplayChangedCalled = false;
Bryce Leeaf691c02017-03-20 14:20:22 -0700194 private boolean mIsAnimating = false;
195
Bryce Leef3c6a472017-11-14 14:53:06 -0800196 TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service,
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700197 int resizeMode, boolean supportsPictureInPicture,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700198 TaskWindowContainerController controller) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800199 super(taskId, stack, userId, service, resizeMode, supportsPictureInPicture,
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700200 new ActivityManager.TaskDescription(), controller);
Bryce Leeaf691c02017-03-20 14:20:22 -0700201 }
202
203 boolean shouldDeferRemoval() {
204 return mShouldDeferRemoval;
205 }
206
207 int positionInParent() {
208 return getParent().mChildren.indexOf(this);
209 }
210
211 @Override
212 void onDisplayChanged(DisplayContent dc) {
213 super.onDisplayChanged(dc);
214 mOnDisplayChangedCalled = true;
215 }
216
217 @Override
Jorim Jaggia5e10572017-11-15 14:36:26 +0100218 boolean isSelfAnimating() {
219 return mIsAnimating;
Bryce Leeaf691c02017-03-20 14:20:22 -0700220 }
221
222 void setLocalIsAnimating(boolean isAnimating) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700223 mIsAnimating = isAnimating;
224 }
225 }
226
227 /**
228 * Used so we can gain access to some protected members of {@link TaskWindowContainerController}
229 * class.
230 */
231 public static class TestTaskWindowContainerController extends TaskWindowContainerController {
232
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700233 TestTaskWindowContainerController(WindowTestsBase testsBase) {
234 this(testsBase.createStackControllerOnDisplay(testsBase.mDisplayContent));
Bryce Leeaf691c02017-03-20 14:20:22 -0700235 }
236
237 TestTaskWindowContainerController(StackWindowController stackController) {
238 super(sNextTaskId++, new TaskWindowContainerListener() {
239 @Override
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700240 public void registerConfigurationChangeListener(
241 ConfigurationContainerListener listener) {
242
243 }
244
245 @Override
246 public void unregisterConfigurationChangeListener(
247 ConfigurationContainerListener listener) {
248
249 }
250
251 @Override
Bryce Leeaf691c02017-03-20 14:20:22 -0700252 public void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
253
254 }
255
256 @Override
257 public void requestResize(Rect bounds, int resizeMode) {
258
259 }
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700260 }, stackController, 0 /* userId */, null /* bounds */, RESIZE_MODE_UNRESIZEABLE,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700261 false /* supportsPictureInPicture */, true /* toTop*/,
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700262 true /* showForAllUsers */, new ActivityManager.TaskDescription(),
263 stackController.mService);
Bryce Leeaf691c02017-03-20 14:20:22 -0700264 }
265
266 @Override
Bryce Leef3c6a472017-11-14 14:53:06 -0800267 TestTask createTask(int taskId, TaskStack stack, int userId, int resizeMode,
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700268 boolean supportsPictureInPicture, ActivityManager.TaskDescription taskDescription) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800269 return new TestTask(taskId, stack, userId, mService, resizeMode,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700270 supportsPictureInPicture, this);
Bryce Leeaf691c02017-03-20 14:20:22 -0700271 }
272 }
273
274 public static class TestAppWindowContainerController extends AppWindowContainerController {
275
276 final IApplicationToken mToken;
277
278 TestAppWindowContainerController(TestTaskWindowContainerController taskController) {
279 this(taskController, new TestIApplicationToken());
280 }
281
282 TestAppWindowContainerController(TestTaskWindowContainerController taskController,
283 IApplicationToken token) {
284 super(taskController, token, null /* listener */, 0 /* index */,
285 SCREEN_ORIENTATION_UNSPECIFIED, true /* fullscreen */,
286 true /* showForAllUsers */, 0 /* configChanges */, false /* voiceInteraction */,
287 false /* launchTaskBehind */, false /* alwaysFocusable */,
288 0 /* targetSdkVersion */, 0 /* rotationAnimationHint */,
Bryce Leef3c6a472017-11-14 14:53:06 -0800289 0 /* inputDispatchingTimeoutNanos */, taskController.mService);
Bryce Leeaf691c02017-03-20 14:20:22 -0700290 mToken = token;
291 }
292
293 @Override
294 AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
295 boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
296 boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
297 int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
Bryce Leef3c6a472017-11-14 14:53:06 -0800298 boolean alwaysFocusable, AppWindowContainerController controller) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700299 return new TestAppWindowToken(service, token, voiceInteraction, dc,
300 inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
301 orientation,
302 rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
Bryce Leef3c6a472017-11-14 14:53:06 -0800303 controller);
Bryce Leeaf691c02017-03-20 14:20:22 -0700304 }
305
Wale Ogunwale11cc5162017-04-25 20:29:13 -0700306 AppWindowToken getAppWindowToken(DisplayContent dc) {
307 return (AppWindowToken) dc.getWindowToken(mToken.asBinder());
Bryce Leeaf691c02017-03-20 14:20:22 -0700308 }
309 }
310
311 public static class TestIApplicationToken implements IApplicationToken {
312
313 private final Binder mBinder = new Binder();
314 @Override
315 public IBinder asBinder() {
316 return mBinder;
317 }
Steven Timotiusaf03df62017-07-18 16:56:43 -0700318 @Override
319 public String getName() {
320 return null;
321 }
Bryce Leeaf691c02017-03-20 14:20:22 -0700322 }
323
324 /** Used to track resize reports. */
325 public static class TestWindowState extends WindowState {
326 boolean resizeReported;
327
328 TestWindowState(WindowManagerService service, Session session, IWindow window,
329 WindowManager.LayoutParams attrs, WindowToken token) {
330 super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0,
331 false /* ownerCanAddInternalSystemWindow */);
332 }
333
334 @Override
335 void reportResized() {
336 super.reportResized();
337 resizeReported = true;
338 }
339
340 @Override
341 public boolean isGoneForLayoutLw() {
342 return false;
343 }
344
345 @Override
346 void updateResizingWindowIfNeeded() {
347 // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
348 // the system that it can actually update the window.
349 boolean hadSurface = mHasSurface;
350 mHasSurface = true;
351
352 super.updateResizingWindowIfNeeded();
353
354 mHasSurface = hadSurface;
355 }
356 }
357}