WindowTestsBase.java revision 9bafc7150ea41758cf40ba60eb90deb62217fc34
1/* 2 * Copyright (C) 2016 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.ActivityManagerInternal; 20import android.content.res.Configuration; 21import android.graphics.Rect; 22import android.os.Binder; 23import android.view.IApplicationToken; 24import org.junit.Assert; 25import org.junit.Before; 26import org.mockito.Mock; 27import org.mockito.Mockito; 28import org.mockito.MockitoAnnotations; 29 30import android.content.Context; 31import android.os.IBinder; 32import android.support.test.InstrumentationRegistry; 33import android.view.IWindow; 34import android.view.WindowManager; 35 36import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID; 37import static android.app.AppOpsManager.OP_NONE; 38import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; 39import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 40import static android.content.res.Configuration.EMPTY; 41import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; 42import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 43import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 44import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY; 45import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 46import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; 47import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 48import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 49import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; 50import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; 51import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 52import static com.android.server.wm.WindowContainer.POSITION_TOP; 53import static org.mockito.Mockito.mock; 54 55import com.android.server.AttributeCache; 56import com.android.server.LocalServices; 57 58/** 59 * Common base class for window manager unit test classes. 60 */ 61class WindowTestsBase { 62 static WindowManagerService sWm = null; 63 static TestWindowManagerPolicy sPolicy = null; 64 private final static IWindow sIWindow = new TestIWindow(); 65 private final static Session sMockSession = mock(Session.class); 66 static int sNextStackId = FIRST_DYNAMIC_STACK_ID; 67 private static int sNextTaskId = 0; 68 69 private static boolean sOneTimeSetupDone = false; 70 static DisplayContent sDisplayContent; 71 static WindowLayersController sLayersController; 72 static WindowState sWallpaperWindow; 73 static WindowState sImeWindow; 74 static WindowState sImeDialogWindow; 75 static WindowState sStatusBarWindow; 76 static WindowState sDockedDividerWindow; 77 static WindowState sNavBarWindow; 78 static WindowState sAppWindow; 79 static WindowState sChildAppWindowAbove; 80 static WindowState sChildAppWindowBelow; 81 static @Mock ActivityManagerInternal sMockAm; 82 83 @Before 84 public void setUp() throws Exception { 85 if (sOneTimeSetupDone) { 86 Mockito.reset(sMockAm); 87 return; 88 } 89 sOneTimeSetupDone = true; 90 MockitoAnnotations.initMocks(this); 91 final Context context = InstrumentationRegistry.getTargetContext(); 92 LocalServices.addService(ActivityManagerInternal.class, sMockAm); 93 AttributeCache.init(context); 94 sWm = TestWindowManagerPolicy.getWindowManagerService(context); 95 sPolicy = (TestWindowManagerPolicy) sWm.mPolicy; 96 sLayersController = new WindowLayersController(sWm); 97 sDisplayContent = new DisplayContent(context.getDisplay(), sWm, sLayersController, 98 new WallpaperController(sWm)); 99 sWm.mRoot.addChild(sDisplayContent, 0); 100 sWm.mDisplayEnabled = true; 101 sWm.mDisplayReady = true; 102 103 // Set-up some common windows. 104 sWallpaperWindow = createWindow(null, TYPE_WALLPAPER, sDisplayContent, "wallpaperWindow"); 105 sImeWindow = createWindow(null, TYPE_INPUT_METHOD, sDisplayContent, "sImeWindow"); 106 sImeDialogWindow = 107 createWindow(null, TYPE_INPUT_METHOD_DIALOG, sDisplayContent, "sImeDialogWindow"); 108 sStatusBarWindow = createWindow(null, TYPE_STATUS_BAR, sDisplayContent, "sStatusBarWindow"); 109 sNavBarWindow = 110 createWindow(null, TYPE_NAVIGATION_BAR, sDisplayContent, "sNavBarWindow"); 111 sDockedDividerWindow = 112 createWindow(null, TYPE_DOCK_DIVIDER, sDisplayContent, "sDockedDividerWindow"); 113 sAppWindow = createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "sAppWindow"); 114 sChildAppWindowAbove = createWindow(sAppWindow, 115 TYPE_APPLICATION_ATTACHED_DIALOG, sAppWindow.mToken, "sChildAppWindowAbove"); 116 sChildAppWindowBelow = createWindow(sAppWindow, 117 TYPE_APPLICATION_MEDIA_OVERLAY, sAppWindow.mToken, "sChildAppWindowBelow"); 118 } 119 120 /** Asserts that the first entry is greater than the second entry. */ 121 void assertGreaterThan(int first, int second) throws Exception { 122 Assert.assertTrue("Excepted " + first + " to be greater than " + second, first > second); 123 } 124 125 /** 126 * Waits until the main handler for WM has processed all messages. 127 */ 128 void waitUntilHandlerIdle() { 129 sWm.mH.runWithScissors(() -> { }, 0); 130 } 131 132 private static WindowToken createWindowToken(DisplayContent dc, int type) { 133 if (type < FIRST_APPLICATION_WINDOW || type > LAST_APPLICATION_WINDOW) { 134 return new TestWindowToken(type, dc); 135 } 136 137 final TaskStack stack = createTaskStackOnDisplay(dc); 138 final Task task = createTaskInStack(stack, 0 /* userId */); 139 final TestAppWindowToken token = new TestAppWindowToken(dc); 140 task.addChild(token, 0); 141 return token; 142 } 143 144 static WindowState createWindow(WindowState parent, int type, String name) { 145 return (parent == null) 146 ? createWindow(parent, type, sDisplayContent, name) 147 : createWindow(parent, type, parent.mToken, name); 148 } 149 150 WindowState createAppWindow(Task task, int type, String name) { 151 final AppWindowToken token = new TestAppWindowToken(sDisplayContent); 152 task.addChild(token, 0); 153 return createWindow(null, type, token, name); 154 } 155 156 static WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name) { 157 final WindowToken token = createWindowToken(dc, type); 158 return createWindow(parent, type, token, name); 159 } 160 161 static WindowState createWindow(WindowState parent, int type, WindowToken token, String name) { 162 final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type); 163 attrs.setTitle(name); 164 165 final WindowState w = new WindowState(sWm, sMockSession, sIWindow, token, parent, OP_NONE, 166 0, attrs, 0, 0); 167 // TODO: Probably better to make this call in the WindowState ctor to avoid errors with 168 // adding it to the token... 169 token.addWindow(w); 170 return w; 171 } 172 173 /** Creates a {@link TaskStack} and adds it to the specified {@link DisplayContent}. */ 174 static TaskStack createTaskStackOnDisplay(DisplayContent dc) { 175 final int stackId = sNextStackId++; 176 dc.addStackToDisplay(stackId, true); 177 return sWm.mStackIdToStack.get(stackId); 178 } 179 180 /**Creates a {@link Task} and adds it to the specified {@link TaskStack}. */ 181 static Task createTaskInStack(TaskStack stack, int userId) { 182 final Task newTask = new Task(sNextTaskId++, stack, userId, sWm, null, EMPTY, false, 0, 183 false, null); 184 stack.addTask(newTask, POSITION_TOP); 185 return newTask; 186 } 187 188 /* Used so we can gain access to some protected members of the {@link WindowToken} class */ 189 static class TestWindowToken extends WindowToken { 190 191 TestWindowToken(int type, DisplayContent dc) { 192 this(type, dc, false /* persistOnEmpty */); 193 } 194 195 TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) { 196 super(sWm, mock(IBinder.class), type, persistOnEmpty, dc); 197 } 198 199 int getWindowsCount() { 200 return mChildren.size(); 201 } 202 203 boolean hasWindow(WindowState w) { 204 return mChildren.contains(w); 205 } 206 } 207 208 /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */ 209 static class TestAppWindowToken extends AppWindowToken { 210 211 TestAppWindowToken(DisplayContent dc) { 212 super(sWm, null, false, dc); 213 } 214 215 int getWindowsCount() { 216 return mChildren.size(); 217 } 218 219 boolean hasWindow(WindowState w) { 220 return mChildren.contains(w); 221 } 222 223 WindowState getFirstChild() { 224 return mChildren.getFirst(); 225 } 226 227 WindowState getLastChild() { 228 return mChildren.getLast(); 229 } 230 } 231 232 /* Used so we can gain access to some protected members of the {@link Task} class */ 233 class TestTask extends Task { 234 235 boolean mShouldDeferRemoval = false; 236 boolean mOnDisplayChangedCalled = false; 237 238 TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds, 239 Configuration overrideConfig, boolean isOnTopLauncher, int resizeMode, 240 boolean homeTask, TaskWindowContainerController controller) { 241 super(taskId, stack, userId, service, bounds, overrideConfig, isOnTopLauncher, 242 resizeMode, homeTask, controller); 243 } 244 245 boolean shouldDeferRemoval() { 246 return mShouldDeferRemoval; 247 } 248 249 int positionInParent() { 250 return getParent().mChildren.indexOf(this); 251 } 252 253 @Override 254 void onDisplayChanged(DisplayContent dc) { 255 super.onDisplayChanged(dc); 256 mOnDisplayChangedCalled = true; 257 } 258 } 259 260 /** 261 * Used so we can gain access to some protected members of {@link TaskWindowContainerController} 262 * class. 263 */ 264 class TestTaskWindowContainerController extends TaskWindowContainerController { 265 266 TestTaskWindowContainerController() { 267 this(createTaskStackOnDisplay(sDisplayContent).mStackId); 268 } 269 270 TestTaskWindowContainerController(int stackId) { 271 super(sNextTaskId++, snapshot -> {}, stackId, 0 /* userId */, null /* bounds */, 272 EMPTY /* overrideConfig*/, RESIZE_MODE_UNRESIZEABLE, false /* homeTask*/, 273 false /* isOnTopLauncher */, true /* toTop*/, true /* showForAllUsers */); 274 } 275 276 @Override 277 TestTask createTask(int taskId, TaskStack stack, int userId, Rect bounds, 278 Configuration overrideConfig, int resizeMode, boolean homeTask, 279 boolean isOnTopLauncher) { 280 return new TestTask(taskId, stack, userId, mService, bounds, overrideConfig, 281 isOnTopLauncher, resizeMode, homeTask, this); 282 } 283 } 284 285 class TestAppWindowContainerController extends AppWindowContainerController { 286 287 final IApplicationToken mToken; 288 289 TestAppWindowContainerController(TestTaskWindowContainerController taskController) { 290 this(taskController, new TestIApplicationToken()); 291 } 292 293 TestAppWindowContainerController(TestTaskWindowContainerController taskController, 294 IApplicationToken token) { 295 super(taskController, token, null /* listener */, 0 /* index */, 296 SCREEN_ORIENTATION_UNSPECIFIED, true /* fullscreen */, 297 true /* showForAllUsers */, 0 /* configChanges */, false /* voiceInteraction */, 298 false /* launchTaskBehind */, false /* alwaysFocusable */, 299 0 /* targetSdkVersion */, 0 /* rotationAnimationHint */, 300 0 /* inputDispatchingTimeoutNanos */, sWm); 301 mToken = token; 302 } 303 304 AppWindowToken getAppWindowToken() { 305 return (AppWindowToken) sDisplayContent.getWindowToken(mToken.asBinder()); 306 } 307 } 308 309 class TestIApplicationToken implements IApplicationToken { 310 311 private final Binder mBinder = new Binder(); 312 @Override 313 public IBinder asBinder() { 314 return mBinder; 315 } 316 } 317 318 /** Used to track resize reports. */ 319 class TestWindowState extends WindowState { 320 boolean resizeReported; 321 322 TestWindowState(WindowManager.LayoutParams attrs, WindowToken token) { 323 super(sWm, sMockSession, sIWindow, token, null, OP_NONE, 0, attrs, 0, 0); 324 } 325 326 @Override 327 void reportResized() { 328 super.reportResized(); 329 resizeReported = true; 330 } 331 332 @Override 333 public boolean isGoneForLayoutLw() { 334 return false; 335 } 336 337 @Override 338 void updateResizingWindowIfNeeded() { 339 // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive 340 // the system that it can actually update the window. 341 boolean hadSurface = mHasSurface; 342 mHasSurface = true; 343 344 super.updateResizingWindowIfNeeded(); 345 346 mHasSurface = hadSurface; 347 } 348 } 349} 350