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 17 package com.android.server.wm; 18 19 import android.app.ActivityManager; 20 import android.content.Context; 21 import android.content.res.Configuration; 22 import android.graphics.Rect; 23 import android.os.Binder; 24 import android.os.IBinder; 25 import android.view.IApplicationToken; 26 import android.view.IWindow; 27 import android.view.WindowManager; 28 29 import static android.app.AppOpsManager.OP_NONE; 30 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; 31 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 32 import static android.content.res.Configuration.EMPTY; 33 import static com.android.server.wm.WindowContainer.POSITION_TOP; 34 import 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 */ 40 public class WindowTestUtils { 41 public static int sNextTaskId = 0; 42 43 /** 44 * Retrieves an instance of {@link WindowManagerService}, creating it if necessary. 45 */ getWindowManagerService(Context context)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 */ getMockWindowManagerService()53 public static WindowManagerService getMockWindowManagerService() { 54 return mock(WindowManagerService.class); 55 } 56 57 /** 58 * Creates a mock instance of {@link StackWindowController}. 59 */ createMockStackWindowContainerController()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}. */ createTaskInStack(WindowManagerService service, TaskStack stack, int userId)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 { TestTaskStack(WindowManagerService service, int stackId)80 TestTaskStack(WindowManagerService service, int stackId) { 81 super(service, stackId); 82 } 83 84 @Override addTask(Task task, int position, boolean showForAllUsers, boolean moveParents)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 TestAppWindowToken(DisplayContent dc)93 TestAppWindowToken(DisplayContent dc) { 94 super(dc.mService, new IApplicationToken.Stub() {}, false, dc, true /* fillsParent */, 95 null /* overrideConfig */, null /* bounds */); 96 } 97 TestAppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint, int configChanges, boolean launchTaskBehind, boolean alwaysFocusable, AppWindowContainerController controller, Configuration overrideConfig, Rect bounds)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 getWindowsCount()109 int getWindowsCount() { 110 return mChildren.size(); 111 } 112 hasWindow(WindowState w)113 boolean hasWindow(WindowState w) { 114 return mChildren.contains(w); 115 } 116 getFirstChild()117 WindowState getFirstChild() { 118 return mChildren.peekFirst(); 119 } 120 getLastChild()121 WindowState getLastChild() { 122 return mChildren.peekLast(); 123 } 124 positionInParent()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 TestWindowToken(int type, DisplayContent dc)134 TestWindowToken(int type, DisplayContent dc) { 135 this(type, dc, false /* persistOnEmpty */); 136 } 137 TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty)138 TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) { 139 super(dc.mService, mock(IBinder.class), type, persistOnEmpty, dc, 140 false /* ownerCanManageAppTokens */); 141 } 142 getWindowsCount()143 int getWindowsCount() { 144 return mChildren.size(); 145 } 146 hasWindow(WindowState w)147 boolean hasWindow(WindowState w) { 148 return mChildren.contains(w); 149 } 150 151 @Override getAnimLayerAdjustment()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 TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds, Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture, boolean homeTask, TaskWindowContainerController controller)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 shouldDeferRemoval()172 boolean shouldDeferRemoval() { 173 return mShouldDeferRemoval; 174 } 175 positionInParent()176 int positionInParent() { 177 return getParent().mChildren.indexOf(this); 178 } 179 180 @Override onDisplayChanged(DisplayContent dc)181 void onDisplayChanged(DisplayContent dc) { 182 super.onDisplayChanged(dc); 183 mOnDisplayChangedCalled = true; 184 } 185 186 @Override isAnimating()187 boolean isAnimating() { 188 return mUseLocalIsAnimating ? mIsAnimating : super.isAnimating(); 189 } 190 setLocalIsAnimating(boolean isAnimating)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 TestTaskWindowContainerController(WindowTestsBase testsBase)203 TestTaskWindowContainerController(WindowTestsBase testsBase) { 204 this(testsBase.createStackControllerOnDisplay(testsBase.mDisplayContent)); 205 } 206 TestTaskWindowContainerController(StackWindowController stackController)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 createTask(int taskId, TaskStack stack, int userId, Rect bounds, Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture, boolean homeTask, ActivityManager.TaskDescription taskDescription)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 TestAppWindowContainerController(TestTaskWindowContainerController taskController)238 TestAppWindowContainerController(TestTaskWindowContainerController taskController) { 239 this(taskController, new TestIApplicationToken()); 240 } 241 TestAppWindowContainerController(TestTaskWindowContainerController taskController, IApplicationToken token)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 createAppWindow(WindowManagerService service, IApplicationToken token, boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint, int configChanges, boolean launchTaskBehind, boolean alwaysFocusable, AppWindowContainerController controller, Configuration overrideConfig, Rect bounds)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 getAppWindowToken(DisplayContent dc)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 asBinder()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 TestWindowState(WindowManagerService service, Session session, IWindow window, WindowManager.LayoutParams attrs, WindowToken token)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 reportResized()293 void reportResized() { 294 super.reportResized(); 295 resizeReported = true; 296 } 297 298 @Override isGoneForLayoutLw()299 public boolean isGoneForLayoutLw() { 300 return false; 301 } 302 303 @Override updateResizingWindowIfNeeded()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