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 17 package android.server.wm; 18 19 import static android.app.ActivityTaskManager.INVALID_STACK_ID; 20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; 21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; 22 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 23 import static android.server.wm.ComponentNameUtils.getActivityName; 24 import static android.server.wm.ComponentNameUtils.getWindowName; 25 import static android.server.wm.StateLogger.logAlways; 26 import static android.server.wm.StateLogger.logE; 27 import static android.view.Display.DEFAULT_DISPLAY; 28 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 29 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; 30 31 import static com.google.common.truth.Truth.assertWithMessage; 32 33 import static org.hamcrest.Matchers.greaterThan; 34 import static org.hamcrest.Matchers.greaterThanOrEqualTo; 35 import static org.junit.Assert.assertEquals; 36 import static org.junit.Assert.assertFalse; 37 import static org.junit.Assert.assertNotEquals; 38 import static org.junit.Assert.assertNotNull; 39 import static org.junit.Assert.assertThat; 40 import static org.junit.Assert.assertTrue; 41 import static org.junit.Assert.fail; 42 import static org.junit.Assume.assumeTrue; 43 44 import android.content.ComponentName; 45 import android.graphics.Rect; 46 import android.util.SparseArray; 47 import android.view.InputEvent; 48 49 import java.util.Arrays; 50 import java.util.List; 51 import java.util.Objects; 52 import java.util.concurrent.TimeUnit; 53 import java.util.function.Consumer; 54 import java.util.function.Function; 55 import java.util.function.Predicate; 56 import java.util.stream.Stream; 57 58 /** Window Manager State helper class with assert and wait functions. */ 59 public class WindowManagerStateHelper extends WindowManagerState { 60 61 /** 62 * Compute AM and WM state of device, check validity and bounds. 63 * WM state will include only visible windows, stack and task bounds will be compared. 64 * 65 * @param componentNames array of activity names to wait for. 66 */ computeState(ComponentName... componentNames)67 public void computeState(ComponentName... componentNames) { 68 waitForValidState(Arrays.stream(componentNames) 69 .map(WaitForValidActivityState::new) 70 .toArray(WaitForValidActivityState[]::new)); 71 } 72 73 /** 74 * Compute AM and WM state of device, check validity and bounds. 75 * WM state will include only visible windows, stack and task bounds will be compared. 76 * 77 * @param waitForActivitiesVisible array of activity names to wait for. 78 */ computeState(WaitForValidActivityState... waitForActivitiesVisible)79 public void computeState(WaitForValidActivityState... waitForActivitiesVisible) { 80 waitForValidState(waitForActivitiesVisible); 81 } 82 83 /** 84 * Wait for the activities to appear and for valid state in AM and WM. 85 * 86 * @param activityNames name list of activities to wait for. 87 */ waitForValidState(ComponentName... activityNames)88 public void waitForValidState(ComponentName... activityNames) { 89 waitForValidState(Arrays.stream(activityNames) 90 .map(WaitForValidActivityState::new) 91 .toArray(WaitForValidActivityState[]::new)); 92 93 } 94 95 /** 96 * Wait for the activities to appear in proper stacks and for valid state in AM and WM. 97 * @param waitForActivitiesVisible array of activity states to wait for. 98 */ waitForValidState(WaitForValidActivityState... waitForActivitiesVisible)99 public void waitForValidState(WaitForValidActivityState... waitForActivitiesVisible) { 100 if (!Condition.waitFor("valid stacks and activities states", () -> { 101 // TODO: Get state of AM and WM at the same time to avoid mismatches caused by 102 // requesting dump in some intermediate state. 103 computeState(); 104 return !(shouldWaitForValidityCheck() 105 || shouldWaitForValidStacks() 106 || shouldWaitForActivities(waitForActivitiesVisible) 107 || shouldWaitForWindows()); 108 })) { 109 logE("***Waiting for states failed: " + Arrays.toString(waitForActivitiesVisible)); 110 } 111 } 112 waitForAllStoppedActivities()113 public void waitForAllStoppedActivities() { 114 if (!Condition.waitFor("all started activities have been removed", () -> { 115 computeState(); 116 return !containsStartedActivities(); 117 })) { 118 fail("All started activities have been removed"); 119 } 120 } 121 waitForAllNonHomeActivitiesToDestroyed()122 public void waitForAllNonHomeActivitiesToDestroyed() { 123 Condition.waitFor("all non-home activities to be destroyed", () -> { 124 computeState(); 125 for (Task rootTask : getRootTasks()) { 126 final Activity activity = rootTask.getActivity( 127 (a) -> !a.state.equals(STATE_DESTROYED) 128 && a.getActivityType() != ACTIVITY_TYPE_HOME); 129 if (activity != null) return false; 130 } 131 return true; 132 }); 133 } 134 135 /** 136 * Compute AM and WM state of device, wait for the activity records to be added, and 137 * wait for debugger window to show up. 138 * 139 * This should only be used when starting with -D (debugger) option, where we pop up the 140 * waiting-for-debugger window, but real activity window won't show up since we're waiting 141 * for debugger. 142 */ waitForDebuggerWindowVisible(ComponentName activityName)143 public void waitForDebuggerWindowVisible(ComponentName activityName) { 144 Condition.waitFor("debugger window", () -> { 145 computeState(); 146 return !shouldWaitForDebuggerWindow(activityName) 147 && !shouldWaitForActivityRecords(activityName); 148 }); 149 } 150 waitForHomeActivityVisible()151 public void waitForHomeActivityVisible() { 152 ComponentName homeActivity = getHomeActivityName(); 153 // Sometimes this function is called before we know what Home Activity is 154 if (homeActivity == null) { 155 logAlways("Computing state to determine Home Activity"); 156 computeState(); 157 homeActivity = getHomeActivityName(); 158 } 159 assertNotNull("homeActivity should not be null", homeActivity); 160 waitForValidState(homeActivity); 161 } 162 163 /** @return {@code true} if the recents is visible; {@code false} if timeout occurs. */ waitForRecentsActivityVisible()164 public boolean waitForRecentsActivityVisible() { 165 if (isHomeRecentsComponent()) { 166 waitForHomeActivityVisible(); 167 return true; 168 } else { 169 return waitForWithAmState(WindowManagerState::isRecentsActivityVisible, 170 "recents activity to be visible"); 171 } 172 } 173 waitForDreamGone()174 public void waitForDreamGone() { 175 assertTrue("Dream must be gone", 176 waitForWithAmState(state -> state.getDreamTask() == null, "DreamActivity gone")); 177 } 178 isKeyguardOccluded(WindowManagerState state)179 public static boolean isKeyguardOccluded(WindowManagerState state) { 180 return state.getKeyguardControllerState().isKeyguardOccluded(DEFAULT_DISPLAY); 181 } 182 isKeyguardShowingAndNotOccluded(WindowManagerState state)183 public static boolean isKeyguardShowingAndNotOccluded(WindowManagerState state) { 184 return state.getKeyguardControllerState().keyguardShowing 185 && state.getKeyguardServiceDelegateState().isKeyguardAwake() 186 && !state.getKeyguardControllerState().mKeyguardGoingAway 187 && !state.getKeyguardControllerState().aodShowing 188 && !state.getKeyguardControllerState().isKeyguardOccluded(DEFAULT_DISPLAY); 189 } 190 waitForKeyguardShowingAndNotOccluded()191 public void waitForKeyguardShowingAndNotOccluded() { 192 waitForWithAmState(WindowManagerStateHelper::isKeyguardShowingAndNotOccluded, 193 "Keyguard showing"); 194 } 195 waitForKeyguardShowingAndOccluded()196 public void waitForKeyguardShowingAndOccluded() { 197 waitForWithAmState(state -> state.getKeyguardControllerState().keyguardShowing 198 && state.getKeyguardControllerState().isKeyguardOccluded(DEFAULT_DISPLAY), 199 "Keyguard showing and occluded"); 200 } 201 waitAndAssertWindowShown(int windowType, boolean show)202 public void waitAndAssertWindowShown(int windowType, boolean show) { 203 assertTrue(waitFor(state -> { 204 Stream<WindowState> windows = getMatchingWindows( 205 ws -> ws.isSurfaceShown() == show && ws.getType() == windowType); 206 return windows.findAny().isPresent(); 207 }, "wait for window surface " + (show ? "show" : "hide"))); 208 } 209 waitForAodShowing()210 public void waitForAodShowing() { 211 waitForWithAmState(state -> state.getKeyguardControllerState().aodShowing, "AOD showing"); 212 } 213 waitForKeyguardGone()214 public void waitForKeyguardGone() { 215 waitForWithAmState(state -> !state.getKeyguardControllerState().keyguardShowing, 216 "Keyguard gone"); 217 } 218 waitAndAssertKeyguardGone()219 public void waitAndAssertKeyguardGone() { 220 assertTrue("Keyguard must be gone", 221 waitForWithAmState( 222 state -> !state.getKeyguardControllerState().keyguardShowing, 223 "Keyguard gone")); 224 } 225 226 /** 227 * Wait for specific rotation for the default display. 228 * @param rotation Surface#Rotation 229 */ waitForRotation(int rotation)230 public boolean waitForRotation(int rotation) { 231 return waitForWithAmState(state -> state.getRotation() == rotation, 232 "Rotation: " + rotation); 233 } 234 235 /** 236 * Wait for specific orientation for the default display. 237 * @param screenOrientation ActivityInfo#ScreenOrientation 238 */ waitForLastOrientation(int screenOrientation)239 public void waitForLastOrientation(int screenOrientation) { 240 waitForWithAmState(state -> state.getLastOrientation() == screenOrientation, 241 "LastOrientation: " + screenOrientation); 242 } 243 244 /** 245 * @param message log message 246 * @param screenOrientation ActivityInfo#ScreenOrientation 247 */ waitAndAssertLastOrientation(String message, int screenOrientation)248 public void waitAndAssertLastOrientation(String message, int screenOrientation) { 249 if (screenOrientation != getLastOrientation()) { 250 waitForLastOrientation(screenOrientation); 251 } 252 assertEquals(message, screenOrientation, getLastOrientation()); 253 } 254 255 /** Waits for the configuration orientation (landscape or portrait) of the default display. 256 * @param configOrientation Configuration#Orientation 257 */ waitForDisplayOrientation(int configOrientation)258 public void waitForDisplayOrientation(int configOrientation) { 259 waitForWithAmState(state -> state.getDisplay(DEFAULT_DISPLAY) 260 .mFullConfiguration.orientation == configOrientation, 261 "orientation of default display to be " + configOrientation); 262 } 263 264 /** 265 * Wait for the configuration orientation of the Activity. 266 * @param activityName activity 267 * @param configOrientation Configuration#Orientation 268 */ waitForActivityOrientation(ComponentName activityName, int configOrientation)269 public boolean waitForActivityOrientation(ComponentName activityName, int configOrientation) { 270 return waitForWithAmState(amState -> { 271 final Activity activity = amState.getActivity(activityName); 272 return activity != null && activity.mFullConfiguration.orientation == configOrientation; 273 }, "orientation of " + getActivityName(activityName) + " to be " + configOrientation); 274 } 275 waitForDisplayUnfrozen()276 public void waitForDisplayUnfrozen() { 277 waitForWithAmState(state -> !state.isDisplayFrozen(), "Display unfrozen"); 278 } 279 waitForActivityState(ComponentName activityName, String activityState)280 public boolean waitForActivityState(ComponentName activityName, String activityState) { 281 return waitForWithAmState(state -> state.hasActivityState(activityName, activityState), 282 "state of " + getActivityName(activityName) + " to be " + activityState); 283 } 284 waitAndAssertActivityState(ComponentName activityName, String activityState)285 public void waitAndAssertActivityState(ComponentName activityName, String activityState) { 286 assertTrue(waitForActivityState(activityName, activityState)); 287 } 288 waitForActivityRemoved(ComponentName activityName)289 public void waitForActivityRemoved(ComponentName activityName) { 290 waitFor((amState) -> !amState.containsActivity(activityName) 291 && !amState.containsWindow(getWindowName(activityName)), 292 getActivityName(activityName) + " to be removed"); 293 } 294 waitAndAssertActivityRemoved(ComponentName activityName)295 public void waitAndAssertActivityRemoved(ComponentName activityName) { 296 waitForActivityRemoved(activityName); 297 assertNotExist(activityName); 298 } 299 waitForFocusedStack(int windowingMode, int activityType)300 public void waitForFocusedStack(int windowingMode, int activityType) { 301 waitForWithAmState(state -> 302 (activityType == ACTIVITY_TYPE_UNDEFINED 303 || state.getFocusedRootTaskActivityType() == activityType) 304 && (windowingMode == WINDOWING_MODE_UNDEFINED 305 || state.getFocusedRootTaskWindowingMode() == windowingMode), 306 "focused stack"); 307 } 308 waitForPendingActivityContain(ComponentName activity)309 public void waitForPendingActivityContain(ComponentName activity) { 310 waitForWithAmState(state -> state.pendingActivityContain(activity), 311 getActivityName(activity) + " in pending list"); 312 } 313 waitForAppTransitionRunningOnDisplay(int displayId)314 public boolean waitForAppTransitionRunningOnDisplay(int displayId) { 315 return waitForWithAmState( 316 state -> WindowManagerState.APP_STATE_RUNNING.equals( 317 state.getDisplay(displayId).getAppTransitionState()), 318 "app transition running on Display " + displayId); 319 } 320 waitForAppTransitionIdleOnDisplay(int displayId)321 public boolean waitForAppTransitionIdleOnDisplay(int displayId) { 322 return waitForWithAmState( 323 state -> WindowManagerState.APP_STATE_IDLE.equals( 324 state.getDisplay(displayId).getAppTransitionState()), 325 "app transition idle on Display " + displayId); 326 } 327 waitAndAssertNavBarShownOnDisplay(int displayId)328 public void waitAndAssertNavBarShownOnDisplay(int displayId) { 329 assertTrue(waitForWithAmState(state -> { 330 // There should be at least one nav bar exist. 331 List<WindowState> navWindows = state.getNavBarWindowsOnDisplay(displayId); 332 333 return !navWindows.isEmpty(); 334 }, "navigation bar to show on display #" + displayId)); 335 } 336 waitAndAssertNavBarShownOnDisplay(int displayId, int expectedNavBarCount)337 public void waitAndAssertNavBarShownOnDisplay(int displayId, int expectedNavBarCount) { 338 assertTrue(waitForWithAmState(state -> { 339 List<WindowState> navWindows = state.getNavBarWindowsOnDisplay(displayId); 340 341 return navWindows.size() == expectedNavBarCount; 342 }, expectedNavBarCount + " navigation bar(s) to show on display #" + displayId)); 343 } 344 waitAndAssertKeyguardShownOnSecondaryDisplay(int displayId)345 public void waitAndAssertKeyguardShownOnSecondaryDisplay(int displayId) { 346 assertTrue("KeyguardDialog must be shown on secondary display " + displayId, 347 waitForWithAmState( 348 state -> isKeyguardOnSecondaryDisplay(state, displayId), 349 "keyguard window to show")); 350 } 351 waitAndAssertKeyguardGoneOnSecondaryDisplay(int displayId)352 public void waitAndAssertKeyguardGoneOnSecondaryDisplay(int displayId) { 353 assertTrue("KeyguardDialog must be gone on secondary display " + displayId, 354 waitForWithAmState( 355 state -> !isKeyguardOnSecondaryDisplay(state, displayId), 356 "keyguard window to dismiss")); 357 } 358 waitForWindowSurfaceShown(String windowName, boolean shown)359 public boolean waitForWindowSurfaceShown(String windowName, boolean shown) { 360 final String message = windowName + "'s isWindowSurfaceShown to return " + shown; 361 return Condition.waitFor(new Condition<>(message, () -> { 362 computeState(); 363 return isWindowSurfaceShown(windowName) == shown; 364 }).setRetryIntervalMs(200).setRetryLimit(20)); 365 } 366 367 void waitForWindowSurfaceDisappeared(String windowName) { 368 waitForWindowSurfaceShown(windowName, false); 369 } 370 371 public void waitAndAssertWindowSurfaceShown(String windowName, boolean shown) { 372 assertTrue(waitForWindowSurfaceShown(windowName, shown)); 373 } 374 375 /** A variant of waitForWithAmState with different parameter order for better Kotlin interop. */ 376 public boolean waitForWithAmState(String message, Predicate<WindowManagerState> waitCondition) { 377 return waitForWithAmState(waitCondition, message); 378 } 379 380 public boolean waitForWithAmState(Predicate<WindowManagerState> waitCondition, 381 String message) { 382 return waitFor(waitCondition, message); 383 } 384 385 public void waitWindowingModeTopFocus(int windowingMode, boolean topFocus, String message) { 386 waitForWithAmState(amState -> { 387 final Task rootTask = amState.getStandardRootTaskByWindowingMode(windowingMode); 388 return rootTask != null 389 && topFocus == (amState.getFocusedTaskId() == rootTask.getRootTaskId()); 390 }, message); 391 } 392 393 public boolean waitForFocusedActivity(final String msg, final ComponentName activityName) { 394 final String activityComponentName = getActivityName(activityName); 395 return waitFor(msg, wmState -> 396 Objects.equals(activityComponentName, wmState.getFocusedActivity()) 397 && Objects.equals(activityComponentName, wmState.getFocusedApp())); 398 } 399 400 /** A variant of waitFor with different parameter order for better Kotlin interop. */ 401 public boolean waitFor(String message, Predicate<WindowManagerState> waitCondition) { 402 return waitFor(waitCondition, message); 403 } 404 405 /** @return {@code true} if the wait is successful; {@code false} if timeout occurs. */ 406 public boolean waitFor(Predicate<WindowManagerState> waitCondition, String message) { 407 return Condition.waitFor(message, () -> { 408 computeState(); 409 return waitCondition.test(this); 410 }); 411 } 412 413 /** Waits for non-null result from {@code function} and returns it. */ 414 public <T> T waitForResult(String message, Function<WindowManagerState, T> function) { 415 return waitForResult(message, function, Objects::nonNull); 416 } 417 418 public <T> T waitForResult(String message, Function<WindowManagerState, T> function, 419 Predicate<T> validator) { 420 return Condition.waitForResult(new Condition<T>(message) 421 .setResultSupplier(() -> { 422 computeState(); 423 return function.apply(this); 424 }) 425 .setResultValidator(validator)); 426 } 427 428 /** 429 * @return true if should wait for valid stacks state. 430 */ 431 private boolean shouldWaitForValidStacks() { 432 final int stackCount = getRootTaskCount(); 433 if (stackCount == 0) { 434 logAlways("***stackCount=" + stackCount); 435 return true; 436 } 437 final int resumedActivitiesCount = getResumedActivitiesCount(); 438 if (!getKeyguardControllerState().keyguardShowing && resumedActivitiesCount < 1) { 439 logAlways("***resumedActivitiesCount=" + resumedActivitiesCount); 440 return true; 441 } 442 if (getFocusedActivity() == null) { 443 logAlways("***focusedActivity=null"); 444 return true; 445 } 446 return false; 447 } 448 449 public void waitAndAssertAppFocus(String appPackageName, long waitTime) { 450 final Condition<String> condition = new Condition<>(appPackageName + " to be focused"); 451 Condition.waitFor(condition.setResultSupplier(() -> { 452 computeState(); 453 return getFocusedApp(); 454 }).setResultValidator(focusedAppName -> { 455 return focusedAppName != null && appPackageName.equals( 456 ComponentName.unflattenFromString(focusedAppName).getPackageName()); 457 }).setOnFailure(focusedAppName -> { 458 fail("Timed out waiting for focus on app " 459 + appPackageName + ", last was " + focusedAppName); 460 }).setRetryIntervalMs(100).setRetryLimit((int) waitTime / 100)); 461 } 462 463 /** 464 * Waits until the given activity is ready for input, this is only needed when directly 465 * injecting input on screen via 466 * {@link android.hardware.input.InputManager#injectInputEvent(InputEvent, int)}. 467 */ 468 public <T extends android.app.Activity> void waitUntilActivityReadyForInputInjection(T activity, 469 String tag, String windowDumpErrMsg) throws InterruptedException { 470 // If we requested an orientation change, just waiting for the window to be visible is not 471 // sufficient. We should first wait for the transitions to stop, and the for app's UI thread 472 // to process them before making sure the window is visible. 473 CtsWindowInfoUtils.waitForStableWindowGeometry(5, TimeUnit.SECONDS); 474 if (activity.getWindow() != null 475 && !CtsWindowInfoUtils.waitForWindowOnTop(activity.getWindow())) { 476 CtsWindowInfoUtils.dumpWindowsOnScreen(tag, windowDumpErrMsg); 477 fail("Activity window did not become visible: " + activity); 478 } 479 } 480 481 /** 482 * @return true if should wait for some activities to become visible. 483 */ 484 private boolean shouldWaitForActivities(WaitForValidActivityState... waitForActivitiesVisible) { 485 if (waitForActivitiesVisible == null || waitForActivitiesVisible.length == 0) { 486 return false; 487 } 488 // If the caller is interested in us waiting for some particular activity windows to be 489 // visible before compute the state. Check for the visibility of those activity windows 490 // and for placing them in correct stacks (if requested). 491 boolean allActivityWindowsVisible = true; 492 boolean tasksInCorrectStacks = true; 493 for (final WaitForValidActivityState state : waitForActivitiesVisible) { 494 final ComponentName activityName = state.activityName; 495 final String windowName = state.windowName; 496 final int stackId = state.stackId; 497 final int windowingMode = state.windowingMode; 498 final int activityType = state.activityType; 499 500 final List<WindowState> matchingWindowStates = 501 getMatchingVisibleWindowState(windowName); 502 boolean activityWindowVisible = !matchingWindowStates.isEmpty(); 503 if (!activityWindowVisible) { 504 logAlways("Activity window not visible: " + windowName); 505 allActivityWindowsVisible = false; 506 } else if (activityName != null 507 && !isActivityVisible(activityName)) { 508 logAlways("Activity not visible: " + getActivityName(activityName)); 509 allActivityWindowsVisible = false; 510 } else { 511 // Check if window is already the correct state requested by test. 512 boolean windowInCorrectState = false; 513 for (WindowState ws : matchingWindowStates) { 514 if (stackId != INVALID_STACK_ID && ws.getStackId() != stackId) { 515 continue; 516 } 517 if (!ws.isWindowingModeCompatible(windowingMode)) { 518 continue; 519 } 520 if (activityType != ACTIVITY_TYPE_UNDEFINED 521 && ws.getActivityType() != activityType) { 522 continue; 523 } 524 windowInCorrectState = true; 525 break; 526 } 527 528 if (!windowInCorrectState) { 529 logAlways("Window in incorrect stack: " + state); 530 tasksInCorrectStacks = false; 531 } 532 } 533 } 534 return !allActivityWindowsVisible || !tasksInCorrectStacks; 535 } 536 537 /** 538 * @return true if should wait valid windows state. 539 */ 540 private boolean shouldWaitForWindows() { 541 if (getFrontWindow() == null) { 542 logAlways("***frontWindow=null"); 543 return true; 544 } 545 if (getFocusedWindow() == null) { 546 logAlways("***focusedWindow=null"); 547 return true; 548 } 549 if (getFocusedApp() == null) { 550 logAlways("***focusedApp=null"); 551 return true; 552 } 553 554 return false; 555 } 556 557 private boolean shouldWaitForDebuggerWindow(ComponentName activityName) { 558 List<WindowState> matchingWindowStates = 559 getMatchingVisibleWindowState(activityName.getPackageName()); 560 for (WindowState ws : matchingWindowStates) { 561 if (ws.isDebuggerWindow()) { 562 return false; 563 } 564 } 565 logAlways("Debugger window not available yet"); 566 return true; 567 } 568 569 private boolean shouldWaitForActivityRecords(ComponentName... activityNames) { 570 // Check if the activity records we're looking for is already added. 571 for (final ComponentName activityName : activityNames) { 572 if (!isActivityVisible(activityName)) { 573 logAlways("ActivityRecord " + getActivityName(activityName) + " not visible yet"); 574 return true; 575 } 576 } 577 return false; 578 } 579 580 private boolean shouldWaitForValidityCheck() { 581 try { 582 assertValidity(); 583 } catch (Throwable t) { 584 logAlways("Waiting for validity check: " + t.toString()); 585 return true; 586 } 587 return false; 588 } 589 590 public void assertValidity() { 591 assertThat("Must have root task", getRootTaskCount(), greaterThan(0)); 592 // TODO: Update when keyguard will be shown on multiple displays 593 if (!getKeyguardControllerState().keyguardShowing) { 594 assertThat("There should be at least one resumed activity in the system.", 595 getResumedActivitiesCount(), greaterThanOrEqualTo(1)); 596 } 597 assertNotNull("Must have focus activity.", getFocusedActivity()); 598 599 for (Task rootTask : getRootTasks()) { 600 final int taskId = rootTask.mRootTaskId; 601 for (Task task : rootTask.getTasks()) { 602 assertEquals("Root task can only contain its own tasks", taskId, 603 task.mRootTaskId); 604 } 605 } 606 607 assertNotNull("Must have front window.", getFrontWindow()); 608 assertNotNull("Must have focused window.", getFocusedWindow()); 609 assertNotNull("Must have app.", getFocusedApp()); 610 } 611 612 public void assertContainsStack(String msg, int windowingMode, int activityType) { 613 assertTrue(msg, containsRootTasks(windowingMode, activityType)); 614 } 615 616 public void assertDoesNotContainStack(String msg, int windowingMode, int activityType) { 617 assertFalse(msg, containsRootTasks(windowingMode, activityType)); 618 } 619 620 public void assertFrontStack(String msg, int windowingMode, int activityType) { 621 assertFrontStackOnDisplay(msg, windowingMode, activityType, DEFAULT_DISPLAY); 622 } 623 624 public void assertFrontStackOnDisplay(String msg, int windowingMode, int activityType, 625 int displayId) { 626 if (windowingMode != WINDOWING_MODE_UNDEFINED) { 627 assertEquals(msg, windowingMode, getFrontRootTaskWindowingMode(displayId)); 628 } 629 if (activityType != ACTIVITY_TYPE_UNDEFINED) { 630 assertEquals(msg, activityType, getFrontRootTaskActivityType(displayId)); 631 } 632 } 633 634 public void assertFrontStackActivityType(String msg, int activityType) { 635 assertEquals(msg, activityType, getFrontRootTaskActivityType(DEFAULT_DISPLAY)); 636 } 637 638 public void assertFocusedRootTask(String msg, int taskId) { 639 assertEquals(msg, taskId, getFocusedTaskId()); 640 } 641 642 public void assertFocusedRootTask(String msg, int windowingMode, int activityType) { 643 if (windowingMode != WINDOWING_MODE_UNDEFINED) { 644 assertEquals(msg, windowingMode, getFocusedRootTaskWindowingMode()); 645 } 646 if (activityType != ACTIVITY_TYPE_UNDEFINED) { 647 assertEquals(msg, activityType, getFocusedRootTaskActivityType()); 648 } 649 } 650 651 public void assertFocusedActivity(final String msg, final ComponentName activityName) { 652 final String activityComponentName = getActivityName(activityName); 653 assertEquals(msg, activityComponentName, getFocusedActivity()); 654 assertEquals(msg, activityComponentName, getFocusedApp()); 655 } 656 657 public boolean waitForFocusedActivity(final ComponentName activityName) { 658 final String activityComponentName = getActivityName(activityName); 659 final String message = activityComponentName + " to be focused"; 660 return Condition.waitFor(new Condition<>(message, () -> { 661 boolean focusedActivityMatching = activityComponentName.equals(getFocusedActivity()); 662 boolean focusedAppMatching = activityComponentName.equals(getFocusedApp()); 663 return focusedActivityMatching && focusedAppMatching; 664 }).setRetryIntervalMs(200).setRetryLimit(20)); 665 } 666 667 public void waitAndAssertFocusedActivity(final String msg, final ComponentName activityName) { 668 assertTrue(msg, waitForFocusedActivity(activityName)); 669 } 670 671 public void assertFocusedAppOnDisplay(final String msg, final ComponentName activityName, 672 final int displayId) { 673 final String activityComponentName = getActivityName(activityName); 674 assertEquals(msg, activityComponentName, getDisplay(displayId).getFocusedApp()); 675 } 676 677 public void assertNotFocusedActivity(String msg, ComponentName activityName) { 678 assertNotEquals(msg, getFocusedActivity(), getActivityName(activityName)); 679 assertNotEquals(msg, getFocusedApp(), getActivityName(activityName)); 680 } 681 682 public void assertResumedActivity(final String msg, final ComponentName activityName) { 683 assertEquals(msg, getActivityName(activityName), 684 getFocusedActivity()); 685 } 686 687 /** Asserts that each display has correct resumed activity. */ 688 public void assertResumedActivities(final String msg, 689 Consumer<SparseArray<ComponentName>> resumedActivitiesMapping) { 690 final SparseArray<ComponentName> resumedActivities = new SparseArray<>(); 691 resumedActivitiesMapping.accept(resumedActivities); 692 for (int i = 0; i < resumedActivities.size(); i++) { 693 final int displayId = resumedActivities.keyAt(i); 694 final ComponentName activityComponent = resumedActivities.valueAt(i); 695 assertEquals("Error asserting resumed activity on display " + displayId + ": " + msg, 696 activityComponent != null ? getActivityName(activityComponent) : null, 697 getResumedActivityOnDisplay(displayId)); 698 } 699 } 700 701 public void assertNotResumedActivity(String msg, ComponentName activityName) { 702 assertNotEquals(msg, getFocusedActivity(), getActivityName(activityName)); 703 } 704 705 public void assertFocusedWindow(String msg, String windowName) { 706 assertEquals(msg, windowName, getFocusedWindow()); 707 } 708 709 public void assertNotFocusedWindow(String msg, String windowName) { 710 assertNotEquals(msg, getFocusedWindow(), windowName); 711 } 712 713 public void assertNotExist(final ComponentName activityName) { 714 final String windowName = getWindowName(activityName); 715 assertFalse("Activity=" + getActivityName(activityName) + " must NOT exist.", 716 containsActivity(activityName)); 717 assertFalse("Window=" + windowName + " must NOT exits.", 718 containsWindow(windowName)); 719 } 720 721 public void waitAndAssertVisibilityGone(final ComponentName activityName) { 722 // Sometimes the surface can be shown due to the late animation. 723 // Wait for the animation is done. 724 waitForWindowSurfaceDisappeared(getWindowName(activityName)); 725 assertVisibility(activityName, false); 726 } 727 728 public void assertVisibility(final ComponentName activityName, final boolean visible) { 729 final String windowName = getWindowName(activityName); 730 // Check existence of activity and window. 731 assertTrue("Activity=" + getActivityName(activityName) + " must exist.", 732 containsActivity(activityName)); 733 assertTrue("Window=" + windowName + " must exist.", containsWindow(windowName)); 734 735 // Check visibility of activity and window. 736 assertEquals("Activity=" + getActivityName(activityName) + " must" + (visible ? "" : " NOT") 737 + " be visible.", visible, isActivityVisible(activityName)); 738 assertEquals("Window=" + windowName + " must" + (visible ? "" : " NOT") 739 + " have shown surface.", 740 visible, isWindowSurfaceShown(windowName)); 741 } 742 743 public void assertHomeActivityVisible(boolean visible) { 744 final ComponentName homeActivity = getHomeActivityName(); 745 assertNotNull(homeActivity); 746 assertVisibility(homeActivity, visible); 747 } 748 749 /** 750 * Asserts that the device default display minimum width is larger than the minimum task width. 751 */ 752 public void assertDeviceDefaultDisplaySizeForMultiWindow(String errorMessage) { 753 computeState(); 754 final int minTaskSizePx = defaultMinimalTaskSize(DEFAULT_DISPLAY); 755 final WindowManagerState.DisplayContent display = getDisplay(DEFAULT_DISPLAY); 756 final Rect displayRect = display.getDisplayRect(); 757 if (Math.min(displayRect.width(), displayRect.height()) < minTaskSizePx) { 758 fail(errorMessage); 759 } 760 } 761 762 /** 763 * Asserts that the device default display minimum width is not smaller than the minimum width 764 * for split-screen required by CDD. 765 */ 766 public void assertDeviceDefaultDisplaySizeForSplitScreen(String errorMessage) { 767 computeState(); 768 final int minDisplaySizePx = defaultMinimalDisplaySizeForSplitScreen(DEFAULT_DISPLAY); 769 final WindowManagerState.DisplayContent display = getDisplay(DEFAULT_DISPLAY); 770 final Rect displayRect = display.getDisplayRect(); 771 if (Math.max(displayRect.width(), displayRect.height()) < minDisplaySizePx) { 772 fail(errorMessage); 773 } 774 } 775 776 public void assertKeyguardShowingAndOccluded() { 777 assertTrue("Keyguard must be showing", 778 getKeyguardControllerState().keyguardShowing); 779 assertFalse("keyguard must not be going away", 780 getKeyguardControllerState().mKeyguardGoingAway); 781 assertTrue("Keyguard must be occluded", 782 getKeyguardControllerState().isKeyguardOccluded(DEFAULT_DISPLAY)); 783 } 784 785 public void assertKeyguardShowingAndNotOccluded() { 786 assertTrue("Keyguard must be showing", 787 getKeyguardControllerState().keyguardShowing); 788 assertFalse("Keyguard must not be going away", 789 getKeyguardControllerState().mKeyguardGoingAway); 790 assertFalse("Keyguard must not be occluded", 791 getKeyguardControllerState().isKeyguardOccluded(DEFAULT_DISPLAY)); 792 } 793 794 public void assertKeyguardGone() { 795 assertFalse("Keyguard is not shown", 796 getKeyguardControllerState().keyguardShowing); 797 assertFalse("Keyguard must not be going away", 798 getKeyguardControllerState().mKeyguardGoingAway); 799 } 800 801 public void assertKeyguardShownOnSecondaryDisplay(int displayId) { 802 assertTrue("KeyguardDialog must be shown on display " + displayId, 803 isKeyguardOnSecondaryDisplay(this, displayId)); 804 } 805 806 public void assertKeyguardGoneOnSecondaryDisplay(int displayId) { 807 assertFalse("KeyguardDialog must be gone on display " + displayId, 808 isKeyguardOnSecondaryDisplay(this, displayId)); 809 } 810 811 public void assertAodShowing() { 812 assertTrue("AOD is showing", 813 getKeyguardControllerState().aodShowing); 814 } 815 816 public void assertAodNotShowing() { 817 assertFalse("AOD is not showing", 818 getKeyguardControllerState().aodShowing); 819 } 820 821 public void assertIllegalTaskState() { 822 computeState(); 823 final List<Task> tasks = getRootTasks(); 824 for (Task task : tasks) { 825 task.forAllTasks((t) -> assertWithMessage("Empty task was found, id = " + t.mTaskId) 826 .that(t.mTasks.size() + t.mTaskFragments.size() + t.mActivities.size()) 827 .isGreaterThan(0)); 828 if (task.isLeafTask()) { 829 continue; 830 } 831 assertWithMessage("Non-leaf task cannot have affinity set, id = " + task.mTaskId) 832 .that(task.mAffinity).isEmpty(); 833 } 834 } 835 836 public void assumePendingActivityContain(ComponentName activity) { 837 assumeTrue(pendingActivityContain(activity)); 838 } 839 840 public void assertActivityDisplayed(final ComponentName activityName) { 841 assertWindowDisplayed(getWindowName(activityName)); 842 } 843 844 public void assertWindowDisplayed(final String windowName) { 845 waitForValidState(WaitForValidActivityState.forWindow(windowName)); 846 assertTrue(windowName + " is visible", isWindowSurfaceShown(windowName)); 847 } 848 849 public void waitAndAssertImePickerShownOnDisplay(int displayId, String message) { 850 if (!Condition.waitFor(message, () -> { 851 computeState(); 852 return getMatchingWindowType(TYPE_INPUT_METHOD_DIALOG).stream().anyMatch( 853 w -> w.getDisplayId() == displayId && w.isSurfaceShown()); 854 })) { 855 fail(message); 856 } 857 } 858 859 public void waitAndAssertImeWindowShownOnDisplay(int displayId) { 860 final WindowState imeWinState = Condition.waitForResult("IME window", 861 condition -> condition 862 .setResultSupplier(this::getImeWindowState) 863 .setResultValidator( 864 w -> w != null && w.isSurfaceShown() 865 && w.getDisplayId() == displayId)); 866 867 assertNotNull("IME window must exist", imeWinState); 868 assertTrue("IME window must be shown", imeWinState.isSurfaceShown()); 869 assertEquals("IME window must be on the given display", displayId, 870 imeWinState.getDisplayId()); 871 } 872 873 public void waitAndAssertImeWindowHiddenOnDisplay(int displayId) { 874 final WindowState imeWinState = Condition.waitForResult("IME window", 875 condition -> condition 876 .setResultSupplier(this::getImeWindowState) 877 .setResultValidator(w -> w == null 878 || (!w.isSurfaceShown() && w.getDisplayId() == displayId))); 879 880 if (imeWinState == null) { 881 return; 882 } 883 assertFalse("IME window must be hidden", imeWinState.isSurfaceShown()); 884 assertEquals("IME window must be on the given display", displayId, 885 imeWinState.getDisplayId()); 886 } 887 888 public WindowState getImeWindowState() { 889 computeState(); 890 return getInputMethodWindowState(); 891 } 892 893 /** 894 * @return the window state for the given {@param activityName}'s window. 895 */ 896 public WindowState getWindowState(ComponentName activityName) { 897 String windowName = getWindowName(activityName); 898 computeState(activityName); 899 final List<WindowManagerState.WindowState> tempWindowList = 900 getMatchingVisibleWindowState(windowName); 901 return tempWindowList.get(0); 902 } 903 904 boolean isScreenPortrait(int displayId) { 905 final Rect displayRect = getDisplay(displayId).getDisplayRect(); 906 return displayRect.height() > displayRect.width(); 907 } 908 909 private static boolean isKeyguardOnSecondaryDisplay( 910 WindowManagerState windowManagerState, int displayId) { 911 final List<WindowManagerState.WindowState> states = 912 windowManagerState.getMatchingWindowType(TYPE_KEYGUARD_DIALOG); 913 for (WindowManagerState.WindowState ws : states) { 914 if (ws.getDisplayId() == displayId) return true; 915 } 916 return false; 917 } 918 } 919