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