• 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.WindowConfiguration.ACTIVITY_TYPE_DREAM;
20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
23 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
24 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
25 import static android.server.wm.ComponentNameUtils.getActivityName;
26 import static android.server.wm.ProtoExtractors.extract;
27 import static android.server.wm.StateLogger.log;
28 import static android.server.wm.StateLogger.logE;
29 import static android.server.wm.WindowManagerState.Task.INVALID_TASK_ID;
30 import static android.util.DisplayMetrics.DENSITY_DEFAULT;
31 import static android.view.Display.DEFAULT_DISPLAY;
32 import static android.window.DisplayAreaOrganizer.FEATURE_IME;
33 import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
34 
35 import static androidx.test.InstrumentationRegistry.getInstrumentation;
36 
37 import static com.google.common.truth.Truth.assertWithMessage;
38 
39 import static org.junit.Assert.assertTrue;
40 import static org.junit.Assert.fail;
41 
42 import android.app.ActivityTaskManager;
43 import android.app.UiAutomation;
44 import android.content.ComponentName;
45 import android.content.res.Configuration;
46 import android.graphics.Point;
47 import android.graphics.Rect;
48 import android.graphics.nano.RectProto;
49 import android.os.ParcelFileDescriptor;
50 import android.os.SystemClock;
51 import android.util.SparseArray;
52 import android.view.nano.DisplayInfoProto;
53 import android.view.nano.InsetsSourceProto;
54 import android.view.nano.ViewProtoEnums;
55 
56 import androidx.annotation.NonNull;
57 import androidx.annotation.Nullable;
58 
59 import com.android.server.wm.nano.ActivityRecordProto;
60 import com.android.server.wm.nano.AppTransitionProto;
61 import com.android.server.wm.nano.BackNavigationProto;
62 import com.android.server.wm.nano.ConfigurationContainerProto;
63 import com.android.server.wm.nano.DisplayAreaProto;
64 import com.android.server.wm.nano.DisplayContentProto;
65 import com.android.server.wm.nano.DisplayFramesProto;
66 import com.android.server.wm.nano.DisplayRotationProto;
67 import com.android.server.wm.nano.IdentifierProto;
68 import com.android.server.wm.nano.KeyguardControllerProto;
69 import com.android.server.wm.nano.KeyguardServiceDelegateProto;
70 import com.android.server.wm.nano.PinnedTaskControllerProto;
71 import com.android.server.wm.nano.RootWindowContainerProto;
72 import com.android.server.wm.nano.TaskFragmentProto;
73 import com.android.server.wm.nano.TaskProto;
74 import com.android.server.wm.nano.WindowContainerChildProto;
75 import com.android.server.wm.nano.WindowContainerProto;
76 import com.android.server.wm.nano.WindowFramesProto;
77 import com.android.server.wm.nano.WindowManagerServiceDumpProto;
78 import com.android.server.wm.nano.WindowStateAnimatorProto;
79 import com.android.server.wm.nano.WindowStateProto;
80 import com.android.server.wm.nano.WindowSurfaceControllerProto;
81 import com.android.server.wm.nano.WindowTokenProto;
82 
83 import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
84 
85 import java.io.ByteArrayOutputStream;
86 import java.io.FileInputStream;
87 import java.io.IOException;
88 import java.nio.charset.StandardCharsets;
89 import java.util.ArrayList;
90 import java.util.Arrays;
91 import java.util.List;
92 import java.util.Objects;
93 import java.util.function.Consumer;
94 import java.util.function.Predicate;
95 import java.util.stream.Collectors;
96 import java.util.stream.Stream;
97 
98 public class WindowManagerState {
99 
100     public static final String STATE_INITIALIZING = "INITIALIZING";
101     public static final String STATE_STARTED = "STARTED";
102     public static final String STATE_RESUMED = "RESUMED";
103     public static final String STATE_PAUSED = "PAUSED";
104     public static final String STATE_STOPPED = "STOPPED";
105     public static final String STATE_DESTROYED = "DESTROYED";
106     public static final String TRANSIT_ACTIVITY_OPEN = "TRANSIT_ACTIVITY_OPEN";
107     public static final String TRANSIT_ACTIVITY_CLOSE = "TRANSIT_ACTIVITY_CLOSE";
108     public static final String TRANSIT_TASK_OPEN = "TRANSIT_TASK_OPEN";
109     public static final String TRANSIT_TASK_CLOSE = "TRANSIT_TASK_CLOSE";
110     public static final String TRANSIT_WALLPAPER_OPEN = "TRANSIT_WALLPAPER_OPEN";
111     public static final String TRANSIT_WALLPAPER_CLOSE = "TRANSIT_WALLPAPER_CLOSE";
112     public static final String TRANSIT_WALLPAPER_INTRA_OPEN = "TRANSIT_WALLPAPER_INTRA_OPEN";
113     public static final String TRANSIT_WALLPAPER_INTRA_CLOSE = "TRANSIT_WALLPAPER_INTRA_CLOSE";
114     public static final String TRANSIT_KEYGUARD_GOING_AWAY = "TRANSIT_KEYGUARD_GOING_AWAY";
115     public static final String TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER =
116             "TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER";
117     public static final String TRANSIT_KEYGUARD_OCCLUDE = "TRANSIT_KEYGUARD_OCCLUDE";
118     public static final String TRANSIT_KEYGUARD_UNOCCLUDE = "TRANSIT_KEYGUARD_UNOCCLUDE";
119     public static final String TRANSIT_TRANSLUCENT_ACTIVITY_OPEN =
120             "TRANSIT_TRANSLUCENT_ACTIVITY_OPEN";
121     public static final String TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE =
122             "TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE";
123     public static final String APP_STATE_IDLE = "APP_STATE_IDLE";
124     public static final String APP_STATE_RUNNING = "APP_STATE_RUNNING";
125 
126     private static final String DUMPSYS_WINDOW = "dumpsys window -a --proto";
127     private static final String STARTING_WINDOW_PREFIX = "Starting ";
128     private static final String DEBUGGER_WINDOW_PREFIX = "Waiting For Debugger: ";
129     /** @see WindowManager.LayoutParams */
130     private static final int TYPE_NAVIGATION_BAR = 2019;
131     /** @see WindowManager.LayoutParams */
132     private static final int TYPE_NAVIGATION_BAR_PANEL = 2024;
133     /** @see WindowManager.LayoutParams */
134     private static final int TYPE_NOTIFICATION_SHADE = 2040;
135 
136     /** Whether accessibility services should be suppressed when taking the WindowManager dump. */
137     private boolean mSuppressAccessibilityServices = true;
138 
139     private RootWindowContainer mRoot = null;
140     // Displays in z-order with the top most at the front of the list, starting with primary.
141     private final List<DisplayContent> mDisplays = new ArrayList<>();
142     /**
143      * Root tasks in z-order with the top most at the front of the list, starting with primary
144      * display.
145      */
146     private final List<Task> mRootTasks = new ArrayList<>();
147     // Windows in z-order with the top most at the front of the list.
148     private final List<WindowState> mWindowStates = new ArrayList<>();
149     private KeyguardControllerState mKeyguardControllerState;
150     private KeyguardServiceDelegateState mKeyguardServiceDelegateState;
151     private final List<String> mPendingActivities = new ArrayList<>();
152     private int mTopFocusedTaskId = -1;
153     private int mFocusedDisplayId = DEFAULT_DISPLAY;
154     private String mFocusedWindow = null;
155     private String mFocusedApp = null;
156     private Boolean mIsHomeRecentsComponent;
157     private String mTopResumedActivityRecord = null;
158     final List<String> mResumedActivitiesInRootTasks = new ArrayList<>();
159     final List<String> mResumedActivitiesInDisplays = new ArrayList<>();
160     private Rect mDefaultPinnedStackBounds = new Rect();
161     private Rect mPinnedStackMovementBounds = new Rect();
162     private String mInputMethodWindowAppToken = null;
163     private boolean mDisplayFrozen;
164     private boolean mSanityCheckFocusedWindow = true;
165     private boolean mWindowFramesValid;
166     private BackNavigationState mBackNavigationState;
167 
appStateToString(int appState)168     static String appStateToString(int appState) {
169         switch (appState) {
170             case AppTransitionProto.APP_STATE_IDLE:
171                 return "APP_STATE_IDLE";
172             case AppTransitionProto.APP_STATE_READY:
173                 return "APP_STATE_READY";
174             case AppTransitionProto.APP_STATE_RUNNING:
175                 return "APP_STATE_RUNNING";
176             case AppTransitionProto.APP_STATE_TIMEOUT:
177                 return "APP_STATE_TIMEOUT";
178             default:
179                 fail("Invalid AppTransitionState");
180                 return null;
181         }
182     }
183 
appTransitionToString(int transition)184     static String appTransitionToString(int transition) {
185         switch (transition) {
186             case ViewProtoEnums.TRANSIT_UNSET: {
187                 return "TRANSIT_UNSET";
188             }
189             case ViewProtoEnums.TRANSIT_NONE: {
190                 return "TRANSIT_NONE";
191             }
192             case ViewProtoEnums.TRANSIT_ACTIVITY_OPEN: {
193                 return TRANSIT_ACTIVITY_OPEN;
194             }
195             case ViewProtoEnums.TRANSIT_ACTIVITY_CLOSE: {
196                 return TRANSIT_ACTIVITY_CLOSE;
197             }
198             case ViewProtoEnums.TRANSIT_TASK_OPEN: {
199                 return TRANSIT_TASK_OPEN;
200             }
201             case ViewProtoEnums.TRANSIT_TASK_CLOSE: {
202                 return TRANSIT_TASK_CLOSE;
203             }
204             case ViewProtoEnums.TRANSIT_TASK_TO_FRONT: {
205                 return "TRANSIT_TASK_TO_FRONT";
206             }
207             case ViewProtoEnums.TRANSIT_TASK_TO_BACK: {
208                 return "TRANSIT_TASK_TO_BACK";
209             }
210             case ViewProtoEnums.TRANSIT_WALLPAPER_CLOSE: {
211                 return TRANSIT_WALLPAPER_CLOSE;
212             }
213             case ViewProtoEnums.TRANSIT_WALLPAPER_OPEN: {
214                 return TRANSIT_WALLPAPER_OPEN;
215             }
216             case ViewProtoEnums.TRANSIT_WALLPAPER_INTRA_OPEN: {
217                 return TRANSIT_WALLPAPER_INTRA_OPEN;
218             }
219             case ViewProtoEnums.TRANSIT_WALLPAPER_INTRA_CLOSE: {
220                 return TRANSIT_WALLPAPER_INTRA_CLOSE;
221             }
222             case ViewProtoEnums.TRANSIT_TASK_OPEN_BEHIND: {
223                 return "TRANSIT_TASK_OPEN_BEHIND";
224             }
225             case ViewProtoEnums.TRANSIT_ACTIVITY_RELAUNCH: {
226                 return "TRANSIT_ACTIVITY_RELAUNCH";
227             }
228             case ViewProtoEnums.TRANSIT_DOCK_TASK_FROM_RECENTS: {
229                 return "TRANSIT_DOCK_TASK_FROM_RECENTS";
230             }
231             case ViewProtoEnums.TRANSIT_KEYGUARD_GOING_AWAY: {
232                 return TRANSIT_KEYGUARD_GOING_AWAY;
233             }
234             case ViewProtoEnums.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER: {
235                 return TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
236             }
237             case ViewProtoEnums.TRANSIT_KEYGUARD_OCCLUDE: {
238                 return TRANSIT_KEYGUARD_OCCLUDE;
239             }
240             case ViewProtoEnums.TRANSIT_KEYGUARD_UNOCCLUDE: {
241                 return TRANSIT_KEYGUARD_UNOCCLUDE;
242             }
243             case ViewProtoEnums.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN: {
244                 return TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
245             }
246             case ViewProtoEnums.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE: {
247                 return TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
248             }
249             case ViewProtoEnums.TRANSIT_CRASHING_ACTIVITY_CLOSE: {
250                 return "TRANSIT_CRASHING_ACTIVITY_CLOSE";
251             }
252             default: {
253                 fail("Invalid lastUsedAppTransition");
254                 return null;
255             }
256         }
257     }
258 
isValidNavBarType(WindowState navState)259     static boolean isValidNavBarType(WindowState navState) {
260         return TYPE_NAVIGATION_BAR == navState.getType();
261     }
262 
263     /**
264      * For a given WindowContainer, traverse down the hierarchy and add all children of type
265      * {@code T} to {@code outChildren}.
266      */
collectDescendantsOfType(Class<T> clazz, WindowContainer root, List<T> outChildren)267     private static <T extends WindowContainer> void collectDescendantsOfType(Class<T> clazz,
268             WindowContainer root, List<T> outChildren) {
269         collectDescendantsOfTypeIf(clazz, t -> true, root, outChildren);
270     }
271 
272     /**
273      * For a given WindowContainer, traverse down the hierarchy and add all children of type
274      * {@code T} to {@code outChildren} if the child passes the test {@code predicate}.
275      */
collectDescendantsOfTypeIf(Class<T> clazz, Predicate<T> predicate, WindowContainer root, List<T> outChildren)276     private static <T extends WindowContainer> void collectDescendantsOfTypeIf(Class<T> clazz,
277             Predicate<T> predicate, WindowContainer root, List<T> outChildren) {
278         // Traverse top to bottom
279         for (int i = root.mChildren.size()-1; i >= 0; i--) {
280             final WindowContainer child = root.mChildren.get(i);
281             if (clazz.isInstance(child)) {
282                 if(predicate.test(clazz.cast(child))) {
283                     outChildren.add(clazz.cast(child));
284                 }
285             }
286             collectDescendantsOfTypeIf(clazz, predicate, child, outChildren);
287         }
288     }
289 
290     /**
291      * For a given WindowContainer, traverse down the hierarchy and add all immediate children of
292      * type {@code T} to {@code outChildren}.
293      */
collectChildrenOfType(Class<T> clazz, WindowContainer root, List<T> outChildren)294     private static <T extends WindowContainer> void collectChildrenOfType(Class<T> clazz,
295             WindowContainer root, List<T> outChildren) {
296         for (int i = root.mChildren.size()-1; i >= 0; i--) {
297             final WindowContainer child = root.mChildren.get(i);
298             if (clazz.isInstance(child)) {
299                 outChildren.add(clazz.cast(child));
300             }
301         }
302     }
303 
304     /** Enable/disable the mFocusedWindow check during the computeState.*/
setSanityCheckWithFocusedWindow(boolean sanityCheckFocusedWindow)305     void setSanityCheckWithFocusedWindow(boolean sanityCheckFocusedWindow) {
306         mSanityCheckFocusedWindow = sanityCheckFocusedWindow;
307     }
308 
computeState()309     public void computeState() {
310         // It is possible the system is in the middle of transition to the right state when we get
311         // the dump. We try a few times to get the information we need before giving up.
312         int retriesLeft = 3;
313         boolean retry = false;
314         byte[] dump = null;
315 
316         log("==============================");
317         log("     WindowManagerState     ");
318         log("==============================");
319 
320         do {
321             if (retry) {
322                 log("***Incomplete AM state. Retrying...");
323                 // Wait half a second between retries for activity manager to finish transitioning.
324                 SystemClock.sleep(500);
325             }
326 
327             dump = executeShellCommand(DUMPSYS_WINDOW);
328             try {
329                 parseSysDumpProto(dump);
330             } catch (InvalidProtocolBufferNanoException ex) {
331                 throw new RuntimeException("Failed to parse dumpsys:\n"
332                         + new String(dump, StandardCharsets.UTF_8), ex);
333             }
334 
335             retry = mRootTasks.isEmpty() || mTopFocusedTaskId == -1 || mWindowStates.isEmpty()
336                     || mFocusedApp == null || (mSanityCheckFocusedWindow && mFocusedWindow == null)
337                     || !mWindowFramesValid
338                     || (mTopResumedActivityRecord == null
339                     || mResumedActivitiesInRootTasks.isEmpty())
340                     && !mKeyguardControllerState.keyguardShowing;
341         } while (retry && retriesLeft-- > 0);
342 
343         if (mRootTasks.isEmpty()) {
344             logE("No root tasks found...");
345         }
346         if (mTopFocusedTaskId == -1) {
347             logE("No focused task found...");
348         }
349         if (mTopResumedActivityRecord == null) {
350             logE("No focused activity found...");
351         }
352         if (mResumedActivitiesInRootTasks.isEmpty()) {
353             logE("No resumed activities found...");
354         }
355         if (mWindowStates.isEmpty()) {
356             logE("No Windows found...");
357         }
358         if (mFocusedWindow == null) {
359             logE("No Focused Window...");
360         }
361         if (mFocusedApp == null) {
362             logE("No Focused App...");
363         }
364         if (!mWindowFramesValid) {
365             logE("Window Frames Invalid...");
366         }
367     }
368 
setSuppressAccessibilityServices(boolean suppressAccessibilityServices)369     public void setSuppressAccessibilityServices(boolean suppressAccessibilityServices) {
370         mSuppressAccessibilityServices = suppressAccessibilityServices;
371     }
372 
executeShellCommand(String cmd)373     private byte[] executeShellCommand(String cmd) {
374         try {
375             ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation(
376                     mSuppressAccessibilityServices ? 0
377                             : UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES)
378                     .executeShellCommand(cmd);
379             byte[] buf = new byte[512];
380             int bytesRead;
381             FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
382             ByteArrayOutputStream stdout = new ByteArrayOutputStream();
383             while ((bytesRead = fis.read(buf)) != -1) {
384                 stdout.write(buf, 0, bytesRead);
385             }
386             fis.close();
387             return stdout.toByteArray();
388         } catch (IOException e) {
389             throw new RuntimeException(e);
390         }
391     }
392 
393     /** Update WindowManagerState state for a newly added DisplayContent. */
updateForDisplayContent(DisplayContent display)394     private void updateForDisplayContent(DisplayContent display) {
395         if (display.mResumedActivity != null) {
396             mResumedActivitiesInDisplays.add(display.mResumedActivity);
397         }
398 
399         for (int i = 0; i < display.mRootTasks.size(); i++) {
400             Task task = display.mRootTasks.get(i);
401             mRootTasks.add(task);
402             addResumedActivity(task);
403         }
404 
405         if (display.mDefaultPinnedStackBounds != null) {
406             mDefaultPinnedStackBounds = display.mDefaultPinnedStackBounds;
407             mPinnedStackMovementBounds = display.mPinnedStackMovementBounds;
408         }
409     }
410 
addResumedActivity(Task task)411     private void addResumedActivity(Task task) {
412         final int numChildTasks = task.mTasks.size();
413         if (numChildTasks > 0) {
414             for (int i = numChildTasks - 1; i >=0; i--) {
415                 addResumedActivity(task.mTasks.get(i));
416             }
417         } else if (task.mResumedActivity != null) {
418             mResumedActivitiesInRootTasks.add(task.mResumedActivity);
419         }
420     }
421 
parseSysDumpProto(byte[] sysDump)422     private void parseSysDumpProto(byte[] sysDump) throws InvalidProtocolBufferNanoException {
423         reset();
424 
425         WindowManagerServiceDumpProto state = WindowManagerServiceDumpProto.parseFrom(sysDump);
426         final RootWindowContainerProto root = state.rootWindowContainer;
427         if (state.focusedWindow != null) {
428             mFocusedWindow = state.focusedWindow.title;
429         }
430         mRoot = new RootWindowContainer(root);
431         collectDescendantsOfType(DisplayContent.class, mRoot, mDisplays);
432         for (int i = 0; i < mDisplays.size(); i++) {
433             DisplayContent display = mDisplays.get(i);
434             updateForDisplayContent(display);
435         }
436         mKeyguardControllerState = new KeyguardControllerState(root.keyguardController);
437         mKeyguardServiceDelegateState =
438                 new KeyguardServiceDelegateState(state.policy.keyguardDelegate);
439         mFocusedApp = state.focusedApp;
440         mFocusedDisplayId = state.focusedDisplayId;
441         final DisplayContent focusedDisplay = getDisplay(mFocusedDisplayId);
442         if (focusedDisplay != null) {
443             mTopFocusedTaskId = focusedDisplay.mFocusedRootTaskId;
444             mTopResumedActivityRecord = focusedDisplay.mResumedActivity;
445         }
446         mIsHomeRecentsComponent = new Boolean(root.isHomeRecentsComponent);
447 
448         for (int i = 0; i < root.pendingActivities.length; i++) {
449             mPendingActivities.add(root.pendingActivities[i].title);
450         }
451 
452         collectDescendantsOfType(WindowState.class, mRoot, mWindowStates);
453 
454         if (state.inputMethodWindow != null) {
455             mInputMethodWindowAppToken = Integer.toHexString(state.inputMethodWindow.hashCode);
456         }
457         mDisplayFrozen = state.displayFrozen;
458         mWindowFramesValid = state.windowFramesValid;
459 
460         mBackNavigationState = new BackNavigationState(state.backNavigation);
461     }
462 
reset()463     private void reset() {
464         mRoot = null;
465         mDisplays.clear();
466         mRootTasks.clear();
467         mWindowStates.clear();
468         mTopFocusedTaskId = -1;
469         mFocusedDisplayId = DEFAULT_DISPLAY;
470         mFocusedWindow = null;
471         mFocusedApp = null;
472         mTopResumedActivityRecord = null;
473         mResumedActivitiesInRootTasks.clear();
474         mResumedActivitiesInDisplays.clear();
475         mKeyguardControllerState = null;
476         mKeyguardServiceDelegateState = null;
477         mIsHomeRecentsComponent = null;
478         mPendingActivities.clear();
479         mDefaultPinnedStackBounds.setEmpty();
480         mPinnedStackMovementBounds.setEmpty();
481         mInputMethodWindowAppToken = null;
482         mDisplayFrozen = false;
483         mWindowFramesValid = false;
484     }
485 
getFocusedApp()486     public String getFocusedApp() {
487         return mFocusedApp;
488     }
489 
getFocusedWindow()490     public String getFocusedWindow() {
491         return mFocusedWindow;
492     }
493 
494     /** @return Whether the home activity is the recents component. */
isHomeRecentsComponent()495     boolean isHomeRecentsComponent() {
496         if (mIsHomeRecentsComponent == null) {
497             computeState();
498         }
499         return mIsHomeRecentsComponent;
500     }
501 
getDisplay(int displayId)502     DisplayContent getDisplay(int displayId) {
503         for (DisplayContent display : mDisplays) {
504             if (display.mId == displayId) {
505                 return display;
506             }
507         }
508         return null;
509     }
510 
511     @Nullable
getTaskDisplayArea(ComponentName activityName)512     DisplayArea getTaskDisplayArea(ComponentName activityName) {
513         final List<DisplayArea> result = new ArrayList<>();
514         for (DisplayContent display : mDisplays) {
515             final DisplayArea tda = display.getTaskDisplayArea(activityName);
516             if (tda != null) {
517                 result.add(tda);
518             }
519         }
520         assertWithMessage("There must be exactly one activity among all TaskDisplayAreas.")
521                 .that(result.size()).isAtMost(1);
522 
523         return result.stream().findFirst().orElse(null);
524     }
525 
getTaskDisplayAreaFeatureId(ComponentName activityName)526     public int getTaskDisplayAreaFeatureId(ComponentName activityName) {
527         final DisplayArea taskDisplayArea = getTaskDisplayArea(activityName);
528         if (taskDisplayArea != null) {
529             return taskDisplayArea.getFeatureId();
530         }
531 
532         return FEATURE_UNDEFINED;
533     }
534 
535     @Nullable
getDisplayArea(String windowName)536     DisplayArea getDisplayArea(String windowName) {
537         final List<DisplayArea> result = new ArrayList<>();
538         for (DisplayContent display : mDisplays) {
539             final DisplayArea da = display.getDisplayArea(windowName);
540             if (da != null) {
541                 result.add(da);
542             }
543         }
544         assertWithMessage("There must be exactly one window among all DisplayAreas.")
545                 .that(result.size()).isAtMost(1);
546 
547         return result.stream().findFirst().orElse(null);
548     }
549 
550     @Nullable
getImeContainer(int displayId)551     public DisplayArea getImeContainer(int displayId) {
552         final DisplayContent displayContent = getDisplay(displayId);
553         if (displayContent == null) {
554             return null;
555         }
556         return displayContent.getImeContainer();
557     }
558 
getFrontRootTaskId(int displayId)559     int getFrontRootTaskId(int displayId) {
560         return getDisplay(displayId).mRootTasks.get(0).mRootTaskId;
561     }
562 
getFrontRootTaskActivityType(int displayId)563     public int getFrontRootTaskActivityType(int displayId) {
564         return getDisplay(displayId).mRootTasks.get(0).getActivityType();
565     }
566 
getFrontRootTaskWindowingMode(int displayId)567     public int getFrontRootTaskWindowingMode(int displayId) {
568         return getDisplay(displayId).mRootTasks.get(0).getWindowingMode();
569     }
570 
getTopActivityName(int displayId)571     public String getTopActivityName(int displayId) {
572         if (!getDisplay(displayId).mRootTasks.isEmpty()) {
573             final Task topRootTask = getDisplay(displayId).mRootTasks.get(0);
574             final Task topTask = topRootTask.getTopTask();
575             if (!topTask.mActivities.isEmpty()) {
576                 return topTask.mActivities.get(0).name;
577             }
578         }
579         return null;
580     }
581 
getFocusedTaskId()582     int getFocusedTaskId() {
583         return mTopFocusedTaskId;
584     }
585 
getFocusedRootTaskActivityType()586     public int getFocusedRootTaskActivityType() {
587         final Task rootTask = getRootTask(mTopFocusedTaskId);
588         return rootTask != null ? rootTask.getActivityType() : ACTIVITY_TYPE_UNDEFINED;
589     }
590 
getFocusedRootTaskWindowingMode()591     public int getFocusedRootTaskWindowingMode() {
592         final Task rootTask = getRootTask(mTopFocusedTaskId);
593         return rootTask != null ? rootTask.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
594     }
595 
getFocusedActivity()596     public String getFocusedActivity() {
597         return mTopResumedActivityRecord;
598     }
599 
getResumedActivitiesCount()600     public int getResumedActivitiesCount() {
601         return mResumedActivitiesInRootTasks.size();
602     }
603 
getResumedActivitiesCountInPackage(String packageName)604     public int getResumedActivitiesCountInPackage(String packageName) {
605         final String componentPrefix = packageName + "/";
606         int count = 0;
607         for (int i = mDisplays.size() - 1; i >= 0; --i) {
608             final ArrayList<Task> rootTasks = mDisplays.get(i).getRootTasks();
609             for (int j = rootTasks.size() - 1; j >= 0; --j) {
610                 final String resumedActivity = rootTasks.get(j).mResumedActivity;
611                 if (resumedActivity != null && resumedActivity.startsWith(componentPrefix)) {
612                     count++;
613                 }
614             }
615         }
616         return count;
617     }
618 
getResumedActivityOnDisplay(int displayId)619     public String getResumedActivityOnDisplay(int displayId) {
620         return getDisplay(displayId).mResumedActivity;
621     }
622 
getKeyguardControllerState()623     public KeyguardControllerState getKeyguardControllerState() {
624         return mKeyguardControllerState;
625     }
626 
getKeyguardServiceDelegateState()627     public KeyguardServiceDelegateState getKeyguardServiceDelegateState() {
628         return mKeyguardServiceDelegateState;
629     }
630 
getBackNavigationState()631     public BackNavigationState getBackNavigationState() {
632         return mBackNavigationState;
633     }
634 
containsRootTasks(int windowingMode, int activityType)635     public boolean containsRootTasks(int windowingMode, int activityType) {
636         return countRootTasks(windowingMode, activityType) > 0;
637     }
638 
countRootTasks(int windowingMode, int activityType)639     public int countRootTasks(int windowingMode, int activityType) {
640         int count = 0;
641         for (Task rootTask : mRootTasks) {
642             if (activityType != ACTIVITY_TYPE_UNDEFINED
643                     && activityType != rootTask.getActivityType()) {
644                 continue;
645             }
646             if (windowingMode != WINDOWING_MODE_UNDEFINED
647                     && windowingMode != rootTask.getWindowingMode()) {
648                 continue;
649             }
650             ++count;
651         }
652         return count;
653     }
654 
getRootTask(int taskId)655     public Task getRootTask(int taskId) {
656         for (Task rootTask : mRootTasks) {
657             if (taskId == rootTask.mRootTaskId) {
658                 return rootTask;
659             }
660         }
661         return null;
662     }
663 
getRootTaskByActivityType(int activityType)664     public Task getRootTaskByActivityType(int activityType) {
665         for (Task rootTask : mRootTasks) {
666             if (activityType == rootTask.getActivityType()) {
667                 return rootTask;
668             }
669         }
670         return null;
671     }
672 
getStandardTaskCountByWindowingMode(int windowingMode)673     public int getStandardTaskCountByWindowingMode(int windowingMode) {
674         int count = 0;
675         for (Task rootTask : mRootTasks) {
676             if (rootTask.getActivityType() != ACTIVITY_TYPE_STANDARD) {
677                 continue;
678             }
679             if (rootTask.getWindowingMode() == windowingMode) {
680                 count += rootTask.mTasks.isEmpty() ? 1 : rootTask.mTasks.size();
681             }
682         }
683         return count;
684     }
685 
686     /** Gets the position of root task on its display with the given {@code activityType}. */
getRootTaskIndexByActivityType(int activityType)687     int getRootTaskIndexByActivityType(int activityType) {
688         for (DisplayContent display : mDisplays) {
689             for (int i = 0; i < display.mRootTasks.size(); i++) {
690                 if (activityType == display.mRootTasks.get(i).getActivityType()) {
691                     return i;
692                 }
693             }
694         }
695         return -1;
696     }
697 
698     /** Gets the root task on its display with the given {@code activityName}. */
699     @Nullable
getRootTaskByActivity(ComponentName activityName)700     Task getRootTaskByActivity(ComponentName activityName) {
701         for (DisplayContent display : mDisplays) {
702             for (int i = display.mRootTasks.size() - 1; i >= 0; --i) {
703                 final Task rootTask = display.mRootTasks.get(i);
704                 if (rootTask.containsActivity(activityName)) return rootTask;
705             }
706         }
707         return null;
708     }
709 
710     /** Get display id by activity on it. */
getDisplayByActivity(ComponentName activityComponent)711     public int getDisplayByActivity(ComponentName activityComponent) {
712         final Task task = getTaskByActivity(activityComponent);
713         if (task == null) {
714             return -1;
715         }
716         return getRootTask(task.mRootTaskId).mDisplayId;
717     }
718 
getDisplays()719     List<DisplayContent> getDisplays() {
720         return new ArrayList<>(mDisplays);
721     }
722 
getRootTasks()723     public List<Task> getRootTasks() {
724         return new ArrayList<>(mRootTasks);
725     }
726 
getRootTaskCount()727     public int getRootTaskCount() {
728         return mRootTasks.size();
729     }
730 
getDisplayCount()731     public int getDisplayCount() {
732         return mDisplays.size();
733     }
734 
containsActivity(ComponentName activityName)735     public boolean containsActivity(ComponentName activityName) {
736         for (Task rootTask : mRootTasks) {
737             if (rootTask.containsActivity(activityName)) return true;
738         }
739         return false;
740     }
741 
containsNoneOf(Iterable<ComponentName> activityNames)742     public boolean containsNoneOf(Iterable<ComponentName> activityNames) {
743         for (ComponentName activityName : activityNames) {
744             for (Task rootTask : mRootTasks) {
745                 if (rootTask.containsActivity(activityName)) return false;
746             }
747         }
748         return true;
749     }
750 
containsActivityInWindowingMode(ComponentName activityName, int windowingMode)751     public boolean containsActivityInWindowingMode(ComponentName activityName, int windowingMode) {
752         for (Task rootTask : mRootTasks) {
753             final Activity activity = rootTask.getActivity(activityName);
754             if (activity != null && activity.getWindowingMode() == windowingMode) {
755                 return true;
756             }
757         }
758         return false;
759     }
760 
isActivityVisible(ComponentName activityName)761     public boolean isActivityVisible(ComponentName activityName) {
762         for (Task rootTask : mRootTasks) {
763             final Activity activity = rootTask.getActivity(activityName);
764             if (activity != null) return activity.visible;
765         }
766         return false;
767     }
768 
isActivityTranslucent(ComponentName activityName)769     public boolean isActivityTranslucent(ComponentName activityName) {
770         for (Task rootTask : mRootTasks) {
771             final Activity activity = rootTask.getActivity(activityName);
772             if (activity != null) return activity.translucent;
773         }
774         return false;
775     }
776 
isBehindOpaqueActivities(ComponentName activityName)777     public boolean isBehindOpaqueActivities(ComponentName activityName) {
778         final String fullName = getActivityName(activityName);
779         for (Task rootTask : mRootTasks) {
780             final Activity activity =
781                     rootTask.getActivity((a) -> a.name.equals(fullName) || !a.translucent);
782             if (activity != null) {
783                 if (activity.name.equals(fullName)) {
784                     return false;
785                 }
786                 if (!activity.translucent) {
787                     return true;
788                 }
789             }
790         }
791 
792         return false;
793     }
794 
isTaskDisplayAreaIgnoringOrientationRequest(ComponentName activityName)795     public boolean isTaskDisplayAreaIgnoringOrientationRequest(ComponentName activityName) {
796         return getTaskDisplayArea(activityName).isIgnoringOrientationRequest();
797     }
798 
containsStartedActivities()799     public boolean containsStartedActivities() {
800         for (Task rootTask : mRootTasks) {
801             final Activity activity = rootTask.getActivity(
802                     (a) -> !a.state.equals(STATE_STOPPED) && !a.state.equals(STATE_DESTROYED));
803             if (activity != null) return true;
804         }
805         return false;
806     }
807 
hasActivityState(ComponentName activityName, String activityState)808     boolean hasActivityState(ComponentName activityName, String activityState) {
809         for (Task rootTask : mRootTasks) {
810             final Activity activity = rootTask.getActivity(activityName);
811             if (activity != null) return activity.state.equals(activityState);
812         }
813         return false;
814     }
815 
getActivityProcId(ComponentName activityName)816     int getActivityProcId(ComponentName activityName) {
817         for (Task rootTask : mRootTasks) {
818             final Activity activity = rootTask.getActivity(activityName);
819             if (activity != null) return activity.procId;
820         }
821         return -1;
822     }
823 
isRecentsActivityVisible()824     boolean isRecentsActivityVisible() {
825         final Activity recentsActivity = getRecentsActivity();
826         return recentsActivity != null && recentsActivity.visible;
827     }
828 
getHomeActivityName()829     ComponentName getHomeActivityName() {
830         Activity activity = getHomeActivity();
831         if (activity == null) {
832             return null;
833         }
834         return ComponentName.unflattenFromString(activity.name);
835     }
836 
getDreamTask()837     Task getDreamTask() {
838         final Task dreamRootTask = getRootTaskByActivityType(ACTIVITY_TYPE_DREAM);
839         if (dreamRootTask != null) {
840             return dreamRootTask.getTopTask();
841         }
842         return null;
843     }
844 
getHomeTask()845     Task getHomeTask() {
846         final Task homeRootTask = getRootTaskByActivityType(ACTIVITY_TYPE_HOME);
847         if (homeRootTask != null) {
848             return homeRootTask.getTopTask();
849         }
850         return null;
851     }
852 
getRecentsTask()853     private Task getRecentsTask() {
854         final Task recentsRootTask = getRootTaskByActivityType(ACTIVITY_TYPE_RECENTS);
855         if (recentsRootTask != null) {
856             return recentsRootTask.getTopTask();
857         }
858         return null;
859     }
860 
getHomeActivity()861     private Activity getHomeActivity() {
862         final Task homeTask = getHomeTask();
863         return homeTask != null ? homeTask.mActivities.get(homeTask.mActivities.size() - 1) : null;
864     }
865 
getRecentsActivity()866     private Activity getRecentsActivity() {
867         final Task recentsTask = getRecentsTask();
868         return recentsTask != null ? recentsTask.mActivities.get(recentsTask.mActivities.size() - 1)
869                 : null;
870     }
871 
getRootTaskIdByActivity(ComponentName activityName)872     public int getRootTaskIdByActivity(ComponentName activityName) {
873         final Task rootTask = getRootTaskByActivity(activityName);
874         return  (rootTask == null) ? INVALID_TASK_ID : rootTask.mTaskId;
875     }
876 
getTaskByActivity(ComponentName activityName)877     public Task getTaskByActivity(ComponentName activityName) {
878         return getTaskByActivity(
879                 activityName, WINDOWING_MODE_UNDEFINED, new int[]{ INVALID_TASK_ID });
880     }
881 
getTaskByActivity(ComponentName activityName, int[] excludeTaskIds)882     public Task getTaskByActivity(ComponentName activityName, int[] excludeTaskIds) {
883         return getTaskByActivity(activityName, WINDOWING_MODE_UNDEFINED, excludeTaskIds);
884     }
885 
getTaskByActivity(ComponentName activityName, int windowingMode, int[] excludeTaskIds)886     private Task getTaskByActivity(ComponentName activityName, int windowingMode,
887             int[] excludeTaskIds) {
888         Activity activity = getActivity(activityName, windowingMode, excludeTaskIds);
889         return activity == null ? null : activity.getTask();
890     }
891 
892     @Nullable
getTaskFragmentByActivity(ComponentName activityName)893     public TaskFragment getTaskFragmentByActivity(ComponentName activityName) {
894         return getActivity(activityName).getTaskFragment();
895     }
896 
getActivity(ComponentName activityName)897     public Activity getActivity(ComponentName activityName) {
898         return getActivity(activityName, WINDOWING_MODE_UNDEFINED, new int[]{ INVALID_TASK_ID });
899     }
900 
getActivity(ComponentName activityName, int windowingMode, int[] excludeTaskIds)901     private Activity getActivity(ComponentName activityName, int windowingMode,
902             int[] excludeTaskIds) {
903         for (Task rootTask : mRootTasks) {
904             if (windowingMode == WINDOWING_MODE_UNDEFINED
905                     || windowingMode == rootTask.getWindowingMode()) {
906                 Activity activity = rootTask.getActivity(activityName, excludeTaskIds);
907                 if (activity != null) return activity;
908             }
909         }
910         return null;
911     }
912 
913     /**
914      * Get the number of activities in the task, with the option to count only activities with
915      * specific name.
916      * @param taskId Id of the task where we're looking for the number of activities.
917      * @param activityName Optional name of the activity we're interested in.
918      * @return Number of all activities in the task if activityName is {@code null}, otherwise will
919      *         report number of activities that have specified name.
920      */
getActivityCountInTask(int taskId, @Nullable ComponentName activityName)921     public int getActivityCountInTask(int taskId, @Nullable ComponentName activityName) {
922         // If activityName is null, count all activities in the task.
923         // Otherwise count activities that have specified name.
924         for (Task rootTask : mRootTasks) {
925             final Task task = rootTask.getTask(taskId);
926             if (task == null) continue;
927 
928             if (activityName == null) {
929                 return task.mActivities.size();
930             }
931             final String fullName = getActivityName(activityName);
932             int count = 0;
933             for (Activity activity : task.mActivities) {
934                 if (activity.name.equals(fullName)) {
935                     count++;
936                 }
937             }
938             return count;
939         }
940         return 0;
941     }
942 
getRootTasksCount()943     public int getRootTasksCount() {
944         return mRootTasks.size();
945     }
946 
getRootTasksCount(int displayId)947     public int getRootTasksCount(int displayId) {
948         return getRootTasksCount(t -> t.mDisplayId == displayId);
949     }
950 
951     /**
952      * Count root tasks filtered by the predicate passed as argument.
953      */
getRootTasksCount(Predicate<? super Task> predicate)954     public int getRootTasksCount(Predicate<? super Task> predicate) {
955         return (int) mRootTasks.stream().filter(predicate).count();
956     }
957 
pendingActivityContain(ComponentName activityName)958     boolean pendingActivityContain(ComponentName activityName) {
959         return mPendingActivities.contains(getActivityName(activityName));
960     }
961 
962     // Get the logical display size of the default display.
getLogicalDisplaySize()963     public static Point getLogicalDisplaySize() {
964         WindowManagerState mWmState = new WindowManagerState();
965         mWmState.computeState();
966         Rect size = mWmState.getDisplay(DEFAULT_DISPLAY).getDisplayRect();
967         return new Point(size.width(), size.height());
968     }
969 
getDefaultDisplayLastTransition()970     String getDefaultDisplayLastTransition() {
971         return getDisplay(DEFAULT_DISPLAY).getLastTransition();
972     }
973 
getDefaultDisplayAppTransitionState()974     String getDefaultDisplayAppTransitionState() {
975         return getDisplay(DEFAULT_DISPLAY).getAppTransitionState();
976     }
977 
getMatchingVisibleWindowState(final String windowName)978     public List<WindowState> getMatchingVisibleWindowState(final String windowName) {
979         return getMatchingWindows(ws -> ws.isSurfaceShown() && windowName.equals(ws.getName()))
980                 .collect(Collectors.toList());
981     }
982 
getMatchingWindows(Predicate<WindowState> condition)983     public Stream<WindowState> getMatchingWindows(Predicate<WindowState> condition) {
984         return mWindowStates.stream().filter(condition);
985     }
986 
987     @Nullable
getWindowByPackageName(String packageName, int windowType)988     public WindowState getWindowByPackageName(String packageName, int windowType) {
989         final List<WindowState> windowList = getWindowsByPackageName(packageName, windowType);
990         return windowList.isEmpty() ? null : windowList.get(0);
991     }
992 
getWindowsByPackageName(String packageName, int... restrictToTypes)993     public List<WindowState> getWindowsByPackageName(String packageName, int... restrictToTypes) {
994         return getMatchingWindows(ws ->
995                 (ws.getName().equals(packageName) || ws.getName().startsWith(packageName + "/"))
996                         && Arrays.stream(restrictToTypes).anyMatch(type -> type == ws.getType()))
997                 .collect(Collectors.toList());
998     }
999 
allActivitiesResumed()1000     public boolean allActivitiesResumed() {
1001         for (Task rootTask : mRootTasks) {
1002             final Activity nonResumedActivity =
1003                     rootTask.getActivity((a) -> !a.state.equals(STATE_RESUMED));
1004             if (nonResumedActivity != null) return false;
1005         }
1006         return true;
1007     }
1008 
hasNotificationShade()1009     public boolean hasNotificationShade() {
1010         computeState();
1011         return !getMatchingWindowType(TYPE_NOTIFICATION_SHADE).isEmpty();
1012     }
1013 
getWindows()1014     List<WindowState> getWindows() {
1015         return new ArrayList<>(mWindowStates);
1016     }
1017 
getMatchingWindowType(int type)1018     public List<WindowState> getMatchingWindowType(int type) {
1019         return getMatchingWindows(ws -> type == ws.mType).collect(Collectors.toList());
1020     }
1021 
getAllNavigationBarStates()1022     List<WindowState> getAllNavigationBarStates() {
1023         return getMatchingWindows(WindowManagerState::isValidNavBarType)
1024                 .collect(Collectors.toList());
1025     }
1026 
1027     @Nullable
getAndAssertNavBarWindowsOnDisplay(int displayId, int expectedNavBarCount)1028     List<WindowState> getAndAssertNavBarWindowsOnDisplay(int displayId, int expectedNavBarCount) {
1029         List<WindowState> navWindows = getMatchingWindows(ws -> isValidNavBarType(ws)
1030                 && ws.getDisplayId() == displayId)
1031                 .filter(Objects::nonNull)
1032                 .collect(Collectors.toList());
1033         // We may need some time to wait for nav bar showing.
1034         // It's Ok to get less that expected nav bars here.
1035         assertTrue("There should be at most expectedNavBarCount navigation bar on a display",
1036                 navWindows.size() <= expectedNavBarCount);
1037 
1038         return navWindows.size() == expectedNavBarCount ? navWindows : null;
1039     }
1040 
getWindowStateForAppToken(String appToken)1041     WindowState getWindowStateForAppToken(String appToken) {
1042         return getMatchingWindows(ws -> ws.getToken().equals(appToken))
1043                 .findFirst()
1044                 .orElse(null);
1045     }
1046 
getFrontWindow()1047     String getFrontWindow() {
1048         if (mWindowStates == null || mWindowStates.isEmpty()) {
1049             return null;
1050         }
1051         return mWindowStates.get(0).getName();
1052     }
1053 
1054     /** Check if there exists a window record with matching windowName. */
containsWindow(String windowName)1055     public boolean containsWindow(String windowName) {
1056         for (WindowState window : mWindowStates) {
1057             if (window.getName().equals(windowName)) {
1058                 return true;
1059             }
1060         }
1061         return false;
1062     }
1063 
1064     /** Check if at least one window which matches the specified name has shown it's surface. */
isWindowSurfaceShown(String windowName)1065     public boolean isWindowSurfaceShown(String windowName) {
1066         for (WindowState window : mWindowStates) {
1067             if (window.getName().equals(windowName)) {
1068                 if (window.isSurfaceShown()) {
1069                     return true;
1070                 }
1071             }
1072         }
1073         return false;
1074     }
1075 
1076     /** Check if at least one window which matches provided window name is visible. */
isWindowVisible(String windowName)1077     public boolean isWindowVisible(String windowName) {
1078         for (WindowState window : mWindowStates) {
1079             if (window.getName().equals(windowName)) {
1080                 if (window.isVisible()) {
1081                     return true;
1082                 }
1083             }
1084         }
1085         return false;
1086     }
1087 
allWindowSurfacesShown(String windowName)1088     public boolean allWindowSurfacesShown(String windowName) {
1089         boolean allShown = false;
1090         for (WindowState window : mWindowStates) {
1091             if (window.getName().equals(windowName)) {
1092                 if (!window.isSurfaceShown()) {
1093                     log("[VISIBLE] not visible" + windowName);
1094                     return false;
1095                 }
1096                 log("[VISIBLE] visible" + windowName);
1097                 allShown = true;
1098             }
1099         }
1100         return allShown;
1101     }
1102 
1103     /** Checks whether the display contains the given activity. */
hasActivityInDisplay(int displayId, ComponentName activityName)1104     boolean hasActivityInDisplay(int displayId, ComponentName activityName) {
1105         for (Task rootTask : getDisplay(displayId).getRootTasks()) {
1106             if (rootTask.containsActivity(activityName)) {
1107                 return true;
1108             }
1109         }
1110         return false;
1111     }
1112 
findFirstWindowWithType(int type)1113     WindowState findFirstWindowWithType(int type) {
1114         for (WindowState window : mWindowStates) {
1115             if (window.getType() == type) {
1116                 return window;
1117             }
1118         }
1119         return null;
1120     }
1121 
getZOrder(WindowState w)1122     public int getZOrder(WindowState w) {
1123         return mWindowStates.size() - mWindowStates.indexOf(w);
1124     }
1125 
getStandardRootTaskByWindowingMode(int windowingMode)1126     Task getStandardRootTaskByWindowingMode(int windowingMode) {
1127         for (Task task : mRootTasks) {
1128             if (task.getActivityType() != ACTIVITY_TYPE_STANDARD) {
1129                 continue;
1130             }
1131             if (task.getWindowingMode() == windowingMode) {
1132                 return task;
1133             }
1134         }
1135         return null;
1136     }
1137 
getInputMethodWindowState()1138     WindowManagerState.WindowState getInputMethodWindowState() {
1139         return getWindowStateForAppToken(mInputMethodWindowAppToken);
1140     }
1141 
isDisplayFrozen()1142     public boolean isDisplayFrozen() {
1143         return mDisplayFrozen;
1144     }
1145 
getRotation()1146     public int getRotation() {
1147         return getDisplay(DEFAULT_DISPLAY).mRotation;
1148     }
1149 
getLastOrientation()1150     public int getLastOrientation() {
1151         return getDisplay(DEFAULT_DISPLAY).mLastOrientation;
1152     }
1153 
getFocusedDisplayId()1154     public int getFocusedDisplayId() {
1155         return mFocusedDisplayId;
1156     }
1157 
isFixedToUserRotation()1158     public boolean isFixedToUserRotation() {
1159         return getDisplay(DEFAULT_DISPLAY).mIsFixedToUserRotation;
1160     }
1161 
1162     public static class DisplayContent extends DisplayArea {
1163         public int mId;
1164         ArrayList<Task> mRootTasks = new ArrayList<>();
1165         int mFocusedRootTaskId;
1166         String mResumedActivity;
1167         boolean mSingleTaskInstance;
1168         Rect mDefaultPinnedStackBounds = null;
1169         Rect mPinnedStackMovementBounds = null;
1170         int mMinSizeOfResizeableTaskDp;
1171 
1172         private Rect mDisplayRect = new Rect();
1173         private Rect mAppRect = new Rect();
1174         private int mDpi;
1175         private int mFlags;
1176         private String mName;
1177         private int mSurfaceSize;
1178         private String mFocusedApp;
1179         private String mLastTransition;
1180         private String mAppTransitionState;
1181         private int mRotation;
1182         private boolean mFrozenToUserRotation;
1183         private int mUserRotation;
1184         private int mFixedToUserRotationMode;
1185         private int mLastOrientation;
1186         private boolean mIsFixedToUserRotation;
1187         private List<Rect> mKeepClearRects;
1188 
DisplayContent(DisplayContentProto proto)1189         DisplayContent(DisplayContentProto proto) {
1190             super(proto.rootDisplayArea);
1191             mId = proto.id;
1192             mFocusedRootTaskId = proto.focusedRootTaskId;
1193             mSingleTaskInstance = proto.singleTaskInstance;
1194             if (proto.resumedActivity != null) {
1195                 mResumedActivity = proto.resumedActivity.title;
1196             }
1197             addRootTasks();
1198 
1199             mDpi = proto.dpi;
1200             DisplayInfoProto infoProto = proto.displayInfo;
1201             if (infoProto != null) {
1202                 mDisplayRect.set(0, 0, infoProto.logicalWidth, infoProto.logicalHeight);
1203                 mAppRect.set(0, 0, infoProto.appWidth, infoProto.appHeight);
1204                 mName = infoProto.name;
1205                 mFlags = infoProto.flags;
1206             }
1207             final DisplayFramesProto displayFramesProto = proto.displayFrames;
1208             mSurfaceSize = proto.surfaceSize;
1209             mFocusedApp = proto.focusedApp;
1210             mMinSizeOfResizeableTaskDp = proto.minSizeOfResizeableTaskDp;
1211 
1212             final AppTransitionProto appTransitionProto = proto.appTransition;
1213             int appState = 0;
1214             int lastTransition = 0;
1215             if (appTransitionProto != null) {
1216                 appState = appTransitionProto.appTransitionState;
1217                 lastTransition = appTransitionProto.lastUsedAppTransition;
1218             }
1219             mAppTransitionState = appStateToString(appState);
1220             mLastTransition = appTransitionToString(lastTransition);
1221 
1222             PinnedTaskControllerProto pinnedTaskProto = proto.pinnedTaskController;
1223             if (pinnedTaskProto != null) {
1224                 mDefaultPinnedStackBounds = extract(pinnedTaskProto.defaultBounds);
1225                 mPinnedStackMovementBounds = extract(pinnedTaskProto.movementBounds);
1226             }
1227 
1228             final DisplayRotationProto rotationProto = proto.displayRotation;
1229             if (rotationProto != null) {
1230                 mRotation = rotationProto.rotation;
1231                 mFrozenToUserRotation = rotationProto.frozenToUserRotation;
1232                 mUserRotation = rotationProto.userRotation;
1233                 mFixedToUserRotationMode = rotationProto.fixedToUserRotationMode;
1234                 mLastOrientation = rotationProto.lastOrientation;
1235                 mIsFixedToUserRotation = rotationProto.isFixedToUserRotation;
1236             }
1237             mKeepClearRects = new ArrayList();
1238             for (RectProto r : proto.keepClearAreas) {
1239                 mKeepClearRects.add(new Rect(r.left, r.top, r.right, r.bottom));
1240             }
1241         }
1242 
getName()1243         public String getName() {
1244             return mName;
1245         }
1246 
addRootTasks()1247         private void addRootTasks() {
1248             // TODO(b/149338177): figure out how CTS tests deal with organizer. For now,
1249             //                    don't treat them as regular root tasks
1250             collectDescendantsOfTypeIf(Task.class, t -> t.isRootTask(), this,
1251                     mRootTasks);
1252 
1253             ArrayList<Task> nonOrganizedRootTasks = new ArrayList<>();
1254             for (int i = 0; i < mRootTasks.size(); i++) {
1255                 final Task task = mRootTasks.get(i);
1256                 if (task.mCreatedByOrganizer) {
1257                     // Get all tasks inside the root-task created by an organizer
1258                     List<Task> nonOrganizedDescendants = new ArrayList<>();
1259                     collectDescendantsOfTypeIf(Task.class, t -> !t.mCreatedByOrganizer, task,
1260                             nonOrganizedDescendants);
1261                     nonOrganizedRootTasks.addAll(nonOrganizedDescendants);
1262                 } else {
1263                     nonOrganizedRootTasks.add(task);
1264                 }
1265             }
1266 
1267             mRootTasks.clear();
1268             mRootTasks.addAll(nonOrganizedRootTasks);
1269         }
1270 
containsActivity(ComponentName activityName)1271         boolean containsActivity(ComponentName activityName) {
1272             for (Task task : mRootTasks) {
1273                 if (task.containsActivity(activityName)) return true;
1274             }
1275             return false;
1276         }
1277 
getAllTaskDisplayAreas()1278         List<DisplayArea> getAllTaskDisplayAreas() {
1279             final List<DisplayArea> taskDisplayAreas = new ArrayList<>();
1280             collectDescendantsOfTypeIf(DisplayArea.class, DisplayArea::isTaskDisplayArea, this,
1281                     taskDisplayAreas);
1282             return taskDisplayAreas;
1283         }
1284 
1285         @Nullable
getTaskDisplayArea(ComponentName activityName)1286         DisplayArea getTaskDisplayArea(ComponentName activityName) {
1287             final List<DisplayArea> taskDisplayAreas = getAllTaskDisplayAreas();
1288             List<DisplayArea> result = taskDisplayAreas.stream().filter(
1289                     tda -> tda.containsActivity(activityName))
1290                     .collect(Collectors.toList());
1291 
1292             assertWithMessage("There must be exactly one activity among all TaskDisplayAreas.")
1293                     .that(result.size()).isAtMost(1);
1294 
1295             return result.stream().findFirst().orElse(null);
1296         }
1297 
getAllChildDisplayAreas()1298         List<DisplayArea> getAllChildDisplayAreas() {
1299             final List<DisplayArea> displayAreas = new ArrayList<>();
1300             collectDescendantsOfType(DisplayArea.class,this, displayAreas);
1301             return displayAreas;
1302         }
1303 
1304         @Nullable
getDisplayArea(String windowName)1305         DisplayArea getDisplayArea(String windowName) {
1306             List<DisplayArea> displayAreas = new ArrayList<>();
1307             final Predicate<DisplayArea> p = da -> {
1308                 final boolean containsChildWindowToken = !da.mChildren.isEmpty()
1309                         && da.mChildren.get(0) instanceof WindowToken;
1310                 return !da.isTaskDisplayArea() && containsChildWindowToken;
1311             };
1312             collectDescendantsOfTypeIf(DisplayArea.class, p, this, displayAreas);
1313             List<DisplayArea> result = displayAreas.stream().filter(
1314                     da -> da.containsWindow(windowName))
1315                     .collect(Collectors.toList());
1316 
1317             assertWithMessage("There must be exactly one window among all DisplayAreas.")
1318                     .that(result.size()).isAtMost(1);
1319 
1320             return result.stream().findFirst().orElse(null);
1321         }
1322 
1323         @NonNull
getImeContainer()1324         DisplayArea getImeContainer() {
1325             final List<DisplayArea> imeContainers = new ArrayList<>();
1326             final Predicate<DisplayArea> p = da -> da.getFeatureId() == FEATURE_IME;
1327             collectDescendantsOfTypeIf(DisplayArea.class, p, this, imeContainers);
1328 
1329             assertWithMessage("There must be exactly one ImeContainer per DisplayContent.")
1330                     .that(imeContainers.size()).isEqualTo(1);
1331 
1332             return imeContainers.get(0);
1333         }
1334 
getRootTasks()1335         ArrayList<Task> getRootTasks() {
1336             return mRootTasks;
1337         }
1338 
getDpi()1339         int getDpi() {
1340             return mDpi;
1341         }
1342 
getDisplayRect()1343         Rect getDisplayRect() {
1344             return mDisplayRect;
1345         }
1346 
getAppRect()1347         public Rect getAppRect() {
1348             return mAppRect;
1349         }
1350 
getFlags()1351         int getFlags() {
1352             return mFlags;
1353         }
1354 
getSurfaceSize()1355         int getSurfaceSize() {
1356             return mSurfaceSize;
1357         }
1358 
getFocusedApp()1359         String getFocusedApp() {
1360             return mFocusedApp;
1361         }
1362 
getLastTransition()1363         String getLastTransition() { return mLastTransition; }
1364 
getAppTransitionState()1365         String getAppTransitionState() { return mAppTransitionState; }
1366 
getKeepClearRects()1367         List<Rect> getKeepClearRects() { return mKeepClearRects; }
1368 
1369         @Override
toString()1370         public String toString() {
1371             return "Display #" + mId + ": name=" + mName + " mDisplayRect=" + mDisplayRect
1372                     + " mAppRect=" + mAppRect + " mFlags=" + mFlags;
1373         }
1374 
1375         @Override
equals(Object o)1376         public boolean equals(Object o) {
1377             if (o == this) {
1378                 return true;
1379             }
1380             if (o == null) {
1381                 return false;
1382             }
1383             if (!(o instanceof DisplayContent)) {
1384                 return false;
1385             }
1386 
1387             DisplayContent dc = (DisplayContent) o;
1388 
1389             return (dc.mDisplayRect == null ? mDisplayRect == null
1390                     : dc.mDisplayRect.equals(mDisplayRect))
1391                 && (dc.mAppRect == null ? mAppRect == null : dc.mAppRect.equals(mAppRect))
1392                 && dc.mDpi == mDpi
1393                 && dc.mFlags == mFlags
1394                 && (dc.mName == null ? mName == null : dc.mName.equals(mName))
1395                 && dc.mSurfaceSize == mSurfaceSize
1396                 && (dc.mAppTransitionState == null ? mAppTransitionState == null
1397                     : dc.mAppTransitionState.equals(mAppTransitionState))
1398                 && dc.mRotation == mRotation
1399                 && dc.mFrozenToUserRotation == mFrozenToUserRotation
1400                 && dc.mUserRotation == mUserRotation
1401                 && dc.mFixedToUserRotationMode == mFixedToUserRotationMode
1402                 && dc.mLastOrientation == mLastOrientation
1403                 && dc.mIsFixedToUserRotation == mIsFixedToUserRotation;
1404         }
1405 
1406         @Override
hashCode()1407         public int hashCode() {
1408             int result = 0;
1409             if (mDisplayRect != null) {
1410                 result = 31 * result + mDisplayRect.hashCode();
1411             }
1412             if (mAppRect != null) {
1413                 result = 31 * result + mAppRect.hashCode();
1414             }
1415             result = 31 * result + mDpi;
1416             result = 31 * result + mFlags;
1417             if (mName != null) {
1418                 result = 31 * result + mName.hashCode();
1419             }
1420             result = 31 * result + mSurfaceSize;
1421             if (mAppTransitionState != null) {
1422                 result = 31 * result + mAppTransitionState.hashCode();
1423             }
1424             result = 31 * result + mRotation;
1425             result = 31 * result + Boolean.hashCode(mFrozenToUserRotation);
1426             result = 31 * result + mUserRotation;
1427             result = 31 * result + mFixedToUserRotationMode;
1428             result = 31 * result + mLastOrientation;
1429             result = 31 * result + Boolean.hashCode(mIsFixedToUserRotation);
1430             return result;
1431         }
1432     }
1433 
1434     public static class Task extends ActivityContainer {
1435         // TODO(b/292187837): Use the one in ActivityTaskManager instead.
1436         public static final int INVALID_TASK_ID = -1;
1437         int mTaskId;
1438         int mRootTaskId;
1439         public int mDisplayId;
1440         Rect mLastNonFullscreenBounds;
1441         String mRealActivity;
1442         String mOrigActivity;
1443         ArrayList<Task> mTasks = new ArrayList<>();
1444         /** Contains TaskFragment but not Task children */
1445         ArrayList<TaskFragment> mTaskFragments = new ArrayList<>();
1446         ArrayList<Activity> mActivities = new ArrayList<>();
1447         int mTaskType;
1448         private int mResizeMode;
1449         String mResumedActivity;
1450         boolean mAnimatingBounds;
1451         private int mSurfaceWidth;
1452         private int mSurfaceHeight;
1453         boolean mCreatedByOrganizer;
1454         String mAffinity;
1455         boolean mHasChildPipActivity;
1456         WindowContainer mParent;
1457 
Task(TaskProto proto, WindowContainer parent)1458         Task(TaskProto proto, WindowContainer parent) {
1459             super(proto.taskFragment.windowContainer);
1460             mTaskId = proto.id;
1461             mRootTaskId = proto.rootTaskId;
1462             mParent = parent;
1463             mDisplayId = proto.taskFragment.displayId;
1464             mLastNonFullscreenBounds = extract(proto.lastNonFullscreenBounds);
1465             mRealActivity = proto.realActivity;
1466             mOrigActivity = proto.origActivity;
1467             mTaskType = proto.taskFragment.activityType;
1468             mResizeMode = proto.resizeMode;
1469             mFullscreen = proto.fillsParent;
1470             mBounds = extract(proto.bounds);
1471             mMinWidth = proto.taskFragment.minWidth;
1472             mMinHeight = proto.taskFragment.minHeight;
1473             mAnimatingBounds = proto.animatingBounds;
1474             mSurfaceWidth = proto.surfaceWidth;
1475             mSurfaceHeight = proto.surfaceHeight;
1476             mCreatedByOrganizer = proto.createdByOrganizer;
1477             mAffinity = proto.affinity;
1478             mHasChildPipActivity = proto.hasChildPipActivity;
1479 
1480             if (proto.resumedActivity != null) {
1481                 mResumedActivity = proto.resumedActivity.title;
1482             }
1483 
1484             collectChildrenOfType(Task.class, this, mTasks);
1485             collectChildrenOfType(TaskFragment.class, this, mTaskFragments);
1486             collectChildrenOfType(Activity.class, this, mActivities);
1487         }
1488 
isEmpty()1489         boolean isEmpty() {
1490             return mTasks.isEmpty() && mTaskFragments.isEmpty() && mActivities.isEmpty();
1491         }
1492 
1493         /** Gets the pure parent TaskFragment if exist. */
getParentTaskFragment()1494         public TaskFragment getParentTaskFragment() {
1495             if (mParent instanceof TaskFragment) {
1496                 return (TaskFragment) mParent;
1497             }
1498             if (mParent instanceof Task) {
1499                 return ((Task) mParent).getParentTaskFragment();
1500             }
1501             // If the parent is a TaskDisplayArea, it means this Task doesn't have TaskFragment
1502             // parent.
1503             return null;
1504         }
1505 
getResizeMode()1506         public int getResizeMode() {
1507             return mResizeMode;
1508         }
1509 
getTaskId()1510         public int getTaskId() {
1511             return mTaskId;
1512         }
isRootTask()1513         boolean isRootTask() {
1514             return mTaskId == mRootTaskId;
1515         }
1516 
isLeafTask()1517         boolean isLeafTask() {
1518             return mTasks.size() == 0;
1519         }
1520 
getRootTaskId()1521         public int getRootTaskId() {
1522             return mRootTaskId;
1523         }
1524 
getSurfaceWidth()1525         int getSurfaceWidth() {
1526             return mSurfaceWidth;
1527         }
1528 
getSurfaceHeight()1529         int getSurfaceHeight() {
1530             return mSurfaceHeight;
1531         }
1532 
getAffinity()1533         public String getAffinity() { return mAffinity; }
1534 
getActivities()1535         public ArrayList<Activity> getActivities() {
1536             return mActivities;
1537         }
1538 
1539         /** @return the top task in the root task. */
getTopTask()1540         Task getTopTask() {
1541             // NOTE: Unlike the WindowManager internals, we dump the state from top to bottom,
1542             //       so the indices are inverted
1543             return getTask((t) -> true);
1544         }
1545 
getResumedActivity()1546         public String getResumedActivity() {
1547             return mResumedActivity;
1548         }
1549 
getTasks()1550         public List<Task> getTasks() {
1551             return new ArrayList<>(mTasks);
1552         }
1553 
1554         /** Returns non-Task leaf {@link TaskFragment} list. */
getTaskFragments()1555         public List<TaskFragment> getTaskFragments() {
1556             return new ArrayList<>(mTaskFragments);
1557         }
1558 
getTask(Predicate<Task> predicate)1559         Task getTask(Predicate<Task> predicate) {
1560             for (Task task : mTasks) {
1561                 if (predicate.test(task)) return task;
1562             }
1563             return predicate.test(this) ? this : null;
1564         }
1565 
getTask(int taskId)1566         Task getTask(int taskId) {
1567             return getTask((t) -> t.mTaskId == taskId);
1568         }
1569 
forAllTasks(Consumer<Task> consumer)1570         void forAllTasks(Consumer<Task> consumer) {
1571             for (Task task : mTasks) {
1572                 consumer.accept(task);
1573             }
1574             consumer.accept(this);
1575         }
1576 
getActivity(Predicate<Activity> predicate)1577         Activity getActivity(Predicate<Activity> predicate) {
1578             for (Activity activity : mActivities) {
1579                 if (predicate.test(activity)) return activity;
1580             }
1581             for (TaskFragment taskFragment : mTaskFragments) {
1582                 final Activity activity = taskFragment.getActivity(predicate);
1583                 if (activity != null) return activity;
1584             }
1585             for (Task task : mTasks) {
1586                 final Activity activity = task.getActivity(predicate);
1587                 if (activity != null) return activity;
1588             }
1589             return null;
1590         }
1591 
getActivity(ComponentName activityName)1592         public Activity getActivity(ComponentName activityName) {
1593             final String fullName = getActivityName(activityName);
1594             return getActivity((activity) -> activity.name.equals(fullName));
1595         }
1596 
getActivity(ComponentName activityName, int[] excludeTaskIds)1597         public Activity getActivity(ComponentName activityName, int[] excludeTaskIds) {
1598             final String fullName = getActivityName(activityName);
1599             return getActivity((activity) -> {
1600                 if (!activity.name.equals(fullName)) {
1601                     return false;
1602                 }
1603                 for (int excludeTaskId : excludeTaskIds) {
1604                     if (activity.getTask().mTaskId == excludeTaskId) {
1605                         return false;
1606                     }
1607                 }
1608                 return true;
1609             });
1610         }
1611 
containsActivity(ComponentName activityName)1612         boolean containsActivity(ComponentName activityName) {
1613             return getActivity(activityName) != null;
1614         }
1615 
getActivityCount()1616         public int getActivityCount() {
1617             int count = mActivities.size();
1618             for (TaskFragment taskFragment : mTaskFragments) {
1619                 count += taskFragment.getActivityCount();
1620             }
1621             for (Task task : mTasks) {
1622                 count += task.getActivityCount();
1623             }
1624             return count;
1625         }
1626 
1627         @Override
getActivityType()1628         int getActivityType() {
1629             return mTaskType;
1630         }
1631 
1632         @Override
toString()1633         public String toString() {
1634             return "Task[id=" + mTaskId + ", display=" + mDisplayId
1635                     + ", mOrigActivity=" + mOrigActivity + ", realActivity=" + mRealActivity
1636                     + ", activities=" + mActivities + "]";
1637         }
1638     }
1639 
1640     public static class TaskFragment extends ActivityContainer {
1641         public int mDisplayId;
1642         Task mParentTask;
1643         ArrayList<Activity> mActivities = new ArrayList<>();
1644         int mTaskFragmentType;
1645 
1646         TaskFragment(TaskFragmentProto proto, WindowContainer parent) {
1647             super(proto.windowContainer);
1648             mParentTask = (Task) parent;
1649             mDisplayId = proto.displayId;
1650             mTaskFragmentType = proto.activityType;
1651             mMinWidth = proto.minWidth;
1652             mMinHeight = proto.minHeight;
1653 
1654             collectChildrenOfType(Activity.class, this, mActivities);
1655         }
1656 
1657         public List<Activity> getActivities() {
1658             return mActivities;
1659         }
1660 
1661         Activity getActivity(Predicate<Activity> predicate) {
1662             for (Activity activity : mActivities) {
1663                 if (predicate.test(activity)) {
1664                     return activity;
1665                 }
1666             }
1667             return null;
1668         }
1669 
1670         public int getActivityCount() {
1671             return mActivities.size();
1672         }
1673 
1674         @Override
1675         int getActivityType() {
1676             return mTaskFragmentType;
1677         }
1678     }
1679 
1680     public static class Activity extends ActivityContainer {
1681 
1682         String name;
1683         String state;
1684         boolean visible;
1685         boolean frontOfTask;
1686         boolean inSizeCompatMode;
1687         float minAspectRatio;
1688         boolean providesMaxBounds;
1689         int procId = -1;
1690         boolean isAnimating;
1691         public boolean translucent;
1692         private WindowContainer mParent;
1693         private boolean mEnableRecentsScreenshot;
1694         private int mLastDropInputMode;
1695         private boolean mShouldSendCompatFakeFocus;
1696         private int mOverrideOrientation;
1697         private boolean mShouldForceRotateForCameraCompat;
1698         private boolean mShouldRefreshActivityForCameraCompat;
1699         private boolean mShouldRefreshActivityViaPauseForCameraCompat;
1700 
1701         Activity(ActivityRecordProto proto, WindowContainer parent) {
1702             super(proto.windowToken.windowContainer);
1703             name = proto.name;
1704             state = proto.state;
1705             visible = proto.visible;
1706             frontOfTask = proto.frontOfTask;
1707             inSizeCompatMode = proto.inSizeCompatMode;
1708             minAspectRatio = proto.minAspectRatio;
1709             providesMaxBounds = proto.providesMaxBounds;
1710             if (proto.procId != 0) {
1711                 procId = proto.procId;
1712             }
1713             isAnimating = proto.isAnimating;
1714             translucent = proto.translucent;
1715             mEnableRecentsScreenshot = proto.enableRecentsScreenshot;
1716             mLastDropInputMode = proto.lastDropInputMode;
1717             mShouldSendCompatFakeFocus = proto.shouldSendCompatFakeFocus;
1718             mOverrideOrientation = proto.overrideOrientation;
1719             mParent = parent;
1720             mShouldForceRotateForCameraCompat = proto.shouldForceRotateForCameraCompat;
1721             mShouldRefreshActivityForCameraCompat = proto.shouldRefreshActivityForCameraCompat;
1722             mShouldRefreshActivityViaPauseForCameraCompat =
1723                     proto.shouldRefreshActivityViaPauseForCameraCompat;
1724         }
1725 
1726         @NonNull
1727         public Task getTask() {
1728             if (mParent instanceof Task) {
1729                 return (Task) mParent;
1730             }
1731             return ((TaskFragment) mParent).mParentTask;
1732         }
1733 
1734         @Nullable
1735         public TaskFragment getTaskFragment() {
1736             if (mParent instanceof TaskFragment) {
1737                 return (TaskFragment) mParent;
1738             }
1739             return ((Task) mParent).getParentTaskFragment();
1740         }
1741 
1742         public String getName() {
1743             return name;
1744         }
1745 
1746         public String getState() {
1747             return state;
1748         }
1749 
1750         public boolean inSizeCompatMode() {
1751             return inSizeCompatMode;
1752         }
1753 
1754         public boolean isAnimating() {
1755             return isAnimating;
1756         }
1757 
1758         public float getMinAspectRatio() {
1759             return minAspectRatio;
1760         }
1761 
1762         public boolean providesMaxBounds() {
1763             return providesMaxBounds;
1764         }
1765 
1766         public boolean enableRecentsScreenshot() {
1767             return mEnableRecentsScreenshot;
1768         }
1769 
1770         public int getLastDropInputMode() {
1771             return mLastDropInputMode;
1772         }
1773 
1774         public boolean getShouldSendCompatFakeFocus() {
1775             return mShouldSendCompatFakeFocus;
1776         }
1777 
1778         public int getUiMode() {
1779             return mFullConfiguration.uiMode;
1780         }
1781 
1782         public int getOverrideOrientation() {
1783             return mOverrideOrientation;
1784         }
1785 
1786         public boolean getShouldForceRotateForCameraCompat() {
1787             return mShouldForceRotateForCameraCompat;
1788         }
1789 
1790         public boolean getShouldRefreshActivityForCameraCompat() {
1791             return mShouldRefreshActivityForCameraCompat;
1792         }
1793 
1794         public boolean getShouldRefreshActivityViaPauseForCameraCompat() {
1795             return mShouldRefreshActivityViaPauseForCameraCompat;
1796         }
1797 
1798         @Override
1799         public Rect getBounds() {
1800             if (mBounds == null) {
1801                 return mFullConfiguration.windowConfiguration.getBounds();
1802             }
1803             return mBounds;
1804         }
1805 
1806         public Rect getMaxBounds() {
1807             return mFullConfiguration.windowConfiguration.getMaxBounds();
1808         }
1809 
1810         public Rect getAppBounds() {
1811             return mFullConfiguration.windowConfiguration.getAppBounds();
1812         }
1813 
1814         @Override
1815         public String toString() {
1816             return "Activity[name=" + name + ", state=" + state + ", visible=" + visible + "]";
1817         }
1818     }
1819 
1820     static abstract class ActivityContainer extends WindowContainer {
1821         protected boolean mFullscreen;
1822         protected Rect mBounds;
1823         protected int mMinWidth = -1;
1824         protected int mMinHeight = -1;
1825 
1826         ActivityContainer(WindowContainerProto proto) {
1827             super(proto);
1828         }
1829 
1830         public Rect getBounds() {
1831             return mBounds;
1832         }
1833 
1834         boolean isFullscreen() {
1835             return mFullscreen;
1836         }
1837 
1838         int getMinWidth() {
1839             return mMinWidth;
1840         }
1841 
1842         int getMinHeight() {
1843             return mMinHeight;
1844         }
1845     }
1846 
1847     static class KeyguardControllerState {
1848 
1849         boolean aodShowing = false;
1850         boolean keyguardShowing = false;
1851         boolean mKeyguardGoingAway = false;
1852         SparseArray<Boolean> mKeyguardOccludedStates = new SparseArray<>();
1853 
1854         KeyguardControllerState(KeyguardControllerProto proto) {
1855             if (proto != null) {
1856                 aodShowing = proto.aodShowing;
1857                 keyguardShowing = proto.keyguardShowing;
1858                 mKeyguardGoingAway = proto.keyguardGoingAway;
1859                 for (int i = 0;  i < proto.keyguardPerDisplay.length; i++) {
1860                     mKeyguardOccludedStates.append(proto.keyguardPerDisplay[i].displayId,
1861                             proto.keyguardPerDisplay[i].keyguardOccluded);
1862                 }
1863             }
1864         }
1865 
1866         boolean isKeyguardOccluded(int displayId) {
1867             if (mKeyguardOccludedStates.get(displayId) != null) {
1868                 return mKeyguardOccludedStates.get(displayId);
1869             }
1870             return false;
1871         }
1872     }
1873 
1874     static class KeyguardServiceDelegateState {
1875 
1876         // copy from KeyguardServiceDelegate.java
1877         private static final int INTERACTIVE_STATE_SLEEP = 0;
1878         private static final int INTERACTIVE_STATE_WAKING = 1;
1879         private static final int INTERACTIVE_STATE_AWAKE = 2;
1880         private static final int INTERACTIVE_STATE_GOING_TO_SLEEP = 3;
1881 
1882         private int mInteractiveState = -1;
1883 
1884         KeyguardServiceDelegateState(KeyguardServiceDelegateProto proto) {
1885             if (proto != null) {
1886                 mInteractiveState = proto.interactiveState;
1887             }
1888         }
1889 
1890         boolean isKeyguardAwake() {
1891             return mInteractiveState == INTERACTIVE_STATE_AWAKE;
1892         }
1893     }
1894 
1895     static class ConfigurationContainer {
1896         final Configuration mOverrideConfiguration = new Configuration();
1897         final Configuration mFullConfiguration = new Configuration();
1898         final Configuration mMergedOverrideConfiguration = new Configuration();
1899 
1900         ConfigurationContainer(ConfigurationContainerProto proto) {
1901             if (proto == null) {
1902                 return;
1903             }
1904             mOverrideConfiguration.setTo(extract(proto.overrideConfiguration));
1905             mFullConfiguration.setTo(extract(proto.fullConfiguration));
1906             mMergedOverrideConfiguration.setTo(extract(proto.mergedOverrideConfiguration));
1907         }
1908 
1909         boolean isWindowingModeCompatible(int requestedWindowingMode) {
1910             if (requestedWindowingMode == WINDOWING_MODE_UNDEFINED) {
1911                 return true;
1912             }
1913             return getWindowingMode() == requestedWindowingMode;
1914         }
1915 
1916         public int getWindowingMode() {
1917             if (mFullConfiguration == null) {
1918                 return WINDOWING_MODE_UNDEFINED;
1919             }
1920             return mFullConfiguration.windowConfiguration.getWindowingMode();
1921         }
1922 
1923         int getActivityType() {
1924             if (mFullConfiguration == null) {
1925                 return ACTIVITY_TYPE_UNDEFINED;
1926             }
1927             return mFullConfiguration.windowConfiguration.getActivityType();
1928         }
1929     }
1930 
1931     public static class RootWindowContainer extends WindowContainer {
1932         RootWindowContainer(RootWindowContainerProto proto) {
1933             super(proto.windowContainer);
1934         }
1935     }
1936     public static class DisplayArea extends WindowContainer {
1937         private final boolean mIsTaskDisplayArea;
1938         private final boolean mIsRootDisplayArea;
1939         private final int mFeatureId;
1940         private final boolean mIsOrganized;
1941         private final boolean mIsIgnoringOrientationRequest;
1942         private ArrayList<Activity> mActivities;
1943         private final ArrayList<WindowState> mWindows = new ArrayList<>();
1944 
1945         DisplayArea(DisplayAreaProto proto) {
1946             super(proto.windowContainer);
1947             mIsTaskDisplayArea = proto.isTaskDisplayArea;
1948             mIsRootDisplayArea = proto.isRootDisplayArea;
1949             mFeatureId = proto.featureId;
1950             mIsOrganized = proto.isOrganized;
1951             mIsIgnoringOrientationRequest = proto.isIgnoringOrientationRequest;
1952             if (mIsTaskDisplayArea) {
1953                 mActivities = new ArrayList<>();
1954                 collectDescendantsOfType(Activity.class, this, mActivities);
1955             }
1956             collectDescendantsOfType(WindowState.class, this, mWindows);
1957         }
1958 
1959         boolean isTaskDisplayArea() {
1960             return mIsTaskDisplayArea;
1961         }
1962 
1963         boolean isRootDisplayArea() {
1964             return mIsRootDisplayArea;
1965         }
1966 
1967         int getFeatureId() {
1968             return mFeatureId;
1969         }
1970 
1971         public boolean isOrganized() {
1972             return mIsOrganized;
1973         }
1974 
1975         public Rect getAppBounds() {
1976             return mFullConfiguration.windowConfiguration.getAppBounds();
1977         }
1978 
1979         public boolean isIgnoringOrientationRequest() {
1980             return mIsIgnoringOrientationRequest;
1981         }
1982 
1983         @Override
1984         public Rect getBounds() {
1985             if (mBounds == null) {
1986                 return mFullConfiguration.windowConfiguration.getBounds();
1987             }
1988             return mBounds;
1989         }
1990 
1991         boolean containsActivity(ComponentName activityName) {
1992             if (!mIsTaskDisplayArea) {
1993                 return false;
1994             }
1995 
1996             final String fullName = getActivityName(activityName);
1997             for (Activity a : mActivities) {
1998                 if (a.name.equals(fullName)) {
1999                     return true;
2000                 }
2001             }
2002             return false;
2003         }
2004 
2005         boolean containsWindow(String windowName) {
2006             for (WindowState w : mWindows) {
2007                 if (w.mName.equals(windowName)) {
2008                     return true;
2009                 }
2010             }
2011             return false;
2012         }
2013     }
2014     public static class WindowToken extends WindowContainer {
2015         WindowToken(WindowTokenProto proto) {
2016             super(proto.windowContainer);
2017         }
2018     }
2019 
2020     /**
2021      * Represents WindowContainer classes such as DisplayContent.WindowContainers and
2022      * DisplayContent.NonAppWindowContainers. This can be expanded into a specific class
2023      * if we need track and assert some state in the future.
2024      */
2025     public static class GenericWindowContainer extends WindowContainer {
2026         GenericWindowContainer(WindowContainerProto proto) {
2027             super(proto);
2028         }
2029     }
2030 
2031     static WindowContainer getWindowContainer(WindowContainerChildProto proto,
2032             WindowContainer parent) {
2033         if (proto.displayContent != null) {
2034             return new DisplayContent(proto.displayContent);
2035         }
2036 
2037         if (proto.displayArea != null) {
2038             return new DisplayArea(proto.displayArea);
2039         }
2040 
2041         if (proto.task != null) {
2042             return new Task(proto.task, parent);
2043         }
2044 
2045         if (proto.taskFragment != null) {
2046             return new TaskFragment(proto.taskFragment, parent);
2047         }
2048 
2049         if (proto.activity != null) {
2050             return new Activity(proto.activity, parent);
2051         }
2052 
2053         if (proto.windowToken != null) {
2054             return new WindowToken(proto.windowToken);
2055         }
2056 
2057         if (proto.window != null) {
2058             return new WindowState(proto.window);
2059         }
2060 
2061         if (proto.windowContainer != null) {
2062             return new GenericWindowContainer(proto.windowContainer);
2063         }
2064         return null;
2065     }
2066 
2067     static abstract class WindowContainer extends ConfigurationContainer {
2068 
2069         protected String mName;
2070         protected final String mAppToken;
2071         protected boolean mFullscreen;
2072         protected Rect mBounds;
2073         protected int mOrientation;
2074         protected boolean mVisible;
2075         protected List<WindowState> mSubWindows = new ArrayList<>();
2076         protected List<WindowContainer> mChildren = new ArrayList<>();
2077 
2078         WindowContainer(WindowContainerProto proto) {
2079             super(proto.configurationContainer);
2080             IdentifierProto identifierProto = proto.identifier;
2081             mName = identifierProto.title;
2082             mAppToken = Integer.toHexString(identifierProto.hashCode);
2083             mOrientation = proto.orientation;
2084             for (int i = 0; i < proto.children.length; i++) {
2085                 final WindowContainer child = getWindowContainer(proto.children[i], this);
2086                 if (child != null) {
2087                     mChildren.add(child);
2088                 }
2089             }
2090             mVisible = proto.visible;
2091         }
2092 
2093         @NonNull
2094         public String getName() {
2095             return mName;
2096         }
2097 
2098         @NonNull
2099         public String getPackageName() {
2100             int sep = mName.indexOf('/');
2101             return sep == -1 ? mName : mName.substring(0, sep);
2102         }
2103 
2104         String getToken() {
2105             return mAppToken;
2106         }
2107 
2108         Rect getBounds() {
2109             return mBounds;
2110         }
2111 
2112         boolean isFullscreen() {
2113             return mFullscreen;
2114         }
2115 
2116         boolean isVisible() {
2117             return mVisible;
2118         }
2119 
2120         List<WindowState> getWindows() {
2121             return mSubWindows;
2122         }
2123     }
2124 
2125     public static class WindowState extends WindowContainer {
2126 
2127         private static final int WINDOW_TYPE_NORMAL = 0;
2128         public static final int WINDOW_TYPE_STARTING = 1;
2129         private static final int WINDOW_TYPE_EXITING = 2;
2130         private static final int WINDOW_TYPE_DEBUGGER = 3;
2131 
2132         private final int mWindowType;
2133         private int mType = 0;
2134         private int mDisplayId;
2135         private int mStackId;
2136         private int mLayer;
2137         private boolean mShown;
2138         private Rect mParentFrame;
2139         private Rect mFrame;
2140         private Rect mCompatFrame;
2141         private Rect mSurfaceInsets;
2142         private Rect mGivenContentInsets;
2143         private Rect mCrop = new Rect();
2144         private boolean mHasCompatScale;
2145         private float mGlobalScale;
2146         private int mRequestedWidth;
2147         private int mRequestedHeight;
2148         private List<Rect> mKeepClearRects;
2149         private List<Rect> mUnrestrictedKeepClearRects;
2150         private List<InsetsSource> mMergedLocalInsetsSources;
2151 
2152         WindowState(WindowStateProto proto) {
2153             super(proto.windowContainer);
2154             mDisplayId = proto.displayId;
2155             mStackId = proto.stackId;
2156             if (proto.attributes != null) {
2157                 mType = proto.attributes.type;
2158             }
2159             WindowStateAnimatorProto animatorProto = proto.animator;
2160             if (animatorProto != null) {
2161                 if (animatorProto.surface != null) {
2162                     WindowSurfaceControllerProto surfaceProto = animatorProto.surface;
2163                     mShown = surfaceProto.shown;
2164                     mLayer = surfaceProto.layer;
2165                 }
2166                 mCrop = extract(animatorProto.lastClipRect);
2167             }
2168             mGivenContentInsets = extract(proto.givenContentInsets);
2169             WindowFramesProto windowFramesProto = proto.windowFrames;
2170             if (windowFramesProto != null) {
2171                 mFrame = extract(windowFramesProto.frame);
2172                 mParentFrame = extract(windowFramesProto.parentFrame);
2173                 mCompatFrame = extract(windowFramesProto.compatFrame);
2174             }
2175             mSurfaceInsets = extract(proto.surfaceInsets);
2176             if (mName.startsWith(STARTING_WINDOW_PREFIX)) {
2177                 mWindowType = WINDOW_TYPE_STARTING;
2178                 // Existing code depends on the prefix being removed
2179                 mName = mName.substring(STARTING_WINDOW_PREFIX.length());
2180             } else if (proto.animatingExit) {
2181                 mWindowType = WINDOW_TYPE_EXITING;
2182             } else if (mName.startsWith(DEBUGGER_WINDOW_PREFIX)) {
2183                 mWindowType = WINDOW_TYPE_DEBUGGER;
2184                 mName = mName.substring(DEBUGGER_WINDOW_PREFIX.length());
2185             } else {
2186                 mWindowType = 0;
2187             }
2188             collectDescendantsOfType(WindowState.class, this, mSubWindows);
2189             mHasCompatScale = proto.hasCompatScale;
2190             mGlobalScale = proto.globalScale;
2191             mRequestedWidth = proto.requestedWidth;
2192             mRequestedHeight = proto.requestedHeight;
2193             mKeepClearRects = new ArrayList();
2194             for (RectProto r : proto.keepClearAreas) {
2195                 mKeepClearRects.add(new Rect(r.left, r.top, r.right, r.bottom));
2196             }
2197             mUnrestrictedKeepClearRects = new ArrayList();
2198             for (RectProto r : proto.unrestrictedKeepClearAreas) {
2199                 mUnrestrictedKeepClearRects.add(new Rect(r.left, r.top, r.right, r.bottom));
2200             }
2201             mMergedLocalInsetsSources = new ArrayList();
2202             for (InsetsSourceProto insets : proto.mergedLocalInsetsSources) {
2203                 mMergedLocalInsetsSources.add(new InsetsSource(insets));
2204             }
2205         }
2206 
2207         boolean isStartingWindow() {
2208             return mWindowType == WINDOW_TYPE_STARTING;
2209         }
2210 
2211         boolean isExitingWindow() {
2212             return mWindowType == WINDOW_TYPE_EXITING;
2213         }
2214 
2215         boolean isDebuggerWindow() {
2216             return mWindowType == WINDOW_TYPE_DEBUGGER;
2217         }
2218 
2219         int getDisplayId() {
2220             return mDisplayId;
2221         }
2222 
2223         int getStackId() {
2224             return mStackId;
2225         }
2226 
2227         public Rect getFrame() {
2228             return mFrame;
2229         }
2230 
2231         Rect getSurfaceInsets() {
2232             return mSurfaceInsets;
2233         }
2234 
2235         Rect getGivenContentInsets() {
2236             return mGivenContentInsets;
2237         }
2238 
2239         Rect getParentFrame() {
2240             return mParentFrame;
2241         }
2242 
2243         public Rect getCompatFrame() {
2244             return mCompatFrame;
2245         }
2246 
2247         Rect getCrop() {
2248             return mCrop;
2249         }
2250 
2251         public boolean isSurfaceShown() {
2252             return mShown;
2253         }
2254 
2255         public int getType() {
2256             return mType;
2257         }
2258 
2259         public boolean hasCompatScale() {
2260             return mHasCompatScale;
2261         }
2262 
2263         public float getGlobalScale() {
2264             return mGlobalScale;
2265         }
2266 
2267         public int getRequestedWidth() {
2268             return mRequestedWidth;
2269         }
2270 
2271         public int getRequestedHeight() {
2272             return mRequestedHeight;
2273         }
2274 
2275         public List<Rect> getKeepClearRects() {
2276             return mKeepClearRects;
2277         }
2278 
2279         public List<Rect> getUnrestrictedKeepClearRects() {
2280             return mUnrestrictedKeepClearRects;
2281         }
2282 
2283         List<InsetsSource> getMergedLocalInsetsSources() {
2284             return mMergedLocalInsetsSources;
2285         }
2286 
2287         private String getWindowTypeSuffix(int windowType) {
2288             switch (windowType) {
2289                 case WINDOW_TYPE_STARTING:
2290                     return " STARTING";
2291                 case WINDOW_TYPE_EXITING:
2292                     return " EXITING";
2293                 case WINDOW_TYPE_DEBUGGER:
2294                     return " DEBUGGER";
2295                 default:
2296                     break;
2297             }
2298             return "";
2299         }
2300 
2301         @Override
2302         public String toString() {
2303             return "WindowState: {" + mAppToken + " " + mName
2304                     + getWindowTypeSuffix(mWindowType) + "}" + " type=" + mType
2305                     + " pf=" + mParentFrame;
2306         }
2307 
2308         public String toLongString() {
2309             return toString() + " f=" + mFrame + " crop=" + mCrop + " isSurfaceShown="
2310                     + isSurfaceShown();
2311         }
2312     }
2313 
2314     static class BackNavigationState {
2315         private boolean mAnimationInProgress;
2316         private int mLastBackType;
2317         private boolean mShowWallpaper;
2318 
2319         BackNavigationState(BackNavigationProto proto) {
2320             if (proto != null) {
2321                 mAnimationInProgress = proto.animationInProgress;
2322                 mLastBackType = proto.lastBackType;
2323                 mShowWallpaper = proto.showWallpaper;
2324             }
2325         }
2326 
2327         boolean isAnimationInProgress() {
2328             return mAnimationInProgress;
2329         }
2330 
2331         int getLastBackType() {
2332             return mLastBackType;
2333         }
2334 
2335         boolean isShowWallpaper() {
2336             return mShowWallpaper;
2337         }
2338     }
2339 
2340     static int dpToPx(float dp, int densityDpi) {
2341         return (int) (dp * densityDpi / DENSITY_DEFAULT + 0.5f);
2342     }
2343 
2344     int defaultMinimalTaskSize(int displayId) {
2345         final DisplayContent dc = getDisplay(displayId);
2346         return dpToPx(dc.mMinSizeOfResizeableTaskDp, dc.getDpi());
2347     }
2348 
2349     int defaultMinimalDisplaySizeForSplitScreen(int displayId) {
2350         return dpToPx(ActivityTaskManager.DEFAULT_MINIMAL_SPLIT_SCREEN_DISPLAY_SIZE_DP,
2351                 getDisplay(displayId).getDpi());
2352     }
2353 
2354     static class InsetsSource {
2355         private String mType;
2356         private Rect mFrame;
2357         private Rect mVisibleFrame;
2358         private boolean mVisible;
2359 
2360         InsetsSource(InsetsSourceProto proto) {
2361             mType = proto.type;
2362             mFrame = new Rect(
2363                     proto.frame.left, proto.frame.top, proto.frame.right, proto.frame.bottom);
2364             if (proto.visibleFrame != null) {
2365                 mVisibleFrame = new Rect(proto.visibleFrame.left, proto.visibleFrame.top,
2366                         proto.visibleFrame.right, proto.visibleFrame.bottom);
2367             }
2368             mVisible = proto.visible;
2369         }
2370 
2371         String getType() {
2372             return mType;
2373         }
2374 
2375         Rect getFrame() {
2376             return mFrame;
2377         }
2378 
2379         Rect getVisibleFrame() {
2380             return mVisibleFrame;
2381         }
2382 
2383         boolean isVisible() {
2384             return mVisible;
2385         }
2386 
2387         boolean isCaptionBar() {
2388             return mType.contains("captionBar");
2389         }
2390 
2391         void insetGivenFrame(Rect inOutFrame) {
2392             if (inOutFrame.left == mFrame.left && inOutFrame.right == mFrame.right) {
2393                 if (inOutFrame.top == mFrame.top) {
2394                     inOutFrame.top = mFrame.bottom;
2395                     return;
2396                 }
2397                 if (inOutFrame.bottom == mFrame.bottom) {
2398                     inOutFrame.bottom = mFrame.top;
2399                     return;
2400                 }
2401             }
2402             if (inOutFrame.top == mFrame.top && inOutFrame.bottom == mFrame.bottom) {
2403                 if (inOutFrame.left == mFrame.left) {
2404                     inOutFrame.left = mFrame.right;
2405                     return;
2406                 }
2407                 if (inOutFrame.right == mFrame.right) {
2408                     inOutFrame.right = mFrame.left;
2409                     return;
2410                 }
2411             }
2412         }
2413 
2414         @Override
2415         public String toString() {
2416             return "InsetsSource: {type=" + mType
2417                     + " frame=" + mFrame
2418                     + " visibleFrame=" + mVisibleFrame
2419                     + " visible=" + mVisible
2420                     + "}";
2421         }
2422     }
2423 }
2424