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