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