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