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