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