1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package android.server.wm;
18 
19 import static android.app.ActivityTaskManager.INVALID_STACK_ID;
20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
23 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
24 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
25 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
26 import static android.server.wm.ComponentNameUtils.getActivityName;
27 import static android.server.wm.ProtoExtractors.extract;
28 import static android.server.wm.StateLogger.log;
29 import static android.server.wm.StateLogger.logE;
30 import static android.server.wm.TestTaskOrganizer.INVALID_TASK_ID;
31 import static android.util.DisplayMetrics.DENSITY_DEFAULT;
32 import static android.view.Display.DEFAULT_DISPLAY;
33 
34 import static androidx.test.InstrumentationRegistry.getInstrumentation;
35 
36 import static com.google.common.truth.Truth.assertWithMessage;
37 
38 import static org.junit.Assert.assertTrue;
39 import static org.junit.Assert.fail;
40 
41 import android.app.ActivityTaskManager;
42 import android.content.ComponentName;
43 import android.content.res.Configuration;
44 import android.graphics.Point;
45 import android.graphics.Rect;
46 import android.os.ParcelFileDescriptor;
47 import android.os.SystemClock;
48 import android.util.SparseArray;
49 import android.view.WindowManager;
50 import android.view.nano.DisplayInfoProto;
51 import android.view.nano.ViewProtoEnums;
52 
53 import androidx.annotation.NonNull;
54 import androidx.annotation.Nullable;
55 
56 import com.android.server.wm.nano.ActivityRecordProto;
57 import com.android.server.wm.nano.AppTransitionProto;
58 import com.android.server.wm.nano.ConfigurationContainerProto;
59 import com.android.server.wm.nano.DisplayAreaProto;
60 import com.android.server.wm.nano.DisplayContentProto;
61 import com.android.server.wm.nano.DisplayFramesProto;
62 import com.android.server.wm.nano.DisplayRotationProto;
63 import com.android.server.wm.nano.IdentifierProto;
64 import com.android.server.wm.nano.KeyguardControllerProto;
65 import com.android.server.wm.nano.PinnedTaskControllerProto;
66 import com.android.server.wm.nano.RootWindowContainerProto;
67 import com.android.server.wm.nano.TaskProto;
68 import com.android.server.wm.nano.WindowContainerChildProto;
69 import com.android.server.wm.nano.WindowContainerProto;
70 import com.android.server.wm.nano.WindowFramesProto;
71 import com.android.server.wm.nano.WindowManagerServiceDumpProto;
72 import com.android.server.wm.nano.WindowStateAnimatorProto;
73 import com.android.server.wm.nano.WindowStateProto;
74 import com.android.server.wm.nano.WindowSurfaceControllerProto;
75 import com.android.server.wm.nano.WindowTokenProto;
76 
77 import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
78 
79 import java.io.ByteArrayOutputStream;
80 import java.io.FileInputStream;
81 import java.io.IOException;
82 import java.nio.charset.StandardCharsets;
83 import java.util.ArrayList;
84 import java.util.Arrays;
85 import java.util.List;
86 import java.util.function.Consumer;
87 import java.util.function.Predicate;
88 import java.util.stream.Collectors;
89 import java.util.stream.Stream;
90 
91 public class WindowManagerState {
92 
93     public static final String STATE_INITIALIZING = "INITIALIZING";
94     public static final String STATE_RESUMED = "RESUMED";
95     public static final String STATE_PAUSED = "PAUSED";
96     public static final String STATE_STOPPED = "STOPPED";
97     public static final String STATE_DESTROYED = "DESTROYED";
98     public static final String TRANSIT_ACTIVITY_OPEN = "TRANSIT_ACTIVITY_OPEN";
99     public static final String TRANSIT_ACTIVITY_CLOSE = "TRANSIT_ACTIVITY_CLOSE";
100     public static final String TRANSIT_TASK_OPEN = "TRANSIT_TASK_OPEN";
101     public static final String TRANSIT_TASK_CLOSE = "TRANSIT_TASK_CLOSE";
102     public static final String TRANSIT_WALLPAPER_OPEN = "TRANSIT_WALLPAPER_OPEN";
103     public static final String TRANSIT_WALLPAPER_CLOSE = "TRANSIT_WALLPAPER_CLOSE";
104     public static final String TRANSIT_WALLPAPER_INTRA_OPEN = "TRANSIT_WALLPAPER_INTRA_OPEN";
105     public static final String TRANSIT_WALLPAPER_INTRA_CLOSE = "TRANSIT_WALLPAPER_INTRA_CLOSE";
106     public static final String TRANSIT_KEYGUARD_GOING_AWAY = "TRANSIT_KEYGUARD_GOING_AWAY";
107     public static final String TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER =
108             "TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER";
109     public static final String TRANSIT_KEYGUARD_OCCLUDE = "TRANSIT_KEYGUARD_OCCLUDE";
110     public static final String TRANSIT_KEYGUARD_UNOCCLUDE = "TRANSIT_KEYGUARD_UNOCCLUDE";
111     public static final String TRANSIT_TRANSLUCENT_ACTIVITY_OPEN =
112             "TRANSIT_TRANSLUCENT_ACTIVITY_OPEN";
113     public static final String TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE =
114             "TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE";
115     public static final String APP_STATE_IDLE = "APP_STATE_IDLE";
116     public static final String APP_STATE_RUNNING = "APP_STATE_RUNNING";
117 
118     private static final String DUMPSYS_WINDOW = "dumpsys window -a --proto";
119     private static final String STARTING_WINDOW_PREFIX = "Starting ";
120     private static final String DEBUGGER_WINDOW_PREFIX = "Waiting For Debugger: ";
121     /** @see WindowManager.LayoutParams */
122     private static final int TYPE_NAVIGATION_BAR = 2019;
123     /** @see WindowManager.LayoutParams */
124     private static final int TYPE_NAVIGATION_BAR_PANEL = 2024;
125     /** @see WindowManager.LayoutParams */
126     private static final int TYPE_NOTIFICATION_SHADE = 2040;
127 
128     // Default minimal size of resizable task, used if none is set explicitly.
129     // Must be kept in sync with 'default_minimal_size_resizable_task' dimen from frameworks/base.
130     private static final int DEFAULT_RESIZABLE_TASK_SIZE_DP = 220;
131 
132     private RootWindowContainer mRoot = null;
133     // Displays in z-order with the top most at the front of the list, starting with primary.
134     private final List<DisplayContent> mDisplays = new ArrayList<>();
135     // Stacks in z-order with the top most at the front of the list, starting with primary display.
136     private final List<ActivityTask> mRootTasks = new ArrayList<>();
137     // Windows in z-order with the top most at the front of the list.
138     private final List<WindowState> mWindowStates = new ArrayList<>();
139     private KeyguardControllerState mKeyguardControllerState;
140     private final List<String> mPendingActivities = new ArrayList<>();
141     private int mTopFocusedTaskId = -1;
142     private int mFocusedDisplayId = DEFAULT_DISPLAY;
143     private String mFocusedWindow = null;
144     private String mFocusedApp = null;
145     private Boolean mIsHomeRecentsComponent;
146     private String mTopResumedActivityRecord = null;
147     final List<String> mResumedActivitiesInStacks = new ArrayList<>();
148     final List<String> mResumedActivitiesInDisplays = new ArrayList<>();
149     private Rect mDefaultPinnedStackBounds = new Rect();
150     private Rect mPinnedStackMovementBounds = new Rect();
151     private String mInputMethodWindowAppToken = null;
152     private boolean mDisplayFrozen;
153     private boolean mSanityCheckFocusedWindow = true;
154 
appStateToString(int appState)155     static String appStateToString(int appState) {
156         switch (appState) {
157             case AppTransitionProto.APP_STATE_IDLE:
158                 return "APP_STATE_IDLE";
159             case AppTransitionProto.APP_STATE_READY:
160                 return "APP_STATE_READY";
161             case AppTransitionProto.APP_STATE_RUNNING:
162                 return "APP_STATE_RUNNING";
163             case AppTransitionProto.APP_STATE_TIMEOUT:
164                 return "APP_STATE_TIMEOUT";
165             default:
166                 fail("Invalid AppTransitionState");
167                 return null;
168         }
169     }
170 
appTransitionToString(int transition)171     static String appTransitionToString(int transition) {
172         switch (transition) {
173             case ViewProtoEnums.TRANSIT_UNSET: {
174                 return "TRANSIT_UNSET";
175             }
176             case ViewProtoEnums.TRANSIT_NONE: {
177                 return "TRANSIT_NONE";
178             }
179             case ViewProtoEnums.TRANSIT_ACTIVITY_OPEN: {
180                 return TRANSIT_ACTIVITY_OPEN;
181             }
182             case ViewProtoEnums.TRANSIT_ACTIVITY_CLOSE: {
183                 return TRANSIT_ACTIVITY_CLOSE;
184             }
185             case ViewProtoEnums.TRANSIT_TASK_OPEN: {
186                 return TRANSIT_TASK_OPEN;
187             }
188             case ViewProtoEnums.TRANSIT_TASK_CLOSE: {
189                 return TRANSIT_TASK_CLOSE;
190             }
191             case ViewProtoEnums.TRANSIT_TASK_TO_FRONT: {
192                 return "TRANSIT_TASK_TO_FRONT";
193             }
194             case ViewProtoEnums.TRANSIT_TASK_TO_BACK: {
195                 return "TRANSIT_TASK_TO_BACK";
196             }
197             case ViewProtoEnums.TRANSIT_WALLPAPER_CLOSE: {
198                 return TRANSIT_WALLPAPER_CLOSE;
199             }
200             case ViewProtoEnums.TRANSIT_WALLPAPER_OPEN: {
201                 return TRANSIT_WALLPAPER_OPEN;
202             }
203             case ViewProtoEnums.TRANSIT_WALLPAPER_INTRA_OPEN: {
204                 return TRANSIT_WALLPAPER_INTRA_OPEN;
205             }
206             case ViewProtoEnums.TRANSIT_WALLPAPER_INTRA_CLOSE: {
207                 return TRANSIT_WALLPAPER_INTRA_CLOSE;
208             }
209             case ViewProtoEnums.TRANSIT_TASK_OPEN_BEHIND: {
210                 return "TRANSIT_TASK_OPEN_BEHIND";
211             }
212             case ViewProtoEnums.TRANSIT_ACTIVITY_RELAUNCH: {
213                 return "TRANSIT_ACTIVITY_RELAUNCH";
214             }
215             case ViewProtoEnums.TRANSIT_DOCK_TASK_FROM_RECENTS: {
216                 return "TRANSIT_DOCK_TASK_FROM_RECENTS";
217             }
218             case ViewProtoEnums.TRANSIT_KEYGUARD_GOING_AWAY: {
219                 return TRANSIT_KEYGUARD_GOING_AWAY;
220             }
221             case ViewProtoEnums.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER: {
222                 return TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
223             }
224             case ViewProtoEnums.TRANSIT_KEYGUARD_OCCLUDE: {
225                 return TRANSIT_KEYGUARD_OCCLUDE;
226             }
227             case ViewProtoEnums.TRANSIT_KEYGUARD_UNOCCLUDE: {
228                 return TRANSIT_KEYGUARD_UNOCCLUDE;
229             }
230             case ViewProtoEnums.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN: {
231                 return TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
232             }
233             case ViewProtoEnums.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE: {
234                 return TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
235             }
236             case ViewProtoEnums.TRANSIT_CRASHING_ACTIVITY_CLOSE: {
237                 return "TRANSIT_CRASHING_ACTIVITY_CLOSE";
238             }
239             default: {
240                 fail("Invalid lastUsedAppTransition");
241                 return null;
242             }
243         }
244     }
245 
isValidNavBarType(WindowState navState)246     static boolean isValidNavBarType(WindowState navState) {
247         return TYPE_NAVIGATION_BAR == navState.getType();
248     }
249 
250     /**
251      * For a given WindowContainer, traverse down the hierarchy and add all children of type
252      * {@code T} to {@code outChildren}.
253      */
collectDescendantsOfType(Class<T> clazz, WindowContainer root, List<T> outChildren)254     private static <T extends WindowContainer> void collectDescendantsOfType(Class<T> clazz,
255             WindowContainer root, List<T> outChildren) {
256         collectDescendantsOfTypeIf(clazz, t -> true, root, outChildren);
257     }
258 
259     /**
260      * For a given WindowContainer, traverse down the hierarchy and add all children of type
261      * {@code T} to {@code outChildren} if the child passes the test {@code predicate}.
262      */
collectDescendantsOfTypeIf(Class<T> clazz, Predicate<T> predicate, WindowContainer root, List<T> outChildren)263     private static <T extends WindowContainer> void collectDescendantsOfTypeIf(Class<T> clazz,
264             Predicate<T> predicate, WindowContainer root, List<T> outChildren) {
265         // Traverse top to bottom
266         for (int i = root.mChildren.size()-1; i >= 0; i--) {
267             final WindowContainer child = root.mChildren.get(i);
268             if (clazz.isInstance(child)) {
269                 if(predicate.test(clazz.cast(child))) {
270                     outChildren.add(clazz.cast(child));
271                 }
272             }
273             collectDescendantsOfTypeIf(clazz, predicate, child, outChildren);
274         }
275     }
276 
277     /**
278      * For a given WindowContainer, traverse down the hierarchy and add all immediate children of
279      * type {@code T} to {@code outChildren}.
280      */
collectChildrenOfType(Class<T> clazz, WindowContainer root, List<T> outChildren)281     private static <T extends WindowContainer> void collectChildrenOfType(Class<T> clazz,
282             WindowContainer root, List<T> outChildren) {
283         for (int i = root.mChildren.size()-1; i >= 0; i--) {
284             final WindowContainer child = root.mChildren.get(i);
285             if (clazz.isInstance(child)) {
286                 outChildren.add(clazz.cast(child));
287             }
288         }
289     }
290 
291     /** Enable/disable the mFocusedWindow check during the computeState.*/
setSanityCheckWithFocusedWindow(boolean sanityCheckFocusedWindow)292     void setSanityCheckWithFocusedWindow(boolean sanityCheckFocusedWindow) {
293         mSanityCheckFocusedWindow = sanityCheckFocusedWindow;
294     }
295 
computeState()296     public void computeState() {
297         // It is possible the system is in the middle of transition to the right state when we get
298         // the dump. We try a few times to get the information we need before giving up.
299         int retriesLeft = 3;
300         boolean retry = false;
301         byte[] dump = null;
302 
303         log("==============================");
304         log("     WindowManagerState     ");
305         log("==============================");
306 
307         do {
308             if (retry) {
309                 log("***Incomplete AM state. Retrying...");
310                 // Wait half a second between retries for activity manager to finish transitioning.
311                 SystemClock.sleep(500);
312             }
313 
314             dump = executeShellCommand(DUMPSYS_WINDOW);
315             try {
316                 parseSysDumpProto(dump);
317             } catch (InvalidProtocolBufferNanoException ex) {
318                 throw new RuntimeException("Failed to parse dumpsys:\n"
319                         + new String(dump, StandardCharsets.UTF_8), ex);
320             }
321 
322             retry = mRootTasks.isEmpty() || mTopFocusedTaskId == -1 || mWindowStates.isEmpty()
323                     || mFocusedApp == null || (mSanityCheckFocusedWindow && mFocusedWindow == null)
324                     || (mTopResumedActivityRecord == null || mResumedActivitiesInStacks.isEmpty())
325                     && !mKeyguardControllerState.keyguardShowing;
326         } while (retry && retriesLeft-- > 0);
327 
328         if (mRootTasks.isEmpty()) {
329             logE("No stacks found...");
330         }
331         if (mTopFocusedTaskId == -1) {
332             logE("No focused stack found...");
333         }
334         if (mTopResumedActivityRecord == null) {
335             logE("No focused activity found...");
336         }
337         if (mResumedActivitiesInStacks.isEmpty()) {
338             logE("No resumed activities found...");
339         }
340         if (mWindowStates.isEmpty()) {
341             logE("No Windows found...");
342         }
343         if (mFocusedWindow == null) {
344             logE("No Focused Window...");
345         }
346         if (mFocusedApp == null) {
347             logE("No Focused App...");
348         }
349     }
350 
executeShellCommand(String cmd)351     private byte[] executeShellCommand(String cmd) {
352         try {
353             ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
354                     .executeShellCommand(cmd);
355             byte[] buf = new byte[512];
356             int bytesRead;
357             FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
358             ByteArrayOutputStream stdout = new ByteArrayOutputStream();
359             while ((bytesRead = fis.read(buf)) != -1) {
360                 stdout.write(buf, 0, bytesRead);
361             }
362             fis.close();
363             return stdout.toByteArray();
364         } catch (IOException e) {
365             throw new RuntimeException(e);
366         }
367     }
368 
369     /** Update WindowManagerState state for a newly added DisplayContent. */
updateForDisplayContent(DisplayContent display)370     private void updateForDisplayContent(DisplayContent display) {
371         if (display.mResumedActivity != null) {
372             mResumedActivitiesInDisplays.add(display.mResumedActivity);
373         }
374 
375         for (int i = 0; i < display.mRootTasks.size(); i++) {
376             ActivityTask task = display.mRootTasks.get(i);
377             mRootTasks.add(task);
378             addResumedActivity(task);
379         }
380 
381         if (display.mDefaultPinnedStackBounds != null) {
382             mDefaultPinnedStackBounds = display.mDefaultPinnedStackBounds;
383             mPinnedStackMovementBounds = display.mPinnedStackMovementBounds;
384         }
385     }
386 
addResumedActivity(ActivityTask task)387     private void addResumedActivity(ActivityTask task) {
388         final int numChildTasks = task.mTasks.size();
389         if (numChildTasks > 0) {
390             for (int i = numChildTasks - 1; i >=0; i--) {
391                 addResumedActivity(task.mTasks.get(i));
392             }
393         } else if (task.mResumedActivity != null) {
394             mResumedActivitiesInStacks.add(task.mResumedActivity);
395         }
396     }
397 
parseSysDumpProto(byte[] sysDump)398     private void parseSysDumpProto(byte[] sysDump) throws InvalidProtocolBufferNanoException {
399         reset();
400 
401         WindowManagerServiceDumpProto state = WindowManagerServiceDumpProto.parseFrom(sysDump);
402         final RootWindowContainerProto root = state.rootWindowContainer;
403         if (state.focusedWindow != null) {
404             mFocusedWindow = state.focusedWindow.title;
405         }
406         mRoot = new RootWindowContainer(root);
407         collectDescendantsOfType(DisplayContent.class, mRoot, mDisplays);
408         for (int i = 0; i < mDisplays.size(); i++) {
409             DisplayContent display = mDisplays.get(i);
410             updateForDisplayContent(display);
411         }
412         mKeyguardControllerState = new KeyguardControllerState(root.keyguardController);
413         mFocusedApp = state.focusedApp;
414         mFocusedDisplayId = state.focusedDisplayId;
415         final DisplayContent focusedDisplay = getDisplay(mFocusedDisplayId);
416         if (focusedDisplay != null) {
417             mTopFocusedTaskId = focusedDisplay.mFocusedRootTaskId;
418             mTopResumedActivityRecord = focusedDisplay.mResumedActivity;
419         }
420         mIsHomeRecentsComponent = new Boolean(root.isHomeRecentsComponent);
421 
422         for (int i = 0; i < root.pendingActivities.length; i++) {
423             mPendingActivities.add(root.pendingActivities[i].title);
424         }
425 
426         collectDescendantsOfType(WindowState.class, mRoot, mWindowStates);
427 
428         if (state.inputMethodWindow != null) {
429             mInputMethodWindowAppToken = Integer.toHexString(state.inputMethodWindow.hashCode);
430         }
431         mDisplayFrozen = state.displayFrozen;
432     }
433 
reset()434     private void reset() {
435         mRoot = null;
436         mDisplays.clear();
437         mRootTasks.clear();
438         mWindowStates.clear();
439         mTopFocusedTaskId = -1;
440         mFocusedDisplayId = DEFAULT_DISPLAY;
441         mFocusedWindow = null;
442         mFocusedApp = null;
443         mTopResumedActivityRecord = null;
444         mResumedActivitiesInStacks.clear();
445         mResumedActivitiesInDisplays.clear();
446         mKeyguardControllerState = null;
447         mIsHomeRecentsComponent = null;
448         mPendingActivities.clear();
449         mDefaultPinnedStackBounds.setEmpty();
450         mPinnedStackMovementBounds.setEmpty();
451         mInputMethodWindowAppToken = null;
452         mDisplayFrozen = false;
453     }
454 
getFocusedApp()455     public String getFocusedApp() {
456         return mFocusedApp;
457     }
458 
getFocusedWindow()459     public String getFocusedWindow() {
460         return mFocusedWindow;
461     }
462 
463     /** @return Whether the home activity is the recents component. */
isHomeRecentsComponent()464     boolean isHomeRecentsComponent() {
465         if (mIsHomeRecentsComponent == null) {
466             computeState();
467         }
468         return mIsHomeRecentsComponent;
469     }
470 
getDisplay(int displayId)471     DisplayContent getDisplay(int displayId) {
472         for (DisplayContent display : mDisplays) {
473             if (display.mId == displayId) {
474                 return display;
475             }
476         }
477         return null;
478     }
479 
480     @Nullable
getTaskDisplayArea(ComponentName activityName)481     DisplayArea getTaskDisplayArea(ComponentName activityName) {
482         final List<DisplayArea> result = new ArrayList<>();
483         for (DisplayContent display : mDisplays) {
484             final DisplayArea tda = display.getTaskDisplayArea(activityName);
485             if (tda != null) {
486                 result.add(tda);
487             }
488         }
489         assertWithMessage("There must be exactly one activity among all TaskDisplayAreas.")
490                 .that(result.size()).isAtMost(1);
491 
492         return result.stream().findFirst().orElse(null);
493     }
494 
495     @Nullable
getDisplayArea(String windowName)496     DisplayArea getDisplayArea(String windowName) {
497         final List<DisplayArea> result = new ArrayList<>();
498         for (DisplayContent display : mDisplays) {
499             final DisplayArea da = display.getDisplayArea(windowName);
500             if (da != null) {
501                 result.add(da);
502             }
503         }
504         assertWithMessage("There must be exactly one window among all DisplayAreas.")
505                 .that(result.size()).isAtMost(1);
506 
507         return result.stream().findFirst().orElse(null);
508     }
509 
getFrontRootTaskId(int displayId)510     int getFrontRootTaskId(int displayId) {
511         return getDisplay(displayId).mRootTasks.get(0).mRootTaskId;
512     }
513 
getFrontStackActivityType(int displayId)514     public int getFrontStackActivityType(int displayId) {
515         return getDisplay(displayId).mRootTasks.get(0).getActivityType();
516     }
517 
getFrontStackWindowingMode(int displayId)518     public int getFrontStackWindowingMode(int displayId) {
519         return getDisplay(displayId).mRootTasks.get(0).getWindowingMode();
520     }
521 
getTopActivityName(int displayId)522     public String getTopActivityName(int displayId) {
523         if (!getDisplay(displayId).mRootTasks.isEmpty()) {
524             final ActivityTask topStack = getDisplay(displayId).mRootTasks.get(0);
525             final ActivityTask topTask = topStack.getTopTask();
526             if (!topTask.mActivities.isEmpty()) {
527                 return topTask.mActivities.get(0).name;
528             }
529         }
530         return null;
531     }
532 
getFocusedStackId()533     int getFocusedStackId() {
534         return mTopFocusedTaskId;
535     }
536 
getFocusedStackActivityType()537     public int getFocusedStackActivityType() {
538         final ActivityTask stack = getRootTask(mTopFocusedTaskId);
539         return stack != null ? stack.getActivityType() : ACTIVITY_TYPE_UNDEFINED;
540     }
541 
getFocusedStackWindowingMode()542     public int getFocusedStackWindowingMode() {
543         final ActivityTask stack = getRootTask(mTopFocusedTaskId);
544         return stack != null ? stack.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
545     }
546 
getFocusedActivity()547     public String getFocusedActivity() {
548         return mTopResumedActivityRecord;
549     }
550 
getResumedActivitiesCount()551     public int getResumedActivitiesCount() {
552         return mResumedActivitiesInStacks.size();
553     }
554 
getResumedActivitiesCountInPackage(String packageName)555     public int getResumedActivitiesCountInPackage(String packageName) {
556         final String componentPrefix = packageName + "/";
557         int count = 0;
558         for (int i = mDisplays.size() - 1; i >= 0; --i) {
559             final ArrayList<ActivityTask> mStacks = mDisplays.get(i).getRootTasks();
560             for (int j = mStacks.size() - 1; j >= 0; --j) {
561                 final String resumedActivity = mStacks.get(j).mResumedActivity;
562                 if (resumedActivity != null && resumedActivity.startsWith(componentPrefix)) {
563                     count++;
564                 }
565             }
566         }
567         return count;
568     }
569 
getResumedActivityOnDisplay(int displayId)570     public String getResumedActivityOnDisplay(int displayId) {
571         return getDisplay(displayId).mResumedActivity;
572     }
573 
getKeyguardControllerState()574     public KeyguardControllerState getKeyguardControllerState() {
575         return mKeyguardControllerState;
576     }
577 
containsStack(int windowingMode, int activityType)578     public boolean containsStack(int windowingMode, int activityType) {
579         return countStacks(windowingMode, activityType) > 0;
580     }
581 
countStacks(int windowingMode, int activityType)582     public int countStacks(int windowingMode, int activityType) {
583         int count = 0;
584         for (ActivityTask stack : mRootTasks) {
585             if (activityType != ACTIVITY_TYPE_UNDEFINED
586                     && activityType != stack.getActivityType()) {
587                 continue;
588             }
589             if (windowingMode != WINDOWING_MODE_UNDEFINED
590                     && windowingMode != stack.getWindowingMode()) {
591                 continue;
592             }
593             ++count;
594         }
595         return count;
596     }
597 
getRootTask(int taskId)598     public ActivityTask getRootTask(int taskId) {
599         for (ActivityTask stack : mRootTasks) {
600             if (taskId == stack.mRootTaskId) {
601                 return stack;
602             }
603         }
604         return null;
605     }
606 
getStackByActivityType(int activityType)607     public ActivityTask getStackByActivityType(int activityType) {
608         for (ActivityTask stack : mRootTasks) {
609             if (activityType == stack.getActivityType()) {
610                 return stack;
611             }
612         }
613         return null;
614     }
615 
getStandardStackByWindowingMode(int windowingMode)616     public ActivityTask getStandardStackByWindowingMode(int windowingMode) {
617         for (ActivityTask stack : mRootTasks) {
618             if (stack.getActivityType() != ACTIVITY_TYPE_STANDARD) {
619                 continue;
620             }
621             if (stack.getWindowingMode() == windowingMode) {
622                 return stack;
623             }
624         }
625         return null;
626     }
627 
getStandardTaskCountByWindowingMode(int windowingMode)628     public int getStandardTaskCountByWindowingMode(int windowingMode) {
629         int count = 0;
630         for (ActivityTask stack : mRootTasks) {
631             if (stack.getActivityType() != ACTIVITY_TYPE_STANDARD) {
632                 continue;
633             }
634             if (stack.getWindowingMode() == windowingMode) {
635                 count += stack.mTasks.isEmpty() ? 1 : stack.mTasks.size();
636             }
637         }
638         return count;
639     }
640 
641     /** Get the stack position on its display. */
getStackIndexByActivityType(int activityType)642     int getStackIndexByActivityType(int activityType) {
643         for (DisplayContent display : mDisplays) {
644             for (int i = 0; i < display.mRootTasks.size(); i++) {
645                 if (activityType == display.mRootTasks.get(i).getActivityType()) {
646                     return i;
647                 }
648             }
649         }
650         return -1;
651     }
652 
653     /** Get the stack on its display. */
getStackByActivity(ComponentName activityName)654     ActivityTask getStackByActivity(ComponentName activityName) {
655         for (DisplayContent display : mDisplays) {
656             for (int i = display.mRootTasks.size() - 1; i >= 0; --i) {
657                 final ActivityTask stack = display.mRootTasks.get(i);
658                 if (stack.containsActivity(activityName)) return stack;
659             }
660         }
661         return null;
662     }
663 
664     /** Get display id by activity on it. */
getDisplayByActivity(ComponentName activityComponent)665     public int getDisplayByActivity(ComponentName activityComponent) {
666         final ActivityTask task = getTaskByActivity(activityComponent);
667         if (task == null) {
668             return -1;
669         }
670         return getRootTask(task.mRootTaskId).mDisplayId;
671     }
672 
getDisplays()673     List<DisplayContent> getDisplays() {
674         return new ArrayList<>(mDisplays);
675     }
676 
getRootTasks()677     public List<ActivityTask> getRootTasks() {
678         return new ArrayList<>(mRootTasks);
679     }
680 
getStackCount()681     public int getStackCount() {
682         return mRootTasks.size();
683     }
684 
getDisplayCount()685     public int getDisplayCount() {
686         return mDisplays.size();
687     }
688 
containsActivity(ComponentName activityName)689     public boolean containsActivity(ComponentName activityName) {
690         for (ActivityTask stack : mRootTasks) {
691             if (stack.containsActivity(activityName)) return true;
692         }
693         return false;
694     }
695 
containsNoneOf(Iterable<ComponentName> activityNames)696     public boolean containsNoneOf(Iterable<ComponentName> activityNames) {
697         for (ComponentName activityName : activityNames) {
698             for (ActivityTask stack : mRootTasks) {
699                 if (stack.containsActivity(activityName)) return false;
700             }
701         }
702         return true;
703     }
704 
containsActivityInWindowingMode(ComponentName activityName, int windowingMode)705     public boolean containsActivityInWindowingMode(ComponentName activityName, int windowingMode) {
706         for (ActivityTask stack : mRootTasks) {
707             final Activity activity = stack.getActivity(activityName);
708             if (activity != null && activity.getWindowingMode() == windowingMode) {
709                 return true;
710             }
711         }
712         return false;
713     }
714 
isActivityVisible(ComponentName activityName)715     public boolean isActivityVisible(ComponentName activityName) {
716         for (ActivityTask stack : mRootTasks) {
717             final Activity activity = stack.getActivity(activityName);
718             if (activity != null) return activity.visible;
719         }
720         return false;
721     }
722 
isActivityTranslucent(ComponentName activityName)723     public boolean isActivityTranslucent(ComponentName activityName) {
724         for (ActivityTask stack : mRootTasks) {
725             final Activity activity = stack.getActivity(activityName);
726             if (activity != null) return activity.translucent;
727         }
728         return false;
729     }
730 
isBehindOpaqueActivities(ComponentName activityName)731     public boolean isBehindOpaqueActivities(ComponentName activityName) {
732         final String fullName = getActivityName(activityName);
733         for (ActivityTask stack : mRootTasks) {
734             final Activity activity =
735                     stack.getActivity((a) -> a.name.equals(fullName) || !a.translucent);
736             if (activity != null) {
737                 if (activity.name.equals(fullName)) {
738                     return false;
739                 }
740                 if (!activity.translucent) {
741                     return true;
742                 }
743             }
744         }
745 
746         return false;
747     }
748 
containsStartedActivities()749     public boolean containsStartedActivities() {
750         for (ActivityTask stack : mRootTasks) {
751             final Activity activity = stack.getActivity(
752                     (a) -> !a.state.equals(STATE_STOPPED) && !a.state.equals(STATE_DESTROYED));
753             if (activity != null) return true;
754         }
755         return false;
756     }
757 
hasActivityState(ComponentName activityName, String activityState)758     boolean hasActivityState(ComponentName activityName, String activityState) {
759         for (ActivityTask stack : mRootTasks) {
760             final Activity activity = stack.getActivity(activityName);
761             if (activity != null) return activity.state.equals(activityState);
762         }
763         return false;
764     }
765 
getActivityProcId(ComponentName activityName)766     int getActivityProcId(ComponentName activityName) {
767         for (ActivityTask stack : mRootTasks) {
768             final Activity activity = stack.getActivity(activityName);
769             if (activity != null) return activity.procId;
770         }
771         return -1;
772     }
773 
isRecentsActivityVisible()774     boolean isRecentsActivityVisible() {
775         final Activity recentsActivity = getRecentsActivity();
776         return recentsActivity != null && recentsActivity.visible;
777     }
778 
getHomeActivityName()779     ComponentName getHomeActivityName() {
780         Activity activity = getHomeActivity();
781         if (activity == null) {
782             return null;
783         }
784         return ComponentName.unflattenFromString(activity.name);
785     }
786 
getDreamTask()787     ActivityTask getDreamTask() {
788         final ActivityTask dreamStack = getStackByActivityType(ACTIVITY_TYPE_DREAM);
789         if (dreamStack != null) {
790             return dreamStack.getTopTask();
791         }
792         return null;
793     }
794 
getHomeTask()795     ActivityTask getHomeTask() {
796         final ActivityTask homeStack = getStackByActivityType(ACTIVITY_TYPE_HOME);
797         if (homeStack != null) {
798             return homeStack.getTopTask();
799         }
800         return null;
801     }
802 
getRecentsTask()803     private ActivityTask getRecentsTask() {
804         final ActivityTask recentsStack = getStackByActivityType(ACTIVITY_TYPE_RECENTS);
805         if (recentsStack != null) {
806             return recentsStack.getTopTask();
807         }
808         return null;
809     }
810 
getHomeActivity()811     private Activity getHomeActivity() {
812         final ActivityTask homeTask = getHomeTask();
813         return homeTask != null ? homeTask.mActivities.get(homeTask.mActivities.size() - 1) : null;
814     }
815 
getRecentsActivity()816     private Activity getRecentsActivity() {
817         final ActivityTask recentsTask = getRecentsTask();
818         return recentsTask != null ? recentsTask.mActivities.get(recentsTask.mActivities.size() - 1)
819                 : null;
820     }
821 
getRootTaskIdByActivity(ComponentName activityName)822     public int getRootTaskIdByActivity(ComponentName activityName) {
823         final ActivityTask task = getTaskByActivity(activityName);
824         return  (task == null) ? INVALID_STACK_ID : task.mRootTaskId;
825     }
826 
getTaskByActivity(ComponentName activityName)827     public ActivityTask getTaskByActivity(ComponentName activityName) {
828         return getTaskByActivity(
829                 activityName, WINDOWING_MODE_UNDEFINED, new int[]{ INVALID_TASK_ID });
830     }
831 
getTaskByActivity(ComponentName activityName, int[] excludeTaskIds)832     public ActivityTask getTaskByActivity(ComponentName activityName, int[] excludeTaskIds) {
833         return getTaskByActivity(activityName, WINDOWING_MODE_UNDEFINED, excludeTaskIds);
834     }
835 
getTaskByActivity(ComponentName activityName, int windowingMode, int[] excludeTaskIds)836     private ActivityTask getTaskByActivity(ComponentName activityName, int windowingMode,
837             int[] excludeTaskIds) {
838         Activity activity = getActivity(activityName, windowingMode, excludeTaskIds);
839         return activity == null ? null : activity.task;
840     }
841 
getActivity(ComponentName activityName)842     public Activity getActivity(ComponentName activityName) {
843         return getActivity(activityName, WINDOWING_MODE_UNDEFINED, new int[]{ INVALID_TASK_ID });
844     }
845 
getActivity(ComponentName activityName, int windowingMode, int[] excludeTaskIds)846     private Activity getActivity(ComponentName activityName, int windowingMode,
847             int[] excludeTaskIds) {
848         for (ActivityTask stack : mRootTasks) {
849             if (windowingMode == WINDOWING_MODE_UNDEFINED
850                     || windowingMode == stack.getWindowingMode()) {
851                 Activity activity = stack.getActivity(activityName, excludeTaskIds);
852                 if (activity != null) return activity;
853             }
854         }
855         return null;
856     }
857 
858     /**
859      * Get the number of activities in the task, with the option to count only activities with
860      * specific name.
861      * @param taskId Id of the task where we're looking for the number of activities.
862      * @param activityName Optional name of the activity we're interested in.
863      * @return Number of all activities in the task if activityName is {@code null}, otherwise will
864      *         report number of activities that have specified name.
865      */
getActivityCountInTask(int taskId, @Nullable ComponentName activityName)866     public int getActivityCountInTask(int taskId, @Nullable ComponentName activityName) {
867         // If activityName is null, count all activities in the task.
868         // Otherwise count activities that have specified name.
869         for (ActivityTask stack : mRootTasks) {
870             final ActivityTask task = stack.getTask(taskId);
871             if (task == null) continue;
872 
873             if (activityName == null) {
874                 return task.mActivities.size();
875             }
876             final String fullName = getActivityName(activityName);
877             int count = 0;
878             for (Activity activity : task.mActivities) {
879                 if (activity.name.equals(fullName)) {
880                     count++;
881                 }
882             }
883             return count;
884         }
885         return 0;
886     }
887 
getRootTasksCount()888     public int getRootTasksCount() {
889         return mRootTasks.size();
890     }
891 
getRootTasksCount(int displayId)892     public int getRootTasksCount(int displayId) {
893         return getRootTasksCount(t -> t.mDisplayId == displayId);
894     }
895 
896     /**
897      * Count root tasks filtered by the predicate passed as argument.
898      */
getRootTasksCount(Predicate<? super ActivityTask> predicate)899     public int getRootTasksCount(Predicate<? super ActivityTask> predicate) {
900         return (int) mRootTasks.stream().filter(predicate).count();
901     }
902 
pendingActivityContain(ComponentName activityName)903     boolean pendingActivityContain(ComponentName activityName) {
904         return mPendingActivities.contains(getActivityName(activityName));
905     }
906 
907     // Get the logical display size of the default display.
getLogicalDisplaySize()908     public static Point getLogicalDisplaySize() {
909         WindowManagerState mWmState = new WindowManagerState();
910         mWmState.computeState();
911         Rect size = mWmState.getDisplay(DEFAULT_DISPLAY).getDisplayRect();
912         return new Point(size.width(), size.height());
913     }
914 
getDefaultDisplayLastTransition()915     String getDefaultDisplayLastTransition() {
916         return getDisplay(DEFAULT_DISPLAY).getLastTransition();
917     }
918 
getDefaultDisplayAppTransitionState()919     String getDefaultDisplayAppTransitionState() {
920         return getDisplay(DEFAULT_DISPLAY).getAppTransitionState();
921     }
922 
getMatchingVisibleWindowState(final String windowName)923     public List<WindowState> getMatchingVisibleWindowState(final String windowName) {
924         return getMatchingWindows(ws -> ws.isSurfaceShown() && windowName.equals(ws.getName()))
925                 .collect(Collectors.toList());
926     }
927 
getMatchingWindows(Predicate<WindowState> condition)928     private Stream<WindowState> getMatchingWindows(Predicate<WindowState> condition) {
929         return mWindowStates.stream().filter(condition);
930     }
931 
932     @Nullable
getWindowByPackageName(String packageName, int windowType)933     public WindowState getWindowByPackageName(String packageName, int windowType) {
934         final List<WindowState> windowList = getWindowsByPackageName(packageName, windowType);
935         return windowList.isEmpty() ? null : windowList.get(0);
936     }
937 
getWindowsByPackageName(String packageName, int... restrictToTypes)938     public List<WindowState> getWindowsByPackageName(String packageName, int... restrictToTypes) {
939         return getMatchingWindows(ws ->
940                 (ws.getName().equals(packageName) || ws.getName().startsWith(packageName + "/"))
941                         && Arrays.stream(restrictToTypes).anyMatch(type -> type == ws.getType()))
942                 .collect(Collectors.toList());
943     }
944 
hasNotificationShade()945     public boolean hasNotificationShade() {
946         computeState();
947         return !getMatchingWindowType(TYPE_NOTIFICATION_SHADE).isEmpty();
948     }
949 
getWindows()950     List<WindowState> getWindows() {
951         return new ArrayList<>(mWindowStates);
952     }
953 
getMatchingWindowType(int type)954     List<WindowState> getMatchingWindowType(int type) {
955         return getMatchingWindows(ws -> type == ws.mType).collect(Collectors.toList());
956     }
957 
getMatchingWindowTokens(final String windowName)958     List<String> getMatchingWindowTokens(final String windowName) {
959         return getMatchingWindows(ws -> windowName.equals(ws.getName()))
960                 .map(WindowState::getToken)
961                 .collect(Collectors.toList());
962     }
963 
getAllNavigationBarStates()964     List<WindowState> getAllNavigationBarStates() {
965         return getMatchingWindows(WindowManagerState::isValidNavBarType)
966                 .collect(Collectors.toList());
967     }
968 
getAndAssertSingleNavBarWindowOnDisplay(int displayId)969     WindowState getAndAssertSingleNavBarWindowOnDisplay(int displayId) {
970         List<WindowState> navWindow = getMatchingWindows(ws ->
971                 WindowManagerState.isValidNavBarType(ws) && ws.getDisplayId() == displayId)
972                 .collect(Collectors.toList());
973 
974         // We may need some time to wait for nav bar showing.
975         // It's Ok to get 0 nav bar here.
976         assertTrue("There should be at most one navigation bar on a display",
977                 navWindow.size() <= 1);
978 
979         return navWindow.isEmpty() ? null : navWindow.get(0);
980     }
981 
getWindowStateForAppToken(String appToken)982     WindowState getWindowStateForAppToken(String appToken) {
983         return getMatchingWindows(ws -> ws.getToken().equals(appToken))
984                 .findFirst()
985                 .orElse(null);
986     }
987 
getFrontWindow()988     String getFrontWindow() {
989         if (mWindowStates == null || mWindowStates.isEmpty()) {
990             return null;
991         }
992         return mWindowStates.get(0).getName();
993     }
994 
995     /** Check if there exists a window record with matching windowName. */
containsWindow(String windowName)996     public boolean containsWindow(String windowName) {
997         for (WindowState window : mWindowStates) {
998             if (window.getName().equals(windowName)) {
999                 return true;
1000             }
1001         }
1002         return false;
1003     }
1004 
1005     /** Check if at least one window which matches the specified name has shown it's surface. */
isWindowSurfaceShown(String windowName)1006     public boolean isWindowSurfaceShown(String windowName) {
1007         for (WindowState window : mWindowStates) {
1008             if (window.getName().equals(windowName)) {
1009                 if (window.isSurfaceShown()) {
1010                     return true;
1011                 }
1012             }
1013         }
1014         return false;
1015     }
1016 
1017     /** Check if at least one window which matches provided window name is visible. */
isWindowVisible(String windowName)1018     public boolean isWindowVisible(String windowName) {
1019         for (WindowState window : mWindowStates) {
1020             if (window.getName().equals(windowName)) {
1021                 if (window.isVisible()) {
1022                     return true;
1023                 }
1024             }
1025         }
1026         return false;
1027     }
1028 
allWindowSurfacesShown(String windowName)1029     public boolean allWindowSurfacesShown(String windowName) {
1030         boolean allShown = false;
1031         for (WindowState window : mWindowStates) {
1032             if (window.getName().equals(windowName)) {
1033                 if (!window.isSurfaceShown()) {
1034                     log("[VISIBLE] not visible" + windowName);
1035                     return false;
1036                 }
1037                 log("[VISIBLE] visible" + windowName);
1038                 allShown = true;
1039             }
1040         }
1041         return allShown;
1042     }
1043 
1044     /** Checks whether the display contains the given activity. */
hasActivityInDisplay(int displayId, ComponentName activityName)1045     boolean hasActivityInDisplay(int displayId, ComponentName activityName) {
1046         for (WindowManagerState.ActivityTask stack : getDisplay(displayId).getRootTasks()) {
1047             if (stack.containsActivity(activityName)) {
1048                 return true;
1049             }
1050         }
1051         return false;
1052     }
1053 
findFirstWindowWithType(int type)1054     WindowState findFirstWindowWithType(int type) {
1055         for (WindowState window : mWindowStates) {
1056             if (window.getType() == type) {
1057                 return window;
1058             }
1059         }
1060         return null;
1061     }
1062 
getZOrder(WindowState w)1063     public int getZOrder(WindowState w) {
1064         return mWindowStates.size() - mWindowStates.indexOf(w);
1065     }
1066 
getStandardRootTaskByWindowingMode(int windowingMode)1067     ActivityTask getStandardRootTaskByWindowingMode(int windowingMode) {
1068         for (ActivityTask task : mRootTasks) {
1069             if (task.getActivityType() != ACTIVITY_TYPE_STANDARD) {
1070                 continue;
1071             }
1072             if (task.getWindowingMode() == windowingMode) {
1073                 return task;
1074             }
1075         }
1076         return null;
1077     }
1078 
getInputMethodWindowState()1079     WindowManagerState.WindowState getInputMethodWindowState() {
1080         return getWindowStateForAppToken(mInputMethodWindowAppToken);
1081     }
1082 
isDisplayFrozen()1083     public boolean isDisplayFrozen() {
1084         return mDisplayFrozen;
1085     }
1086 
getRotation()1087     public int getRotation() {
1088         return getDisplay(DEFAULT_DISPLAY).mRotation;
1089     }
1090 
getLastOrientation()1091     public int getLastOrientation() {
1092         return getDisplay(DEFAULT_DISPLAY).mLastOrientation;
1093     }
1094 
getFocusedDisplayId()1095     public int getFocusedDisplayId() {
1096         return mFocusedDisplayId;
1097     }
1098 
1099     public static class DisplayContent extends DisplayArea {
1100         public int mId;
1101         ArrayList<ActivityTask> mRootTasks = new ArrayList<>();
1102         int mFocusedRootTaskId;
1103         String mResumedActivity;
1104         boolean mSingleTaskInstance;
1105         Rect mDefaultPinnedStackBounds = null;
1106         Rect mPinnedStackMovementBounds = null;
1107 
1108         private Rect mDisplayRect = new Rect();
1109         private Rect mAppRect = new Rect();
1110         private int mDpi;
1111         private int mFlags;
1112         private String mName;
1113         private int mSurfaceSize;
1114         private String mFocusedApp;
1115         private String mLastTransition;
1116         private String mAppTransitionState;
1117         private int mRotation;
1118         private boolean mFrozenToUserRotation;
1119         private int mUserRotation;
1120         private int mFixedToUserRotationMode;
1121         private int mLastOrientation;
1122 
DisplayContent(DisplayContentProto proto)1123         DisplayContent(DisplayContentProto proto) {
1124             super(proto.rootDisplayArea);
1125             mId = proto.id;
1126             mFocusedRootTaskId = proto.focusedRootTaskId;
1127             mSingleTaskInstance = proto.singleTaskInstance;
1128             if (proto.resumedActivity != null) {
1129                 mResumedActivity = proto.resumedActivity.title;
1130             }
1131             addRootTasks();
1132 
1133             mDpi = proto.dpi;
1134             DisplayInfoProto infoProto = proto.displayInfo;
1135             if (infoProto != null) {
1136                 mDisplayRect.set(0, 0, infoProto.logicalWidth, infoProto.logicalHeight);
1137                 mAppRect.set(0, 0, infoProto.appWidth, infoProto.appHeight);
1138                 mName = infoProto.name;
1139                 mFlags = infoProto.flags;
1140             }
1141             final DisplayFramesProto displayFramesProto = proto.displayFrames;
1142             mSurfaceSize = proto.surfaceSize;
1143             mFocusedApp = proto.focusedApp;
1144 
1145             final AppTransitionProto appTransitionProto = proto.appTransition;
1146             int appState = 0;
1147             int lastTransition = 0;
1148             if (appTransitionProto != null) {
1149                 appState = appTransitionProto.appTransitionState;
1150                 lastTransition = appTransitionProto.lastUsedAppTransition;
1151             }
1152             mAppTransitionState = appStateToString(appState);
1153             mLastTransition = appTransitionToString(lastTransition);
1154 
1155             PinnedTaskControllerProto pinnedTaskProto = proto.pinnedTaskController;
1156             if (pinnedTaskProto != null) {
1157                 mDefaultPinnedStackBounds = extract(pinnedTaskProto.defaultBounds);
1158                 mPinnedStackMovementBounds = extract(pinnedTaskProto.movementBounds);
1159             }
1160 
1161             final DisplayRotationProto rotationProto = proto.displayRotation;
1162             if (rotationProto != null) {
1163                 mRotation = rotationProto.rotation;
1164                 mFrozenToUserRotation = rotationProto.frozenToUserRotation;
1165                 mUserRotation = rotationProto.userRotation;
1166                 mFixedToUserRotationMode = rotationProto.fixedToUserRotationMode;
1167                 mLastOrientation = rotationProto.lastOrientation;
1168             }
1169         }
1170 
getName()1171         public String getName() {
1172             return mName;
1173         }
1174 
addRootTasks()1175         private void addRootTasks() {
1176             // TODO(b/149338177): figure out how CTS tests deal with organizer. For now,
1177             //                    don't treat them as regular stacks
1178             collectDescendantsOfTypeIf(ActivityTask.class, t -> t.isRootTask(), this,
1179                     mRootTasks);
1180             ArrayList<ActivityTask> rootOrganizedTasks = new ArrayList<>();
1181             for (int i = mRootTasks.size() -1; i >= 0; --i) {
1182                 final ActivityTask task = mRootTasks.get(i);
1183                 // Skip tasks created by an organizer
1184                 if (task.mCreatedByOrganizer) {
1185                     mRootTasks.remove(task);
1186                     rootOrganizedTasks.add(task);
1187                 }
1188             }
1189             // Add root tasks controlled by an organizer
1190             while (rootOrganizedTasks.size() > 0) {
1191                 final ActivityTask task = rootOrganizedTasks.remove(0);
1192                 for (int i = task.mChildren.size() - 1; i >= 0; i--) {
1193                     final ActivityTask child = (ActivityTask) task.mChildren.get(i);
1194                     if (!child.mCreatedByOrganizer) {
1195                         mRootTasks.add(child);
1196                     } else {
1197                         rootOrganizedTasks.add(child);
1198                     }
1199                 }
1200             }
1201         }
1202 
containsActivity(ComponentName activityName)1203         boolean containsActivity(ComponentName activityName) {
1204             for (ActivityTask task : mRootTasks) {
1205                 if (task.containsActivity(activityName)) return true;
1206             }
1207             return false;
1208         }
1209 
getAllTaskDisplayAreas()1210         List<DisplayArea> getAllTaskDisplayAreas() {
1211             final List<DisplayArea> taskDisplayAreas = new ArrayList<>();
1212             collectDescendantsOfTypeIf(DisplayArea.class, DisplayArea::isTaskDisplayArea, this,
1213                     taskDisplayAreas);
1214             return taskDisplayAreas;
1215         }
1216 
1217         @Nullable
getTaskDisplayArea(ComponentName activityName)1218         DisplayArea getTaskDisplayArea(ComponentName activityName) {
1219             final List<DisplayArea> taskDisplayAreas = getAllTaskDisplayAreas();
1220             List<DisplayArea> result = taskDisplayAreas.stream().filter(
1221                     tda -> tda.containsActivity(activityName))
1222                     .collect(Collectors.toList());
1223 
1224             assertWithMessage("There must be exactly one activity among all TaskDisplayAreas.")
1225                     .that(result.size()).isAtMost(1);
1226 
1227             return result.stream().findFirst().orElse(null);
1228         }
1229 
getAllChildDisplayAreas()1230         List<DisplayArea> getAllChildDisplayAreas() {
1231             final List<DisplayArea> displayAreas = new ArrayList<>();
1232             collectDescendantsOfType(DisplayArea.class,this, displayAreas);
1233             return displayAreas;
1234         }
1235 
1236         @Nullable
getDisplayArea(String windowName)1237         DisplayArea getDisplayArea(String windowName) {
1238             List<DisplayArea> displayAreas = new ArrayList<>();
1239             final Predicate<DisplayArea> p = da -> {
1240                 final boolean containsChildWindowToken = !da.mChildren.isEmpty()
1241                         && da.mChildren.get(0) instanceof WindowToken;
1242                 return !da.isTaskDisplayArea() && containsChildWindowToken;
1243             };
1244             collectDescendantsOfTypeIf(DisplayArea.class, p, this, displayAreas);
1245             List<DisplayArea> result = displayAreas.stream().filter(
1246                     da -> da.containsWindow(windowName))
1247                     .collect(Collectors.toList());
1248 
1249             assertWithMessage("There must be exactly one window among all DisplayAreas.")
1250                     .that(result.size()).isAtMost(1);
1251 
1252             return result.stream().findFirst().orElse(null);
1253         }
1254 
getRootTasks()1255         ArrayList<ActivityTask> getRootTasks() {
1256             return mRootTasks;
1257         }
1258 
getDpi()1259         int getDpi() {
1260             return mDpi;
1261         }
1262 
getDisplayRect()1263         Rect getDisplayRect() {
1264             return mDisplayRect;
1265         }
1266 
getFlags()1267         int getFlags() {
1268             return mFlags;
1269         }
1270 
getSurfaceSize()1271         int getSurfaceSize() {
1272             return mSurfaceSize;
1273         }
1274 
getFocusedApp()1275         String getFocusedApp() {
1276             return mFocusedApp;
1277         }
1278 
getLastTransition()1279         String getLastTransition() { return mLastTransition; }
1280 
getAppTransitionState()1281         String getAppTransitionState() { return mAppTransitionState; }
1282 
1283         @Override
toString()1284         public String toString() {
1285             return "Display #" + mId + ": name=" + mName + " mDisplayRect=" + mDisplayRect
1286                     + " mAppRect=" + mAppRect + " mFlags=" + mFlags;
1287         }
1288     }
1289 
1290     public static class ActivityTask extends ActivityContainer {
1291 
1292         int mTaskId;
1293         int mRootTaskId;
1294         public int mDisplayId;
1295         Rect mLastNonFullscreenBounds;
1296         String mRealActivity;
1297         String mOrigActivity;
1298         ArrayList<ActivityTask> mTasks = new ArrayList<>();
1299         ArrayList<Activity> mActivities = new ArrayList<>();
1300         int mTaskType;
1301         private int mResizeMode;
1302         String mResumedActivity;
1303         boolean mAnimatingBounds;
1304         private int mSurfaceWidth;
1305         private int mSurfaceHeight;
1306         boolean mCreatedByOrganizer;
1307         String mAffinity;
1308         boolean mHasChildPipActivity;
1309 
ActivityTask(TaskProto proto)1310         ActivityTask(TaskProto proto) {
1311             super(proto.windowContainer);
1312             mTaskId = proto.id;
1313             mRootTaskId = proto.rootTaskId;
1314             mDisplayId = proto.displayId;
1315             mLastNonFullscreenBounds = extract(proto.lastNonFullscreenBounds);
1316             mRealActivity = proto.realActivity;
1317             mOrigActivity = proto.origActivity;
1318             mTaskType = proto.activityType;
1319             mResizeMode = proto.resizeMode;
1320             mFullscreen = proto.fillsParent;
1321             mBounds = extract(proto.bounds);
1322             mMinWidth = proto.minWidth;
1323             mMinHeight = proto.minHeight;
1324             mAnimatingBounds = proto.animatingBounds;
1325             mSurfaceWidth = proto.surfaceWidth;
1326             mSurfaceHeight = proto.surfaceHeight;
1327             mCreatedByOrganizer = proto.createdByOrganizer;
1328             mAffinity = proto.affinity;
1329             mHasChildPipActivity = proto.hasChildPipActivity;
1330 
1331             if (proto.resumedActivity != null) {
1332                 mResumedActivity = proto.resumedActivity.title;
1333             }
1334 
1335             collectChildrenOfType(ActivityTask.class, this, mTasks);
1336             collectChildrenOfType(Activity.class, this, mActivities);
1337         }
1338 
isEmpty()1339         boolean isEmpty() {
1340             return mTasks.isEmpty() && mActivities.isEmpty();
1341         }
1342 
getResizeMode()1343         public int getResizeMode() {
1344             return mResizeMode;
1345         }
1346 
getTaskId()1347         public int getTaskId() {
1348             return mTaskId;
1349         }
isRootTask()1350         boolean isRootTask() {
1351             return mTaskId == mRootTaskId;
1352         }
1353 
isLeafTask()1354         boolean isLeafTask() {
1355             return mTasks.size() == 0;
1356         }
1357 
getRootTaskId()1358         public int getRootTaskId() {
1359             return mRootTaskId;
1360         }
1361 
getSurfaceWidth()1362         int getSurfaceWidth() {
1363             return mSurfaceWidth;
1364         }
1365 
getSurfaceHeight()1366         int getSurfaceHeight() {
1367             return mSurfaceHeight;
1368         }
1369 
getActivities()1370         public ArrayList<Activity> getActivities() {
1371             return mActivities;
1372         }
1373 
1374         /** @return the top task in the stack. */
getTopTask()1375         ActivityTask getTopTask() {
1376             // NOTE: Unlike the WindowManager internals, we dump the state from top to bottom,
1377             //       so the indices are inverted
1378             return getTask((t) -> true);
1379         }
1380 
getResumedActivity()1381         public String getResumedActivity() {
1382             return mResumedActivity;
1383         }
1384 
getTasks()1385         public List<ActivityTask> getTasks() {
1386             return new ArrayList<>(mTasks);
1387         }
1388 
getTask(Predicate<ActivityTask> predicate)1389         ActivityTask getTask(Predicate<ActivityTask> predicate) {
1390             for (ActivityTask task : mTasks) {
1391                 if (predicate.test(task)) return task;
1392             }
1393             return predicate.test(this) ? this : null;
1394         }
1395 
getTask(int taskId)1396         ActivityTask getTask(int taskId) {
1397             return getTask((t) -> t.mTaskId == taskId);
1398         }
1399 
forAllTasks(Consumer<ActivityTask> consumer)1400         void forAllTasks(Consumer<ActivityTask> consumer) {
1401             for (ActivityTask task : mTasks) {
1402                 consumer.accept(task);
1403             }
1404             consumer.accept(this);
1405         }
1406 
getActivity(Predicate<Activity> predicate)1407         Activity getActivity(Predicate<Activity> predicate) {
1408             for (Activity activity : mActivities) {
1409                 if (predicate.test(activity)) return activity;
1410             }
1411             for (ActivityTask task : mTasks) {
1412                 final Activity activity = task.getActivity(predicate);
1413                 if (activity != null) return activity;
1414             }
1415             return null;
1416         }
1417 
getActivity(ComponentName activityName)1418         public Activity getActivity(ComponentName activityName) {
1419             final String fullName = getActivityName(activityName);
1420             return getActivity((activity) -> activity.name.equals(fullName));
1421         }
1422 
getActivity(ComponentName activityName, int[] excludeTaskIds)1423         public Activity getActivity(ComponentName activityName, int[] excludeTaskIds) {
1424             final String fullName = getActivityName(activityName);
1425             return getActivity((activity) -> {
1426                 if (!activity.name.equals(fullName)) {
1427                     return false;
1428                 }
1429                 for (int excludeTaskId : excludeTaskIds) {
1430                     if (activity.task.mTaskId == excludeTaskId) {
1431                         return false;
1432                     }
1433                 }
1434                 return true;
1435             });
1436         }
1437 
containsActivity(ComponentName activityName)1438         boolean containsActivity(ComponentName activityName) {
1439             return getActivity(activityName) != null;
1440         }
1441 
1442         @Override
getActivityType()1443         int getActivityType() {
1444             return mTaskType;
1445         }
1446     }
1447 
1448     public static class Activity extends ActivityContainer {
1449 
1450         String name;
1451         String state;
1452         boolean visible;
1453         boolean frontOfTask;
1454         boolean inSizeCompatMode;
1455         int procId = -1;
1456         public boolean translucent;
1457         ActivityTask task;
1458 
1459         Activity(ActivityRecordProto proto, WindowContainer parent) {
1460             super(proto.windowToken.windowContainer);
1461             task = (ActivityTask) parent;
1462             name = proto.name;
1463             state = proto.state;
1464             visible = proto.visible;
1465             frontOfTask = proto.frontOfTask;
1466             inSizeCompatMode = proto.inSizeCompatMode;
1467             if (proto.procId != 0) {
1468                 procId = proto.procId;
1469             }
1470             translucent = proto.translucent;
1471         }
1472 
1473         public String getName() {
1474             return name;
1475         }
1476 
1477         public String getState() {
1478             return state;
1479         }
1480 
1481         public boolean inSizeCompatMode() {
1482             return inSizeCompatMode;
1483         }
1484 
1485         @Override
1486         public Rect getBounds() {
1487             if (mBounds == null) {
1488                 return mFullConfiguration.windowConfiguration.getBounds();
1489             }
1490             return mBounds;
1491         }
1492 
1493         public Rect getMaxBounds() {
1494             return mFullConfiguration.windowConfiguration.getMaxBounds();
1495         }
1496 
1497         public Rect getAppBounds() {
1498             return mFullConfiguration.windowConfiguration.getAppBounds();
1499         }
1500     }
1501 
1502     static abstract class ActivityContainer extends WindowContainer {
1503         protected boolean mFullscreen;
1504         protected Rect mBounds;
1505         protected int mMinWidth = -1;
1506         protected int mMinHeight = -1;
1507 
1508         ActivityContainer(WindowContainerProto proto) {
1509             super(proto);
1510         }
1511 
1512         public Rect getBounds() {
1513             return mBounds;
1514         }
1515 
1516         boolean isFullscreen() {
1517             return mFullscreen;
1518         }
1519 
1520         int getMinWidth() {
1521             return mMinWidth;
1522         }
1523 
1524         int getMinHeight() {
1525             return mMinHeight;
1526         }
1527     }
1528 
1529     static class KeyguardControllerState {
1530 
1531         boolean aodShowing = false;
1532         boolean keyguardShowing = false;
1533         SparseArray<Boolean> mKeyguardOccludedStates = new SparseArray<>();
1534 
1535         KeyguardControllerState(KeyguardControllerProto proto) {
1536             if (proto != null) {
1537                 aodShowing = proto.aodShowing;
1538                 keyguardShowing = proto.keyguardShowing;
1539                 for (int i = 0;  i < proto.keyguardOccludedStates.length; i++) {
1540                     mKeyguardOccludedStates.append(proto.keyguardOccludedStates[i].displayId,
1541                             proto.keyguardOccludedStates[i].keyguardOccluded);
1542                 }
1543             }
1544         }
1545 
1546         boolean isKeyguardOccluded(int displayId) {
1547             if (mKeyguardOccludedStates.get(displayId) != null) {
1548                 return mKeyguardOccludedStates.get(displayId);
1549             }
1550             return false;
1551         }
1552     }
1553 
1554     static class ConfigurationContainer {
1555         final Configuration mOverrideConfiguration = new Configuration();
1556         final Configuration mFullConfiguration = new Configuration();
1557         final Configuration mMergedOverrideConfiguration = new Configuration();
1558 
1559         ConfigurationContainer(ConfigurationContainerProto proto) {
1560             if (proto == null) {
1561                 return;
1562             }
1563             mOverrideConfiguration.setTo(extract(proto.overrideConfiguration));
1564             mFullConfiguration.setTo(extract(proto.fullConfiguration));
1565             mMergedOverrideConfiguration.setTo(extract(proto.mergedOverrideConfiguration));
1566         }
1567 
1568         boolean isWindowingModeCompatible(int requestedWindowingMode) {
1569             if (requestedWindowingMode == WINDOWING_MODE_UNDEFINED) {
1570                 return true;
1571             }
1572             return getWindowingMode() == requestedWindowingMode;
1573         }
1574 
1575         public int getWindowingMode() {
1576             if (mFullConfiguration == null) {
1577                 return WINDOWING_MODE_UNDEFINED;
1578             }
1579             return mFullConfiguration.windowConfiguration.getWindowingMode();
1580         }
1581 
1582         int getActivityType() {
1583             if (mFullConfiguration == null) {
1584                 return ACTIVITY_TYPE_UNDEFINED;
1585             }
1586             return mFullConfiguration.windowConfiguration.getActivityType();
1587         }
1588     }
1589 
1590     public static class RootWindowContainer extends WindowContainer {
1591         RootWindowContainer(RootWindowContainerProto proto) {
1592             super(proto.windowContainer);
1593         }
1594     }
1595     public static class DisplayArea extends WindowContainer {
1596         private final boolean mIsTaskDisplayArea;
1597         private final boolean mIsRootDisplayArea;
1598         private final int mFeatureId;
1599         private final boolean mIsOrganized;
1600         private ArrayList<Activity> mActivities;
1601         private final ArrayList<WindowState> mWindows = new ArrayList<>();
1602 
1603         DisplayArea(DisplayAreaProto proto) {
1604             super(proto.windowContainer);
1605             mIsTaskDisplayArea = proto.isTaskDisplayArea;
1606             mIsRootDisplayArea = proto.isRootDisplayArea;
1607             mFeatureId = proto.featureId;
1608             mIsOrganized = proto.isOrganized;
1609             if (mIsTaskDisplayArea) {
1610                 mActivities = new ArrayList<>();
1611                 collectDescendantsOfType(Activity.class, this, mActivities);
1612             }
1613             collectDescendantsOfType(WindowState.class, this, mWindows);
1614         }
1615 
1616         boolean isTaskDisplayArea() {
1617             return mIsTaskDisplayArea;
1618         }
1619 
1620         boolean isRootDisplayArea() {
1621             return mIsRootDisplayArea;
1622         }
1623 
1624         int getFeatureId() {
1625             return mFeatureId;
1626         }
1627 
1628         boolean isOrganized() {
1629             return mIsOrganized;
1630         }
1631 
1632         @Override
1633         public Rect getBounds() {
1634             if (mBounds == null) {
1635                 return mFullConfiguration.windowConfiguration.getBounds();
1636             }
1637             return mBounds;
1638         }
1639 
1640         boolean containsActivity(ComponentName activityName) {
1641             if (!mIsTaskDisplayArea) {
1642                 return false;
1643             }
1644 
1645             final String fullName = getActivityName(activityName);
1646             for (Activity a : mActivities) {
1647                 if (a.name.equals(fullName)) {
1648                     return true;
1649                 }
1650             }
1651             return false;
1652         }
1653 
1654         boolean containsWindow(String windowName) {
1655             for (WindowState w : mWindows) {
1656                 if (w.mName.equals(windowName)) {
1657                     return true;
1658                 }
1659             }
1660             return false;
1661         }
1662     }
1663     public static class WindowToken extends WindowContainer {
1664         WindowToken(WindowTokenProto proto) {
1665             super(proto.windowContainer);
1666         }
1667     }
1668 
1669     /**
1670      * Represents WindowContainer classes such as DisplayContent.WindowContainers and
1671      * DisplayContent.NonAppWindowContainers. This can be expanded into a specific class
1672      * if we need track and assert some state in the future.
1673      */
1674     public static class GenericWindowContainer extends WindowContainer {
1675         GenericWindowContainer(WindowContainerProto proto) {
1676             super(proto);
1677         }
1678     }
1679 
1680     static WindowContainer getWindowContainer(WindowContainerChildProto proto,
1681             WindowContainer parent) {
1682         if (proto.displayContent != null) {
1683             return new DisplayContent(proto.displayContent);
1684         }
1685 
1686         if (proto.displayArea != null) {
1687             return new DisplayArea(proto.displayArea);
1688         }
1689 
1690         if (proto.task != null) {
1691             return new ActivityTask(proto.task);
1692         }
1693 
1694         if (proto.activity != null) {
1695             return new Activity(proto.activity, parent);
1696         }
1697 
1698         if (proto.windowToken != null) {
1699             return new WindowToken(proto.windowToken);
1700         }
1701 
1702         if (proto.window != null) {
1703             return new WindowState(proto.window);
1704         }
1705 
1706         if (proto.windowContainer != null) {
1707             return new GenericWindowContainer(proto.windowContainer);
1708         }
1709         return null;
1710     }
1711 
1712     static abstract class WindowContainer extends ConfigurationContainer {
1713 
1714         protected String mName;
1715         protected final String mAppToken;
1716         protected boolean mFullscreen;
1717         protected Rect mBounds;
1718         protected int mOrientation;
1719         protected boolean mVisible;
1720         protected List<WindowState> mSubWindows = new ArrayList<>();
1721         protected List<WindowContainer> mChildren = new ArrayList<>();
1722 
1723         WindowContainer(WindowContainerProto proto) {
1724             super(proto.configurationContainer);
1725             IdentifierProto identifierProto = proto.identifier;
1726             mName = identifierProto.title;
1727             mAppToken = Integer.toHexString(identifierProto.hashCode);
1728             mOrientation = proto.orientation;
1729             for (int i = 0; i < proto.children.length; i++) {
1730                 final WindowContainer child = getWindowContainer(proto.children[i], this);
1731                 if (child != null) {
1732                     mChildren.add(child);
1733                 }
1734             }
1735             mVisible = proto.visible;
1736         }
1737 
1738         @NonNull
1739         public String getName() {
1740             return mName;
1741         }
1742 
1743         @NonNull
1744         public String getPackageName() {
1745             int sep = mName.indexOf('/');
1746             return sep == -1 ? mName : mName.substring(0, sep);
1747         }
1748 
1749         String getToken() {
1750             return mAppToken;
1751         }
1752 
1753         Rect getBounds() {
1754             return mBounds;
1755         }
1756 
1757         boolean isFullscreen() {
1758             return mFullscreen;
1759         }
1760 
1761         boolean isVisible() {
1762             return mVisible;
1763         }
1764 
1765         List<WindowState> getWindows() {
1766             return mSubWindows;
1767         }
1768     }
1769 
1770     public static class WindowState extends WindowContainer {
1771 
1772         private static final int WINDOW_TYPE_NORMAL = 0;
1773         public static final int WINDOW_TYPE_STARTING = 1;
1774         private static final int WINDOW_TYPE_EXITING = 2;
1775         private static final int WINDOW_TYPE_DEBUGGER = 3;
1776 
1777         private final int mWindowType;
1778         private int mType = 0;
1779         private int mDisplayId;
1780         private int mStackId;
1781         private int mLayer;
1782         private boolean mShown;
1783         private Rect mContainingFrame;
1784         private Rect mParentFrame;
1785         private Rect mFrame;
1786         private Rect mCompatFrame;
1787         private Rect mSurfaceInsets = new Rect();
1788         private Rect mGivenContentInsets = new Rect();
1789         private Rect mCrop = new Rect();
1790         private boolean mHasCompatScale;
1791         private float mGlobalScale;
1792         private int mRequestedWidth;
1793         private int mRequestedHeight;
1794 
1795         WindowState(WindowStateProto proto) {
1796             super(proto.windowContainer);
1797             mDisplayId = proto.displayId;
1798             mStackId = proto.stackId;
1799             if (proto.attributes != null) {
1800                 mType = proto.attributes.type;
1801             }
1802             WindowStateAnimatorProto animatorProto = proto.animator;
1803             if (animatorProto != null) {
1804                 if (animatorProto.surface != null) {
1805                     WindowSurfaceControllerProto surfaceProto = animatorProto.surface;
1806                     mShown = surfaceProto.shown;
1807                     mLayer = surfaceProto.layer;
1808                 }
1809                 mCrop = extract(animatorProto.lastClipRect);
1810             }
1811             mGivenContentInsets = extract(proto.givenContentInsets);
1812             WindowFramesProto windowFramesProto = proto.windowFrames;
1813             if (windowFramesProto != null) {
1814                 mFrame = extract(windowFramesProto.frame);
1815                 mContainingFrame = extract(windowFramesProto.containingFrame);
1816                 mParentFrame = extract(windowFramesProto.parentFrame);
1817                 mCompatFrame = extract(windowFramesProto.compatFrame);
1818             }
1819             mSurfaceInsets = extract(proto.surfaceInsets);
1820             if (mName.startsWith(STARTING_WINDOW_PREFIX)) {
1821                 mWindowType = WINDOW_TYPE_STARTING;
1822                 // Existing code depends on the prefix being removed
1823                 mName = mName.substring(STARTING_WINDOW_PREFIX.length());
1824             } else if (proto.animatingExit) {
1825                 mWindowType = WINDOW_TYPE_EXITING;
1826             } else if (mName.startsWith(DEBUGGER_WINDOW_PREFIX)) {
1827                 mWindowType = WINDOW_TYPE_STARTING;
1828                 mName = mName.substring(DEBUGGER_WINDOW_PREFIX.length());
1829             } else {
1830                 mWindowType = 0;
1831             }
1832             collectDescendantsOfType(WindowState.class, this, mSubWindows);
1833             mHasCompatScale = proto.hasCompatScale;
1834             mGlobalScale = proto.globalScale;
1835             mRequestedWidth = proto.requestedWidth;
1836             mRequestedHeight = proto.requestedHeight;
1837         }
1838 
1839         boolean isStartingWindow() {
1840             return mWindowType == WINDOW_TYPE_STARTING;
1841         }
1842 
1843         boolean isExitingWindow() {
1844             return mWindowType == WINDOW_TYPE_EXITING;
1845         }
1846 
1847         boolean isDebuggerWindow() {
1848             return mWindowType == WINDOW_TYPE_DEBUGGER;
1849         }
1850 
1851         int getDisplayId() {
1852             return mDisplayId;
1853         }
1854 
1855         int getStackId() {
1856             return mStackId;
1857         }
1858 
1859         Rect getContainingFrame() {
1860             return mContainingFrame;
1861         }
1862 
1863         public Rect getFrame() {
1864             return mFrame;
1865         }
1866 
1867         Rect getSurfaceInsets() {
1868             return mSurfaceInsets;
1869         }
1870 
1871         Rect getGivenContentInsets() {
1872             return mGivenContentInsets;
1873         }
1874 
1875         Rect getParentFrame() {
1876             return mParentFrame;
1877         }
1878 
1879         public Rect getCompatFrame() {
1880             return mCompatFrame;
1881         }
1882 
1883         Rect getCrop() {
1884             return mCrop;
1885         }
1886 
1887         public boolean isSurfaceShown() {
1888             return mShown;
1889         }
1890 
1891         public int getType() {
1892             return mType;
1893         }
1894 
1895         public boolean hasCompatScale() {
1896             return mHasCompatScale;
1897         }
1898 
1899         public float getGlobalScale() {
1900             return mGlobalScale;
1901         }
1902 
1903         public int getRequestedWidth() {
1904             return mRequestedWidth;
1905         }
1906 
1907         public int getRequestedHeight() {
1908             return mRequestedHeight;
1909         }
1910 
1911         private String getWindowTypeSuffix(int windowType) {
1912             switch (windowType) {
1913                 case WINDOW_TYPE_STARTING:
1914                     return " STARTING";
1915                 case WINDOW_TYPE_EXITING:
1916                     return " EXITING";
1917                 case WINDOW_TYPE_DEBUGGER:
1918                     return " DEBUGGER";
1919                 default:
1920                     break;
1921             }
1922             return "";
1923         }
1924 
1925         @Override
1926         public String toString() {
1927             return "WindowState: {" + mAppToken + " " + mName
1928                     + getWindowTypeSuffix(mWindowType) + "}" + " type=" + mType
1929                     + " cf=" + mContainingFrame + " pf=" + mParentFrame;
1930         }
1931 
1932         public String toLongString() {
1933             return toString() + " f=" + mFrame + " crop=" + mCrop + " isSurfaceShown="
1934                     + isSurfaceShown();
1935         }
1936     }
1937 
1938     static int dpToPx(float dp, int densityDpi) {
1939         return (int) (dp * densityDpi / DENSITY_DEFAULT + 0.5f);
1940     }
1941 
1942     int defaultMinimalTaskSize(int displayId) {
1943         return dpToPx(DEFAULT_RESIZABLE_TASK_SIZE_DP, getDisplay(displayId).getDpi());
1944     }
1945 
1946     int defaultMinimalDisplaySizeForSplitScreen(int displayId) {
1947         return dpToPx(ActivityTaskManager.DEFAULT_MINIMAL_SPLIT_SCREEN_DISPLAY_SIZE_DP,
1948                 getDisplay(displayId).getDpi());
1949     }
1950 }
1951