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.getKeyguardControllerState().isKeyguardOccluded(DEFAULT_DISPLAY); 178 } 179 waitForKeyguardShowingAndNotOccluded()180 public void waitForKeyguardShowingAndNotOccluded() { 181 waitForWithAmState(WindowManagerStateHelper::isKeyguardShowingAndNotOccluded, 182 "Keyguard showing"); 183 } 184 waitForKeyguardShowingAndOccluded()185 public void waitForKeyguardShowingAndOccluded() { 186 waitForWithAmState(state -> state.getKeyguardControllerState().keyguardShowing 187 && state.getKeyguardControllerState().isKeyguardOccluded(DEFAULT_DISPLAY), 188 "Keyguard showing and occluded"); 189 } 190 waitForAodShowing()191 public void waitForAodShowing() { 192 waitForWithAmState(state -> state.getKeyguardControllerState().aodShowing, "AOD showing"); 193 } 194 waitForKeyguardGone()195 public void waitForKeyguardGone() { 196 waitForWithAmState(state -> !state.getKeyguardControllerState().keyguardShowing, 197 "Keyguard gone"); 198 } 199 waitAndAssertKeyguardGone()200 public void waitAndAssertKeyguardGone() { 201 assertTrue("Keyguard must be gone", 202 waitForWithAmState( 203 state -> !state.getKeyguardControllerState().keyguardShowing, 204 "Keyguard gone")); 205 } 206 207 /** Wait for specific rotation for the default display. Values are Surface#Rotation */ waitForRotation(int rotation)208 public void waitForRotation(int rotation) { 209 waitForWithAmState(state -> state.getRotation() == rotation, "Rotation: " + rotation); 210 } 211 212 /** 213 * Wait for specific orientation for the default display. 214 * Values are ActivityInfo.ScreenOrientation 215 */ waitForLastOrientation(int orientation)216 public void waitForLastOrientation(int orientation) { 217 waitForWithAmState(state -> state.getLastOrientation() == orientation, 218 "LastOrientation: " + orientation); 219 } 220 waitAndAssertLastOrientation(String message, int screenOrientation)221 public void waitAndAssertLastOrientation(String message, int screenOrientation) { 222 if (screenOrientation != getLastOrientation()) { 223 waitForLastOrientation(screenOrientation); 224 } 225 assertEquals(message, screenOrientation, getLastOrientation()); 226 } 227 228 /** 229 * Wait for orientation for the Activity 230 */ waitForActivityOrientation(ComponentName activityName, int orientation)231 public void waitForActivityOrientation(ComponentName activityName, int orientation) { 232 waitForWithAmState(amState -> { 233 final Task task = amState.getTaskByActivity(activityName); 234 if (task == null) { 235 return false; 236 } 237 return task.mFullConfiguration.orientation == orientation; 238 }, "orientation of " + getActivityName(activityName) + " to be " + orientation); 239 } 240 waitForDisplayUnfrozen()241 public void waitForDisplayUnfrozen() { 242 waitForWithAmState(state -> !state.isDisplayFrozen(), "Display unfrozen"); 243 } 244 waitForActivityState(ComponentName activityName, String activityState)245 public void waitForActivityState(ComponentName activityName, String activityState) { 246 waitForWithAmState(state -> state.hasActivityState(activityName, activityState), 247 "state of " + getActivityName(activityName) + " to be " + activityState); 248 } 249 waitForActivityRemoved(ComponentName activityName)250 public void waitForActivityRemoved(ComponentName activityName) { 251 waitFor((amState) -> !amState.containsActivity(activityName) 252 && !amState.containsWindow(getWindowName(activityName)), 253 getActivityName(activityName) + " to be removed"); 254 } 255 waitAndAssertActivityRemoved(ComponentName activityName)256 public void waitAndAssertActivityRemoved(ComponentName activityName) { 257 waitForActivityRemoved(activityName); 258 assertNotExist(activityName); 259 } 260 waitForFocusedStack(int windowingMode, int activityType)261 public void waitForFocusedStack(int windowingMode, int activityType) { 262 waitForWithAmState(state -> 263 (activityType == ACTIVITY_TYPE_UNDEFINED 264 || state.getFocusedRootTaskActivityType() == activityType) 265 && (windowingMode == WINDOWING_MODE_UNDEFINED 266 || state.getFocusedRootTaskWindowingMode() == windowingMode), 267 "focused stack"); 268 } 269 waitForPendingActivityContain(ComponentName activity)270 public void waitForPendingActivityContain(ComponentName activity) { 271 waitForWithAmState(state -> state.pendingActivityContain(activity), 272 getActivityName(activity) + " in pending list"); 273 } 274 waitForAppTransitionRunningOnDisplay(int displayId)275 public boolean waitForAppTransitionRunningOnDisplay(int displayId) { 276 return waitForWithAmState( 277 state -> WindowManagerState.APP_STATE_RUNNING.equals( 278 state.getDisplay(displayId).getAppTransitionState()), 279 "app transition running on Display " + displayId); 280 } 281 waitForAppTransitionIdleOnDisplay(int displayId)282 public boolean waitForAppTransitionIdleOnDisplay(int displayId) { 283 return waitForWithAmState( 284 state -> WindowManagerState.APP_STATE_IDLE.equals( 285 state.getDisplay(displayId).getAppTransitionState()), 286 "app transition idle on Display " + displayId); 287 } 288 waitAndAssertNavBarShownOnDisplay(int displayId)289 void waitAndAssertNavBarShownOnDisplay(int displayId) { 290 waitAndAssertNavBarShownOnDisplay(displayId, 1 /* expectedNavBarCount */); 291 } 292 waitAndAssertNavBarShownOnDisplay(int displayId, int expectedNavBarCount)293 void waitAndAssertNavBarShownOnDisplay(int displayId, int expectedNavBarCount) { 294 assertTrue(waitForWithAmState(state -> { 295 List<WindowState> navWindows = state 296 .getAndAssertNavBarWindowsOnDisplay(displayId, expectedNavBarCount); 297 298 return navWindows != null; 299 }, "navigation bar #" + displayId + " show")); 300 } 301 waitAndAssertKeyguardShownOnSecondaryDisplay(int displayId)302 public void waitAndAssertKeyguardShownOnSecondaryDisplay(int displayId) { 303 assertTrue("KeyguardDialog must be shown on secondary display " + displayId, 304 waitForWithAmState( 305 state -> isKeyguardOnSecondaryDisplay(state, displayId), 306 "keyguard window to show")); 307 } 308 waitAndAssertKeyguardGoneOnSecondaryDisplay(int displayId)309 public void waitAndAssertKeyguardGoneOnSecondaryDisplay(int displayId) { 310 assertTrue("KeyguardDialog must be gone on secondary display " + displayId, 311 waitForWithAmState( 312 state -> !isKeyguardOnSecondaryDisplay(state, displayId), 313 "keyguard window to dismiss")); 314 } 315 waitForWindowSurfaceDisappeared(String windowName)316 void waitForWindowSurfaceDisappeared(String windowName) { 317 waitForWithAmState(state -> { 318 return !state.isWindowSurfaceShown(windowName); 319 }, windowName + "'s surface is disappeared"); 320 } 321 waitAndAssertWindowSurfaceShown(String windowName, boolean shown)322 void waitAndAssertWindowSurfaceShown(String windowName, boolean shown) { 323 assertTrue( 324 waitForWithAmState(state -> state.isWindowSurfaceShown(windowName) == shown, 325 windowName + "'s isWindowSurfaceShown to return " + shown)); 326 } 327 328 /** A variant of waitForWithAmState with different parameter order for better Kotlin interop. */ waitForWithAmState(String message, Predicate<WindowManagerState> waitCondition)329 public boolean waitForWithAmState(String message, Predicate<WindowManagerState> waitCondition) { 330 return waitForWithAmState(waitCondition, message); 331 } 332 waitForWithAmState(Predicate<WindowManagerState> waitCondition, String message)333 public boolean waitForWithAmState(Predicate<WindowManagerState> waitCondition, 334 String message) { 335 return waitFor((amState) -> waitCondition.test(amState), message); 336 } 337 waitWindowingModeTopFocus(int windowingMode, boolean topFocus, String message)338 public void waitWindowingModeTopFocus(int windowingMode, boolean topFocus, String message) { 339 waitForWithAmState(amState -> { 340 final Task rootTask = amState.getStandardRootTaskByWindowingMode(windowingMode); 341 return rootTask != null 342 && topFocus == (amState.getFocusedTaskId() == rootTask.getRootTaskId()); 343 }, message); 344 } 345 waitForFocusedActivity(final String msg, final ComponentName activityName)346 public void waitForFocusedActivity(final String msg, final ComponentName activityName) { 347 final String activityComponentName = getActivityName(activityName); 348 waitFor(msg, wmState -> Objects.equals(activityComponentName, wmState.getFocusedActivity()) 349 && Objects.equals(activityComponentName, wmState.getFocusedApp())); 350 } 351 352 /** A variant of waitFor with different parameter order for better Kotlin interop. */ waitFor(String message, Predicate<WindowManagerState> waitCondition)353 public boolean waitFor(String message, Predicate<WindowManagerState> waitCondition) { 354 return waitFor(waitCondition, message); 355 } 356 357 /** @return {@code true} if the wait is successful; {@code false} if timeout occurs. */ waitFor(Predicate<WindowManagerState> waitCondition, String message)358 public boolean waitFor(Predicate<WindowManagerState> waitCondition, String message) { 359 return Condition.waitFor(message, () -> { 360 computeState(); 361 return waitCondition.test(this); 362 }); 363 } 364 365 /** Waits for non-null result from {@code function} and returns it. */ waitForResult(String message, Function<WindowManagerState, T> function)366 public <T> T waitForResult(String message, Function<WindowManagerState, T> function) { 367 return waitForResult(message, function, Objects::nonNull); 368 } 369 waitForResult(String message, Function<WindowManagerState, T> function, Predicate<T> validator)370 public <T> T waitForResult(String message, Function<WindowManagerState, T> function, 371 Predicate<T> validator) { 372 return Condition.waitForResult(new Condition<T>(message) 373 .setResultSupplier(() -> { 374 computeState(); 375 return function.apply(this); 376 }) 377 .setResultValidator(validator)); 378 } 379 380 /** 381 * @return true if should wait for valid stacks state. 382 */ 383 private boolean shouldWaitForValidStacks() { 384 final int stackCount = getRootTaskCount(); 385 if (stackCount == 0) { 386 logAlways("***stackCount=" + stackCount); 387 return true; 388 } 389 final int resumedActivitiesCount = getResumedActivitiesCount(); 390 if (!getKeyguardControllerState().keyguardShowing && resumedActivitiesCount < 1) { 391 logAlways("***resumedActivitiesCount=" + resumedActivitiesCount); 392 return true; 393 } 394 if (getFocusedActivity() == null) { 395 logAlways("***focusedActivity=null"); 396 return true; 397 } 398 return false; 399 } 400 401 public void waitAndAssertAppFocus(String appPackageName, long waitTime) { 402 final Condition<String> condition = new Condition<>(appPackageName + " to be focused"); 403 Condition.waitFor(condition.setResultSupplier(() -> { 404 computeState(); 405 return getFocusedApp(); 406 }).setResultValidator(focusedAppName -> { 407 return focusedAppName != null && appPackageName.equals( 408 ComponentName.unflattenFromString(focusedAppName).getPackageName()); 409 }).setOnFailure(focusedAppName -> { 410 fail("Timed out waiting for focus on app " 411 + appPackageName + ", last was " + focusedAppName); 412 }).setRetryIntervalMs(100).setRetryLimit((int) waitTime / 100)); 413 } 414 415 /** 416 * @return true if should wait for some activities to become visible. 417 */ 418 private boolean shouldWaitForActivities(WaitForValidActivityState... waitForActivitiesVisible) { 419 if (waitForActivitiesVisible == null || waitForActivitiesVisible.length == 0) { 420 return false; 421 } 422 // If the caller is interested in us waiting for some particular activity windows to be 423 // visible before compute the state. Check for the visibility of those activity windows 424 // and for placing them in correct stacks (if requested). 425 boolean allActivityWindowsVisible = true; 426 boolean tasksInCorrectStacks = true; 427 for (final WaitForValidActivityState state : waitForActivitiesVisible) { 428 final ComponentName activityName = state.activityName; 429 final String windowName = state.windowName; 430 final int stackId = state.stackId; 431 final int windowingMode = state.windowingMode; 432 final int activityType = state.activityType; 433 434 final List<WindowState> matchingWindowStates = 435 getMatchingVisibleWindowState(windowName); 436 boolean activityWindowVisible = !matchingWindowStates.isEmpty(); 437 if (!activityWindowVisible) { 438 logAlways("Activity window not visible: " + windowName); 439 allActivityWindowsVisible = false; 440 } else if (activityName != null 441 && !isActivityVisible(activityName)) { 442 logAlways("Activity not visible: " + getActivityName(activityName)); 443 allActivityWindowsVisible = false; 444 } else { 445 // Check if window is already the correct state requested by test. 446 boolean windowInCorrectState = false; 447 for (WindowState ws : matchingWindowStates) { 448 if (stackId != INVALID_STACK_ID && ws.getStackId() != stackId) { 449 continue; 450 } 451 if (!ws.isWindowingModeCompatible(windowingMode)) { 452 continue; 453 } 454 if (activityType != ACTIVITY_TYPE_UNDEFINED 455 && ws.getActivityType() != activityType) { 456 continue; 457 } 458 windowInCorrectState = true; 459 break; 460 } 461 462 if (!windowInCorrectState) { 463 logAlways("Window in incorrect stack: " + state); 464 tasksInCorrectStacks = false; 465 } 466 } 467 } 468 return !allActivityWindowsVisible || !tasksInCorrectStacks; 469 } 470 471 /** 472 * @return true if should wait valid windows state. 473 */ 474 private boolean shouldWaitForWindows() { 475 if (getFrontWindow() == null) { 476 logAlways("***frontWindow=null"); 477 return true; 478 } 479 if (getFocusedWindow() == null) { 480 logAlways("***focusedWindow=null"); 481 return true; 482 } 483 if (getFocusedApp() == null) { 484 logAlways("***focusedApp=null"); 485 return true; 486 } 487 488 return false; 489 } 490 491 private boolean shouldWaitForDebuggerWindow(ComponentName activityName) { 492 List<WindowState> matchingWindowStates = 493 getMatchingVisibleWindowState(activityName.getPackageName()); 494 for (WindowState ws : matchingWindowStates) { 495 if (ws.isDebuggerWindow()) { 496 return false; 497 } 498 } 499 logAlways("Debugger window not available yet"); 500 return true; 501 } 502 503 private boolean shouldWaitForActivityRecords(ComponentName... activityNames) { 504 // Check if the activity records we're looking for is already added. 505 for (final ComponentName activityName : activityNames) { 506 if (!isActivityVisible(activityName)) { 507 logAlways("ActivityRecord " + getActivityName(activityName) + " not visible yet"); 508 return true; 509 } 510 } 511 return false; 512 } 513 514 private boolean shouldWaitForValidityCheck() { 515 try { 516 assertValidity(); 517 } catch (Throwable t) { 518 logAlways("Waiting for validity check: " + t.toString()); 519 return true; 520 } 521 return false; 522 } 523 524 void assertValidity() { 525 assertThat("Must have root task", getRootTaskCount(), greaterThan(0)); 526 // TODO: Update when keyguard will be shown on multiple displays 527 if (!getKeyguardControllerState().keyguardShowing) { 528 assertThat("There should be at least one resumed activity in the system.", 529 getResumedActivitiesCount(), greaterThanOrEqualTo(1)); 530 } 531 assertNotNull("Must have focus activity.", getFocusedActivity()); 532 533 for (Task rootTask : getRootTasks()) { 534 final int taskId = rootTask.mRootTaskId; 535 for (Task task : rootTask.getTasks()) { 536 assertEquals("Root task can only contain its own tasks", taskId, 537 task.mRootTaskId); 538 } 539 } 540 541 assertNotNull("Must have front window.", getFrontWindow()); 542 assertNotNull("Must have focused window.", getFocusedWindow()); 543 assertNotNull("Must have app.", getFocusedApp()); 544 } 545 546 public void assertContainsStack(String msg, int windowingMode, int activityType) { 547 assertTrue(msg, containsRootTasks(windowingMode, activityType)); 548 } 549 550 public void assertDoesNotContainStack(String msg, int windowingMode, int activityType) { 551 assertFalse(msg, containsRootTasks(windowingMode, activityType)); 552 } 553 554 public void assertFrontStack(String msg, int windowingMode, int activityType) { 555 assertFrontStackOnDisplay(msg, windowingMode, activityType, DEFAULT_DISPLAY); 556 } 557 558 public void assertFrontStackOnDisplay(String msg, int windowingMode, int activityType, 559 int displayId) { 560 if (windowingMode != WINDOWING_MODE_UNDEFINED) { 561 assertEquals(msg, windowingMode, getFrontRootTaskWindowingMode(displayId)); 562 } 563 if (activityType != ACTIVITY_TYPE_UNDEFINED) { 564 assertEquals(msg, activityType, getFrontRootTaskActivityType(displayId)); 565 } 566 } 567 568 public void assertFrontStackActivityType(String msg, int activityType) { 569 assertEquals(msg, activityType, getFrontRootTaskActivityType(DEFAULT_DISPLAY)); 570 } 571 572 void assertFocusedRootTask(String msg, int taskId) { 573 assertEquals(msg, taskId, getFocusedTaskId()); 574 } 575 576 void assertFocusedRootTask(String msg, int windowingMode, int activityType) { 577 if (windowingMode != WINDOWING_MODE_UNDEFINED) { 578 assertEquals(msg, windowingMode, getFocusedRootTaskWindowingMode()); 579 } 580 if (activityType != ACTIVITY_TYPE_UNDEFINED) { 581 assertEquals(msg, activityType, getFocusedRootTaskActivityType()); 582 } 583 } 584 585 public void assertFocusedActivity(final String msg, final ComponentName activityName) { 586 final String activityComponentName = getActivityName(activityName); 587 assertEquals(msg, activityComponentName, getFocusedActivity()); 588 assertEquals(msg, activityComponentName, getFocusedApp()); 589 } 590 591 public void assertFocusedAppOnDisplay(final String msg, final ComponentName activityName, 592 final int displayId) { 593 final String activityComponentName = getActivityName(activityName); 594 assertEquals(msg, activityComponentName, getDisplay(displayId).getFocusedApp()); 595 } 596 597 public void assertNotFocusedActivity(String msg, ComponentName activityName) { 598 assertNotEquals(msg, getFocusedActivity(), getActivityName(activityName)); 599 assertNotEquals(msg, getFocusedApp(), getActivityName(activityName)); 600 } 601 602 public void assertResumedActivity(final String msg, final ComponentName activityName) { 603 assertEquals(msg, getActivityName(activityName), 604 getFocusedActivity()); 605 } 606 607 /** Asserts that each display has correct resumed activity. */ 608 public void assertResumedActivities(final String msg, 609 Consumer<SparseArray<ComponentName>> resumedActivitiesMapping) { 610 final SparseArray<ComponentName> resumedActivities = new SparseArray<>(); 611 resumedActivitiesMapping.accept(resumedActivities); 612 for (int i = 0; i < resumedActivities.size(); i++) { 613 final int displayId = resumedActivities.keyAt(i); 614 final ComponentName activityComponent = resumedActivities.valueAt(i); 615 assertEquals("Error asserting resumed activity on display " + displayId + ": " + msg, 616 activityComponent != null ? getActivityName(activityComponent) : null, 617 getResumedActivityOnDisplay(displayId)); 618 } 619 } 620 621 public void assertNotResumedActivity(String msg, ComponentName activityName) { 622 assertNotEquals(msg, getFocusedActivity(), getActivityName(activityName)); 623 } 624 625 public void assertFocusedWindow(String msg, String windowName) { 626 assertEquals(msg, windowName, getFocusedWindow()); 627 } 628 629 public void assertNotFocusedWindow(String msg, String windowName) { 630 assertNotEquals(msg, getFocusedWindow(), windowName); 631 } 632 633 public void assertNotExist(final ComponentName activityName) { 634 final String windowName = getWindowName(activityName); 635 assertFalse("Activity=" + getActivityName(activityName) + " must NOT exist.", 636 containsActivity(activityName)); 637 assertFalse("Window=" + windowName + " must NOT exits.", 638 containsWindow(windowName)); 639 } 640 641 public void waitAndAssertVisibilityGone(final ComponentName activityName) { 642 // Sometimes the surface can be shown due to the late animation. 643 // Wait for the animation is done. 644 waitForWindowSurfaceDisappeared(getWindowName(activityName)); 645 assertVisibility(activityName, false); 646 } 647 648 public void assertVisibility(final ComponentName activityName, final boolean visible) { 649 final String windowName = getWindowName(activityName); 650 // Check existence of activity and window. 651 assertTrue("Activity=" + getActivityName(activityName) + " must exist.", 652 containsActivity(activityName)); 653 assertTrue("Window=" + windowName + " must exist.", containsWindow(windowName)); 654 655 // Check visibility of activity and window. 656 assertEquals("Activity=" + getActivityName(activityName) + " must" + (visible ? "" : " NOT") 657 + " be visible.", visible, isActivityVisible(activityName)); 658 assertEquals("Window=" + windowName + " must" + (visible ? "" : " NOT") 659 + " have shown surface.", 660 visible, isWindowSurfaceShown(windowName)); 661 } 662 663 public void assertHomeActivityVisible(boolean visible) { 664 final ComponentName homeActivity = getHomeActivityName(); 665 assertNotNull(homeActivity); 666 assertVisibility(homeActivity, visible); 667 } 668 669 /** 670 * Asserts that the device default display minimim width is larger than the minimum task width. 671 */ 672 void assertDeviceDefaultDisplaySizeForMultiWindow(String errorMessage) { 673 computeState(); 674 final int minTaskSizePx = defaultMinimalTaskSize(DEFAULT_DISPLAY); 675 final WindowManagerState.DisplayContent display = getDisplay(DEFAULT_DISPLAY); 676 final Rect displayRect = display.getDisplayRect(); 677 if (Math.min(displayRect.width(), displayRect.height()) < minTaskSizePx) { 678 fail(errorMessage); 679 } 680 } 681 682 /** 683 * Asserts that the device default display minimum width is not smaller than the minimum width 684 * for split-screen required by CDD. 685 */ 686 void assertDeviceDefaultDisplaySizeForSplitScreen(String errorMessage) { 687 computeState(); 688 final int minDisplaySizePx = defaultMinimalDisplaySizeForSplitScreen(DEFAULT_DISPLAY); 689 final WindowManagerState.DisplayContent display = getDisplay(DEFAULT_DISPLAY); 690 final Rect displayRect = display.getDisplayRect(); 691 if (Math.max(displayRect.width(), displayRect.height()) < minDisplaySizePx) { 692 fail(errorMessage); 693 } 694 } 695 696 public void assertKeyguardShowingAndOccluded() { 697 assertTrue("Keyguard is showing", 698 getKeyguardControllerState().keyguardShowing); 699 assertTrue("Keyguard is occluded", 700 getKeyguardControllerState().isKeyguardOccluded(DEFAULT_DISPLAY)); 701 } 702 703 public void assertKeyguardShowingAndNotOccluded() { 704 assertTrue("Keyguard is showing", 705 getKeyguardControllerState().keyguardShowing); 706 assertFalse("Keyguard is not occluded", 707 getKeyguardControllerState().isKeyguardOccluded(DEFAULT_DISPLAY)); 708 } 709 710 public void assertKeyguardGone() { 711 assertFalse("Keyguard is not shown", 712 getKeyguardControllerState().keyguardShowing); 713 } 714 715 void assertKeyguardShownOnSecondaryDisplay(int displayId) { 716 assertTrue("KeyguardDialog must be shown on display " + displayId, 717 isKeyguardOnSecondaryDisplay(this, displayId)); 718 } 719 720 void assertKeyguardGoneOnSecondaryDisplay(int displayId) { 721 assertFalse("KeyguardDialog must be gone on display " + displayId, 722 isKeyguardOnSecondaryDisplay(this, displayId)); 723 } 724 725 public void assertAodShowing() { 726 assertTrue("AOD is showing", 727 getKeyguardControllerState().aodShowing); 728 } 729 730 public void assertAodNotShowing() { 731 assertFalse("AOD is not showing", 732 getKeyguardControllerState().aodShowing); 733 } 734 735 public void assertIllegalTaskState() { 736 computeState(); 737 final List<Task> tasks = getRootTasks(); 738 for (Task task : tasks) { 739 task.forAllTasks((t) -> assertWithMessage("Empty task was found, id = " + t.mTaskId) 740 .that(t.mTasks.size() + t.mActivities.size()).isGreaterThan(0)); 741 if (task.isLeafTask()) { 742 continue; 743 } 744 assertWithMessage("Non-leaf task cannot have affinity set, id = " + task.mTaskId) 745 .that(task.mAffinity).isEmpty(); 746 } 747 } 748 749 public void assumePendingActivityContain(ComponentName activity) { 750 assumeTrue(pendingActivityContain(activity)); 751 } 752 753 public void assertActivityDisplayed(final ComponentName activityName) { 754 assertWindowDisplayed(getWindowName(activityName)); 755 } 756 757 public void assertWindowDisplayed(final String windowName) { 758 waitForValidState(WaitForValidActivityState.forWindow(windowName)); 759 assertTrue(windowName + " is visible", isWindowSurfaceShown(windowName)); 760 } 761 762 void waitAndAssertImeWindowShownOnDisplay(int displayId) { 763 final WindowState imeWinState = Condition.waitForResult("IME window", 764 condition -> condition 765 .setResultSupplier(this::getImeWindowState) 766 .setResultValidator( 767 w -> w != null && w.isSurfaceShown() 768 && w.getDisplayId() == displayId)); 769 770 assertNotNull("IME window must exist", imeWinState); 771 assertTrue("IME window must be shown", imeWinState.isSurfaceShown()); 772 assertEquals("IME window must be on the given display", displayId, 773 imeWinState.getDisplayId()); 774 } 775 776 WindowState getImeWindowState() { 777 computeState(); 778 return getInputMethodWindowState(); 779 } 780 781 boolean isScreenPortrait(int displayId) { 782 final Rect displayRect = getDisplay(displayId).getDisplayRect(); 783 return displayRect.height() > displayRect.width(); 784 } 785 786 private static boolean isKeyguardOnSecondaryDisplay( 787 WindowManagerState windowManagerState, int displayId) { 788 final List<WindowManagerState.WindowState> states = 789 windowManagerState.getMatchingWindowType(TYPE_KEYGUARD_DIALOG); 790 for (WindowManagerState.WindowState ws : states) { 791 if (ws.getDisplayId() == displayId) return true; 792 } 793 return false; 794 } 795 } 796