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_STANDARD;
20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
21 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
22 import static android.server.wm.ProtoExtractors.extract;
23 import static android.server.wm.StateLogger.log;
24 import static android.server.wm.StateLogger.logE;
25 import static android.view.Display.DEFAULT_DISPLAY;
26 
27 import static androidx.test.InstrumentationRegistry.getInstrumentation;
28 
29 import static org.junit.Assert.assertTrue;
30 import static org.junit.Assert.fail;
31 
32 import android.content.res.Configuration;
33 import android.graphics.Rect;
34 import android.os.ParcelFileDescriptor;
35 import android.os.SystemClock;
36 import android.view.WindowManager;
37 import android.view.nano.DisplayInfoProto;
38 import android.view.nano.ViewProtoEnums;
39 
40 import androidx.annotation.NonNull;
41 import androidx.annotation.Nullable;
42 
43 import com.android.server.wm.nano.AppTransitionProto;
44 import com.android.server.wm.nano.AppWindowTokenProto;
45 import com.android.server.wm.nano.ConfigurationContainerProto;
46 import com.android.server.wm.nano.DisplayContentProto;
47 import com.android.server.wm.nano.DisplayFramesProto;
48 import com.android.server.wm.nano.IdentifierProto;
49 import com.android.server.wm.nano.PinnedStackControllerProto;
50 import com.android.server.wm.nano.StackProto;
51 import com.android.server.wm.nano.TaskProto;
52 import com.android.server.wm.nano.WindowContainerProto;
53 import com.android.server.wm.nano.WindowFramesProto;
54 import com.android.server.wm.nano.WindowManagerServiceDumpProto;
55 import com.android.server.wm.nano.WindowStateAnimatorProto;
56 import com.android.server.wm.nano.WindowStateProto;
57 import com.android.server.wm.nano.WindowSurfaceControllerProto;
58 import com.android.server.wm.nano.WindowTokenProto;
59 
60 import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
61 
62 import java.io.ByteArrayOutputStream;
63 import java.io.FileInputStream;
64 import java.io.IOException;
65 import java.nio.charset.StandardCharsets;
66 import java.util.ArrayList;
67 import java.util.Arrays;
68 import java.util.HashMap;
69 import java.util.LinkedList;
70 import java.util.List;
71 import java.util.Map;
72 import java.util.function.Predicate;
73 import java.util.stream.Collectors;
74 import java.util.stream.Stream;
75 
76 public class WindowManagerState {
77     public static final String TRANSIT_ACTIVITY_OPEN = "TRANSIT_ACTIVITY_OPEN";
78     public static final String TRANSIT_ACTIVITY_CLOSE = "TRANSIT_ACTIVITY_CLOSE";
79     public static final String TRANSIT_TASK_OPEN = "TRANSIT_TASK_OPEN";
80     public static final String TRANSIT_TASK_CLOSE = "TRANSIT_TASK_CLOSE";
81 
82     public static final String TRANSIT_WALLPAPER_OPEN = "TRANSIT_WALLPAPER_OPEN";
83     public static final String TRANSIT_WALLPAPER_CLOSE = "TRANSIT_WALLPAPER_CLOSE";
84     public static final String TRANSIT_WALLPAPER_INTRA_OPEN = "TRANSIT_WALLPAPER_INTRA_OPEN";
85     public static final String TRANSIT_WALLPAPER_INTRA_CLOSE = "TRANSIT_WALLPAPER_INTRA_CLOSE";
86 
87     public static final String TRANSIT_KEYGUARD_GOING_AWAY = "TRANSIT_KEYGUARD_GOING_AWAY";
88     public static final String TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER =
89             "TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER";
90     public static final String TRANSIT_KEYGUARD_OCCLUDE = "TRANSIT_KEYGUARD_OCCLUDE";
91     public static final String TRANSIT_KEYGUARD_UNOCCLUDE = "TRANSIT_KEYGUARD_UNOCCLUDE";
92     public static final String TRANSIT_TRANSLUCENT_ACTIVITY_OPEN =
93             "TRANSIT_TRANSLUCENT_ACTIVITY_OPEN";
94     public static final String TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE =
95             "TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE";
96 
97     public static final String APP_STATE_IDLE = "APP_STATE_IDLE";
98 
99     private static final String DUMPSYS_WINDOW = "dumpsys window -a --proto";
100 
101     private static final String STARTING_WINDOW_PREFIX = "Starting ";
102     private static final String DEBUGGER_WINDOW_PREFIX = "Waiting For Debugger: ";
103 
104     /** @see WindowManager.LayoutParams */
105     private static final int TYPE_NAVIGATION_BAR = 2019;
106 
107     /** @see WindowManager.LayoutParams */
108     private static final int TYPE_NAVIGATION_BAR_PANEL = 2024;
109 
110     // Windows in z-order with the top most at the front of the list.
111     private List<WindowState> mWindowStates = new ArrayList();
112     // Stacks in z-order with the top most at the front of the list, starting with primary display.
113     private final List<WindowStack> mStacks = new ArrayList();
114     // Stacks on all attached displays, in z-order with the top most at the front of the list.
115     private final Map<Integer, List<WindowStack>> mDisplayStacks
116             = new HashMap<>();
117     private List<Display> mDisplays = new ArrayList();
118     private String mFocusedWindow = null;
119     private String mFocusedApp = null;
120     private String mInputMethodWindowAppToken = null;
121     private Rect mDefaultPinnedStackBounds = new Rect();
122     private Rect mPinnedStackMovementBounds = new Rect();
123     private final LinkedList<String> mSysDump = new LinkedList();
124     private int mRotation;
125     private int mLastOrientation;
126     private boolean mDisplayFrozen;
127     private boolean mIsDockedStackMinimized;
128 
computeState()129     public void computeState() {
130         // It is possible the system is in the middle of transition to the right state when we get
131         // the dump. We try a few times to get the information we need before giving up.
132         int retriesLeft = 3;
133         boolean retry = false;
134         byte[] dump = null;
135 
136         log("==============================");
137         log("      WindowManagerState      ");
138         log("==============================");
139         do {
140             if (retry) {
141                 log("***Incomplete WM state. Retrying...");
142                 // Wait half a second between retries for window manager to finish transitioning...
143                 SystemClock.sleep(500);
144             }
145 
146             dump = executeShellCommand(DUMPSYS_WINDOW);
147             try {
148                 parseSysDumpProto(dump);
149             } catch (InvalidProtocolBufferNanoException ex) {
150                 throw new RuntimeException("Failed to parse dumpsys:\n"
151                         + new String(dump, StandardCharsets.UTF_8), ex);
152             }
153 
154             retry = mWindowStates.isEmpty() || mFocusedApp == null;
155         } while (retry && retriesLeft-- > 0);
156 
157         if (mWindowStates.isEmpty()) {
158             logE("No Windows found...");
159         }
160         if (mFocusedWindow == null) {
161             logE("No Focused Window...");
162         }
163         if (mFocusedApp == null) {
164             logE("No Focused App...");
165         }
166     }
167 
executeShellCommand(String cmd)168     private byte[] executeShellCommand(String cmd) {
169         try {
170             ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
171                     .executeShellCommand(cmd);
172             byte[] buf = new byte[512];
173             int bytesRead;
174             FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
175             ByteArrayOutputStream stdout = new ByteArrayOutputStream();
176             while ((bytesRead = fis.read(buf)) != -1) {
177                 stdout.write(buf, 0, bytesRead);
178             }
179             fis.close();
180             return stdout.toByteArray();
181         } catch (IOException e) {
182             throw new RuntimeException(e);
183         }
184     }
185 
186 
parseSysDumpProto(byte[] sysDump)187     private void parseSysDumpProto(byte[] sysDump) throws InvalidProtocolBufferNanoException {
188         reset();
189         WindowManagerServiceDumpProto state = WindowManagerServiceDumpProto.parseFrom(sysDump);
190         List<WindowState> allWindows = new ArrayList<>();
191         Map<String, WindowState> windowMap = new HashMap<>();
192         if (state.focusedWindow != null) {
193             mFocusedWindow = state.focusedWindow.title;
194         }
195         mFocusedApp = state.focusedApp;
196         for (int i = 0; i < state.rootWindowContainer.displays.length; i++) {
197             DisplayContentProto displayProto = state.rootWindowContainer.displays[i];
198             final Display display = new Display(displayProto);
199             mDisplays.add(display);
200             allWindows.addAll(display.getWindows());
201             List<WindowStack> stacks = new ArrayList<>();
202             for (int j = 0; j < displayProto.stacks.length; j++) {
203                 StackProto stackProto = displayProto.stacks[j];
204                 final WindowStack stack = new WindowStack(stackProto);
205                 mStacks.add(stack);
206                 stacks.add(stack);
207                 allWindows.addAll(stack.getWindows());
208             }
209             mDisplayStacks.put(display.mDisplayId, stacks);
210 
211             // use properties from the default display only
212             if (display.getDisplayId() == DEFAULT_DISPLAY) {
213                 if (displayProto.dockedStackDividerController != null) {
214                     mIsDockedStackMinimized =
215                             displayProto.dockedStackDividerController.minimizedDock;
216                 }
217                 PinnedStackControllerProto pinnedStackProto = displayProto.pinnedStackController;
218                 if (pinnedStackProto != null) {
219                     mDefaultPinnedStackBounds = extract(pinnedStackProto.defaultBounds);
220                     mPinnedStackMovementBounds = extract(pinnedStackProto.movementBounds);
221                 }
222             }
223         }
224         for (WindowState w : allWindows) {
225             windowMap.put(w.getToken(), w);
226         }
227         for (int i = 0; i < state.rootWindowContainer.windows.length; i++) {
228             IdentifierProto identifierProto = state.rootWindowContainer.windows[i];
229             String hash_code = Integer.toHexString(identifierProto.hashCode);
230             mWindowStates.add(windowMap.get(hash_code));
231         }
232         if (state.inputMethodWindow != null) {
233             mInputMethodWindowAppToken = Integer.toHexString(state.inputMethodWindow.hashCode);
234         }
235         mDisplayFrozen = state.displayFrozen;
236         mRotation = state.rotation;
237         mLastOrientation = state.lastOrientation;
238     }
239 
appStateToString(int appState)240     static String appStateToString(int appState) {
241         switch (appState) {
242             case AppTransitionProto.APP_STATE_IDLE:
243                 return "APP_STATE_IDLE";
244             case AppTransitionProto.APP_STATE_READY:
245                 return "APP_STATE_READY";
246             case AppTransitionProto.APP_STATE_RUNNING:
247                 return "APP_STATE_RUNNING";
248             case AppTransitionProto.APP_STATE_TIMEOUT:
249                 return "APP_STATE_TIMEOUT";
250             default:
251                 fail("Invalid AppTransitionState");
252                 return null;
253         }
254     }
255 
appTransitionToString(int transition)256     static String appTransitionToString(int transition) {
257         switch (transition) {
258             case ViewProtoEnums.TRANSIT_UNSET: {
259                 return "TRANSIT_UNSET";
260             }
261             case ViewProtoEnums.TRANSIT_NONE: {
262                 return "TRANSIT_NONE";
263             }
264             case ViewProtoEnums.TRANSIT_ACTIVITY_OPEN: {
265                 return TRANSIT_ACTIVITY_OPEN;
266             }
267             case ViewProtoEnums.TRANSIT_ACTIVITY_CLOSE: {
268                 return TRANSIT_ACTIVITY_CLOSE;
269             }
270             case ViewProtoEnums.TRANSIT_TASK_OPEN: {
271                 return TRANSIT_TASK_OPEN;
272             }
273             case ViewProtoEnums.TRANSIT_TASK_CLOSE: {
274                 return TRANSIT_TASK_CLOSE;
275             }
276             case ViewProtoEnums.TRANSIT_TASK_TO_FRONT: {
277                 return "TRANSIT_TASK_TO_FRONT";
278             }
279             case ViewProtoEnums.TRANSIT_TASK_TO_BACK: {
280                 return "TRANSIT_TASK_TO_BACK";
281             }
282             case ViewProtoEnums.TRANSIT_WALLPAPER_CLOSE: {
283                 return TRANSIT_WALLPAPER_CLOSE;
284             }
285             case ViewProtoEnums.TRANSIT_WALLPAPER_OPEN: {
286                 return TRANSIT_WALLPAPER_OPEN;
287             }
288             case ViewProtoEnums.TRANSIT_WALLPAPER_INTRA_OPEN: {
289                 return TRANSIT_WALLPAPER_INTRA_OPEN;
290             }
291             case ViewProtoEnums.TRANSIT_WALLPAPER_INTRA_CLOSE: {
292                 return TRANSIT_WALLPAPER_INTRA_CLOSE;
293             }
294             case ViewProtoEnums.TRANSIT_TASK_OPEN_BEHIND: {
295                 return "TRANSIT_TASK_OPEN_BEHIND";
296             }
297             case ViewProtoEnums.TRANSIT_ACTIVITY_RELAUNCH: {
298                 return "TRANSIT_ACTIVITY_RELAUNCH";
299             }
300             case ViewProtoEnums.TRANSIT_DOCK_TASK_FROM_RECENTS: {
301                 return "TRANSIT_DOCK_TASK_FROM_RECENTS";
302             }
303             case ViewProtoEnums.TRANSIT_KEYGUARD_GOING_AWAY: {
304                 return TRANSIT_KEYGUARD_GOING_AWAY;
305             }
306             case ViewProtoEnums.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER: {
307                 return TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
308             }
309             case ViewProtoEnums.TRANSIT_KEYGUARD_OCCLUDE: {
310                 return TRANSIT_KEYGUARD_OCCLUDE;
311             }
312             case ViewProtoEnums.TRANSIT_KEYGUARD_UNOCCLUDE: {
313                 return TRANSIT_KEYGUARD_UNOCCLUDE;
314             }
315             case ViewProtoEnums.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN: {
316                 return TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
317             }
318             case ViewProtoEnums.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE: {
319                 return TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
320             }
321             case ViewProtoEnums.TRANSIT_CRASHING_ACTIVITY_CLOSE: {
322                 return "TRANSIT_CRASHING_ACTIVITY_CLOSE";
323             }
324             default: {
325                 fail("Invalid lastUsedAppTransition");
326                 return null;
327             }
328         }
329     }
330 
getMatchingWindowType(int type)331     List<WindowState> getMatchingWindowType(int type) {
332         return getMatchingWindows(ws -> type == ws.mType).collect(Collectors.toList());
333     }
334 
getMatchingWindowTokens(final String windowName)335     List<String> getMatchingWindowTokens(final String windowName) {
336         return getMatchingWindows(ws -> windowName.equals(ws.getName()))
337                 .map(WindowState::getToken)
338                 .collect(Collectors.toList());
339     }
340 
getAllNavigationBarStates()341     List<WindowState> getAllNavigationBarStates() {
342         return getMatchingWindows(WindowManagerState::isValidNavBarType)
343                 .collect(Collectors.toList());
344     }
345 
getAndAssertSingleNavBarWindowOnDisplay(int displayId)346     WindowState getAndAssertSingleNavBarWindowOnDisplay(int displayId) {
347         List<WindowState> navWindow = getMatchingWindows(ws ->
348                 isValidNavBarType(ws) && ws.getDisplayId() == displayId)
349                 .collect(Collectors.toList());
350 
351         // We may need some time to wait for nav bar showing.
352         // It's Ok to get 0 nav bar here.
353         assertTrue("There should be at most one navigation bar on a display",
354                 navWindow.size() <= 1);
355 
356         return navWindow.isEmpty() ? null : navWindow.get(0);
357     }
358 
isValidNavBarType(WindowState navState)359     private static boolean isValidNavBarType(WindowState navState) {
360         return TYPE_NAVIGATION_BAR == navState.getType();
361     }
362 
getMatchingVisibleWindowState(final String windowName)363     public List<WindowState> getMatchingVisibleWindowState(final String windowName) {
364         return getMatchingWindows(ws -> ws.isShown() && windowName.equals(ws.getName()))
365                 .collect(Collectors.toList());
366     }
367 
getExitingWindows()368     List<WindowState> getExitingWindows() {
369         return getMatchingWindows(WindowState::isExitingWindow)
370                 .collect(Collectors.toList());
371     }
372 
getMatchingWindows(Predicate<WindowState> condition)373     private Stream<WindowState> getMatchingWindows(Predicate<WindowState> condition) {
374         return mWindowStates.stream().filter(condition);
375     }
376 
377     @Nullable
getWindowByPackageName(String packageName, int windowType)378     public WindowState getWindowByPackageName(String packageName, int windowType) {
379         final List<WindowState> windowList = getWindowsByPackageName(packageName, windowType);
380         return windowList.isEmpty() ? null : windowList.get(0);
381     }
382 
getWindowsByPackageName(String packageName, int... restrictToTypes)383     public List<WindowState> getWindowsByPackageName(String packageName, int... restrictToTypes) {
384         return getMatchingWindows(ws ->
385                 (ws.getName().equals(packageName) || ws.getName().startsWith(packageName + "/"))
386                 && Arrays.stream(restrictToTypes).anyMatch(type -> type == ws.getType()))
387                 .collect(Collectors.toList());
388     }
389 
getWindowStateForAppToken(String appToken)390     WindowState getWindowStateForAppToken(String appToken) {
391         return getMatchingWindows(ws -> ws.getToken().equals(appToken))
392                 .findFirst()
393                 .orElse(null);
394     }
395 
getDisplay(int displayId)396     Display getDisplay(int displayId) {
397         for (Display display : mDisplays) {
398             if (displayId == display.getDisplayId()) {
399                 return display;
400             }
401         }
402         return null;
403     }
404 
getDisplays()405     List<Display> getDisplays() {
406         return mDisplays;
407     }
408 
getFrontWindow()409     String getFrontWindow() {
410         if (mWindowStates == null || mWindowStates.isEmpty()) {
411             return null;
412         }
413         return mWindowStates.get(0).getName();
414     }
415 
getFocusedWindow()416     public String getFocusedWindow() {
417         return mFocusedWindow;
418     }
419 
getFocusedApp()420     public String getFocusedApp() {
421         return mFocusedApp;
422     }
423 
getDefaultDisplayLastTransition()424     String getDefaultDisplayLastTransition() {
425         return getDisplay(DEFAULT_DISPLAY).getLastTransition();
426     }
427 
getDefaultDisplayAppTransitionState()428     String getDefaultDisplayAppTransitionState() {
429         return getDisplay(DEFAULT_DISPLAY).getAppTransitionState();
430     }
431 
getFrontStackId(int displayId)432     int getFrontStackId(int displayId) {
433         return mDisplayStacks.get(displayId).get(0).mStackId;
434     }
435 
getFrontStackActivityType(int displayId)436     int getFrontStackActivityType(int displayId) {
437         return mDisplayStacks.get(displayId).get(0).getActivityType();
438     }
439 
getRotation()440     public int getRotation() {
441         return mRotation;
442     }
443 
getLastOrientation()444     int getLastOrientation() {
445         return mLastOrientation;
446     }
447 
containsStack(int stackId)448     boolean containsStack(int stackId) {
449         for (WindowStack stack : mStacks) {
450             if (stackId == stack.mStackId) {
451                 return true;
452             }
453         }
454         return false;
455     }
456 
containsStack(int windowingMode, int activityType)457     boolean containsStack(int windowingMode, int activityType) {
458         for (WindowStack stack : mStacks) {
459             if (activityType != ACTIVITY_TYPE_UNDEFINED
460                     && activityType != stack.getActivityType()) {
461                 continue;
462             }
463             if (windowingMode != WINDOWING_MODE_UNDEFINED
464                     && windowingMode != stack.getWindowingMode()) {
465                 continue;
466             }
467             return true;
468         }
469         return false;
470     }
471 
472     /**
473      * Check if there exists a window record with matching windowName.
474      */
containsWindow(String windowName)475     public boolean containsWindow(String windowName) {
476         for (WindowState window : mWindowStates) {
477             if (window.getName().equals(windowName)) {
478                 return true;
479             }
480         }
481         return false;
482     }
483 
484     /**
485      * Check if at least one window which matches provided window name is visible.
486      */
isWindowVisible(String windowName)487     boolean isWindowVisible(String windowName) {
488         for (WindowState window : mWindowStates) {
489             if (window.getName().equals(windowName)) {
490                 if (window.isShown()) {
491                     return true;
492                 }
493             }
494         }
495         return false;
496     }
497 
allWindowsVisible(String windowName)498     boolean allWindowsVisible(String windowName) {
499         boolean allVisible = false;
500         for (WindowState window : mWindowStates) {
501             if (window.getName().equals(windowName)) {
502                 if (!window.isShown()) {
503                     log("[VISIBLE] not visible" + windowName);
504                     return false;
505                 }
506                 log("[VISIBLE] visible" + windowName);
507                 allVisible = true;
508             }
509         }
510         return allVisible;
511     }
512 
getStack(int stackId)513     WindowStack getStack(int stackId) {
514         for (WindowStack stack : mStacks) {
515             if (stackId == stack.mStackId) {
516                 return stack;
517             }
518         }
519         return null;
520     }
521 
getStandardStackByWindowingMode(int windowingMode)522     WindowStack getStandardStackByWindowingMode(int windowingMode) {
523         for (WindowStack stack : mStacks) {
524             if (stack.getActivityType() != ACTIVITY_TYPE_STANDARD) {
525                 continue;
526             }
527             if (stack.getWindowingMode() == windowingMode) {
528                 return stack;
529             }
530         }
531         return null;
532     }
533 
534     /** Get the stack position on its display. */
getStackIndexByActivityType(int activityType)535     int getStackIndexByActivityType(int activityType) {
536         for (Integer displayId : mDisplayStacks.keySet()) {
537             List<WindowStack> stacks = mDisplayStacks.get(displayId);
538             for (int i = 0; i < stacks.size(); i++) {
539                 if (activityType == stacks.get(i).getActivityType()) {
540                     return i;
541                 }
542             }
543         }
544         return -1;
545     }
546 
getInputMethodWindowState()547     WindowState getInputMethodWindowState() {
548         return getWindowStateForAppToken(mInputMethodWindowAppToken);
549     }
550 
getStableBounds()551     Rect getStableBounds() {
552         return getDisplay(DEFAULT_DISPLAY).mStableBounds;
553     }
554 
getDefaultPinnedStackBounds()555     Rect getDefaultPinnedStackBounds() {
556         return new Rect(mDefaultPinnedStackBounds);
557     }
558 
getPinnedStackMovementBounds()559     Rect getPinnedStackMovementBounds() {
560         return new Rect(mPinnedStackMovementBounds);
561     }
562 
findFirstWindowWithType(int type)563     WindowState findFirstWindowWithType(int type) {
564         for (WindowState window : mWindowStates) {
565             if (window.getType() == type) {
566                 return window;
567             }
568         }
569         return null;
570     }
571 
isDisplayFrozen()572     public boolean isDisplayFrozen() {
573         return mDisplayFrozen;
574     }
575 
isDockedStackMinimized()576     public boolean isDockedStackMinimized() {
577         return mIsDockedStackMinimized;
578     }
579 
getZOrder(WindowState w)580     public int getZOrder(WindowState w) {
581         return mWindowStates.size() - mWindowStates.indexOf(w);
582     }
583 
reset()584     private void reset() {
585         mSysDump.clear();
586         mStacks.clear();
587         mDisplays.clear();
588         mWindowStates.clear();
589         mDisplayStacks.clear();
590         mFocusedWindow = null;
591         mFocusedApp = null;
592         mInputMethodWindowAppToken = null;
593         mIsDockedStackMinimized = false;
594         mDefaultPinnedStackBounds.setEmpty();
595         mPinnedStackMovementBounds.setEmpty();
596         mRotation = 0;
597         mLastOrientation = 0;
598         mDisplayFrozen = false;
599     }
600 
601     static class WindowStack extends WindowContainer {
602 
603         int mStackId;
604         ArrayList<WindowTask> mTasks = new ArrayList<>();
605         boolean mWindowAnimationBackgroundSurfaceShowing;
606         boolean mAnimatingBounds;
607 
WindowStack(StackProto proto)608         WindowStack(StackProto proto) {
609             super(proto.windowContainer);
610             mStackId = proto.id;
611             mFullscreen = proto.fillsParent;
612             mBounds = extract(proto.bounds);
613             for (int i = 0; i < proto.tasks.length; i++) {
614                 TaskProto taskProto = proto.tasks[i];
615                 WindowTask task = new WindowTask(taskProto);
616                 mTasks.add(task);
617                 mSubWindows.addAll(task.getWindows());
618             }
619             mWindowAnimationBackgroundSurfaceShowing = proto.animationBackgroundSurfaceIsDimming;
620             mAnimatingBounds = proto.animatingBounds;
621         }
622 
getTask(int taskId)623         WindowTask getTask(int taskId) {
624             for (WindowTask task : mTasks) {
625                 if (taskId == task.mTaskId) {
626                     return task;
627                 }
628             }
629             return null;
630         }
631 
isWindowAnimationBackgroundSurfaceShowing()632         boolean isWindowAnimationBackgroundSurfaceShowing() {
633             return mWindowAnimationBackgroundSurfaceShowing;
634         }
635     }
636 
637     static class WindowTask extends WindowContainer {
638 
639         int mTaskId;
640         List<String> mAppTokens = new ArrayList<>();
641         private int mSurfaceWidth;
642         private int mSurfaceHeight;
643 
WindowTask(TaskProto proto)644         WindowTask(TaskProto proto) {
645             super(proto.windowContainer);
646             mTaskId = proto.id;
647             mFullscreen = proto.fillsParent;
648             mBounds = extract(proto.bounds);
649             for (int i = 0; i < proto.appWindowTokens.length; i++) {
650                 AppWindowTokenProto appWindowTokenProto = proto.appWindowTokens[i];
651                 mAppTokens.add(appWindowTokenProto.name);
652                 WindowTokenProto windowTokenProto = appWindowTokenProto.windowToken;
653                 for (int j = 0; j < windowTokenProto.windows.length; j++) {
654                     WindowStateProto windowProto = windowTokenProto.windows[j];
655                     WindowState window = new WindowState(windowProto);
656                     mSubWindows.add(window);
657                     mSubWindows.addAll(window.getWindows());
658                 }
659             }
660             mSurfaceWidth = proto.surfaceWidth;
661             mSurfaceHeight = proto.surfaceHeight;
662         }
663 
getSurfaceWidth()664         int getSurfaceWidth() {
665             return mSurfaceWidth;
666         }
667 
getSurfaceHeight()668         int getSurfaceHeight() {
669             return mSurfaceHeight;
670         }
671     }
672 
673     static class ConfigurationContainer {
674         final Configuration mOverrideConfiguration = new Configuration();
675         final Configuration mFullConfiguration = new Configuration();
676         final Configuration mMergedOverrideConfiguration = new Configuration();
677 
ConfigurationContainer(ConfigurationContainerProto proto)678         ConfigurationContainer(ConfigurationContainerProto proto) {
679             if (proto == null) {
680                 return;
681             }
682             mOverrideConfiguration.setTo(extract(proto.overrideConfiguration));
683             mFullConfiguration.setTo(extract(proto.fullConfiguration));
684             mMergedOverrideConfiguration.setTo(extract(proto.mergedOverrideConfiguration));
685         }
686 
getWindowingMode()687         int getWindowingMode() {
688             if (mFullConfiguration == null) {
689                 return WINDOWING_MODE_UNDEFINED;
690             }
691             return mFullConfiguration.windowConfiguration.getWindowingMode();
692         }
693 
getActivityType()694         int getActivityType() {
695             if (mFullConfiguration == null) {
696                 return ACTIVITY_TYPE_UNDEFINED;
697             }
698             return mFullConfiguration.windowConfiguration.getActivityType();
699         }
700     }
701 
702     static abstract class WindowContainer extends ConfigurationContainer {
703 
704         protected boolean mFullscreen;
705         protected Rect mBounds;
706         protected int mOrientation;
707         protected List<WindowState> mSubWindows = new ArrayList<>();
708 
WindowContainer(WindowContainerProto proto)709         WindowContainer(WindowContainerProto proto) {
710             super(proto.configurationContainer);
711             mOrientation = proto.orientation;
712         }
713 
getBounds()714         Rect getBounds() {
715             return mBounds;
716         }
717 
isFullscreen()718         boolean isFullscreen() {
719             return mFullscreen;
720         }
721 
getWindows()722         List<WindowState> getWindows() {
723             return mSubWindows;
724         }
725     }
726 
727     static class Display extends WindowContainer {
728 
729         private final int mDisplayId;
730         private Rect mDisplayRect = new Rect();
731         private Rect mAppRect = new Rect();
732         private int mDpi;
733         private Rect mStableBounds;
734         private String mName;
735         private int mSurfaceSize;
736         private String mFocusedApp;
737         private String mLastTransition;
738         private String mAppTransitionState;
739 
Display(DisplayContentProto proto)740         public Display(DisplayContentProto proto) {
741             super(proto.windowContainer);
742             mDisplayId = proto.id;
743             for (int i = 0; i < proto.aboveAppWindows.length; i++) {
744                 addWindowsFromTokenProto(proto.aboveAppWindows[i]);
745             }
746             for (int i = 0; i < proto.belowAppWindows.length; i++) {
747                 addWindowsFromTokenProto(proto.belowAppWindows[i]);
748             }
749             for (int i = 0; i < proto.imeWindows.length; i++) {
750                 addWindowsFromTokenProto(proto.imeWindows[i]);
751             }
752             mDpi = proto.dpi;
753             DisplayInfoProto infoProto = proto.displayInfo;
754             if (infoProto != null) {
755                 mDisplayRect.set(0, 0, infoProto.logicalWidth, infoProto.logicalHeight);
756                 mAppRect.set(0, 0, infoProto.appWidth, infoProto.appHeight);
757                 mName = infoProto.name;
758             }
759             final DisplayFramesProto displayFramesProto = proto.displayFrames;
760             if (displayFramesProto != null) {
761                 mStableBounds = extract(displayFramesProto.stableBounds);
762             }
763             mSurfaceSize = proto.surfaceSize;
764             mFocusedApp = proto.focusedApp;
765 
766             final AppTransitionProto appTransitionProto = proto.appTransition;
767             int appState = 0;
768             int lastTransition = 0;
769             if (appTransitionProto != null) {
770                 appState = appTransitionProto.appTransitionState;
771                 lastTransition = appTransitionProto.lastUsedAppTransition;
772             }
773             mAppTransitionState = appStateToString(appState);
774             mLastTransition = appTransitionToString(lastTransition);
775         }
776 
addWindowsFromTokenProto(WindowTokenProto proto)777         private void addWindowsFromTokenProto(WindowTokenProto proto) {
778             for (int j = 0; j < proto.windows.length; j++) {
779                 WindowStateProto windowProto = proto.windows[j];
780                 WindowState childWindow = new WindowState(windowProto);
781                 mSubWindows.add(childWindow);
782                 mSubWindows.addAll(childWindow.getWindows());
783             }
784         }
785 
getDisplayId()786         int getDisplayId() {
787             return mDisplayId;
788         }
789 
getDpi()790         int getDpi() {
791             return mDpi;
792         }
793 
getDisplayRect()794         Rect getDisplayRect() {
795             return mDisplayRect;
796         }
797 
getAppRect()798         Rect getAppRect() {
799             return mAppRect;
800         }
801 
getName()802         String getName() {
803             return mName;
804         }
805 
getSurfaceSize()806         int getSurfaceSize() {
807             return mSurfaceSize;
808         }
809 
getFocusedApp()810         String getFocusedApp() {
811             return mFocusedApp;
812         }
813 
getLastTransition()814         String getLastTransition() { return mLastTransition; }
815 
getAppTransitionState()816         String getAppTransitionState() { return mAppTransitionState; }
817 
818         @Override
toString()819         public String toString() {
820             return "Display #" + mDisplayId + ": name=" + mName + " mDisplayRect=" + mDisplayRect
821                     + " mAppRect=" + mAppRect;
822         }
823     }
824 
825     public static class WindowState extends WindowContainer {
826 
827         private static final int WINDOW_TYPE_NORMAL = 0;
828         private static final int WINDOW_TYPE_STARTING = 1;
829         private static final int WINDOW_TYPE_EXITING = 2;
830         private static final int WINDOW_TYPE_DEBUGGER = 3;
831 
832         private String mName;
833         private final String mAppToken;
834         private final int mWindowType;
835         private int mType = 0;
836         private int mDisplayId;
837         private int mStackId;
838         private int mLayer;
839         private boolean mShown;
840         private Rect mContainingFrame;
841         private Rect mParentFrame;
842         private Rect mContentFrame;
843         private Rect mFrame;
844         private Rect mSurfaceInsets = new Rect();
845         private Rect mContentInsets = new Rect();
846         private Rect mGivenContentInsets = new Rect();
847         private Rect mCrop = new Rect();
848 
WindowState(WindowStateProto proto)849         WindowState(WindowStateProto proto) {
850             super(proto.windowContainer);
851             IdentifierProto identifierProto = proto.identifier;
852             mName = identifierProto.title;
853             mAppToken = Integer.toHexString(identifierProto.hashCode);
854             mDisplayId = proto.displayId;
855             mStackId = proto.stackId;
856             if (proto.attributes != null) {
857                 mType = proto.attributes.type;
858             }
859             WindowStateAnimatorProto animatorProto = proto.animator;
860             if (animatorProto != null) {
861                 if (animatorProto.surface != null) {
862                     WindowSurfaceControllerProto surfaceProto = animatorProto.surface;
863                     mShown = surfaceProto.shown;
864                     mLayer = surfaceProto.layer;
865                 }
866                 mCrop = extract(animatorProto.lastClipRect);
867             }
868             mGivenContentInsets = extract(proto.givenContentInsets);
869             WindowFramesProto windowFramesProto = proto.windowFrames;
870             if (windowFramesProto != null) {
871                 mFrame = extract(windowFramesProto.frame);
872                 mContainingFrame = extract(windowFramesProto.containingFrame);
873                 mParentFrame = extract(windowFramesProto.parentFrame);
874                 mContentFrame = extract(windowFramesProto.contentFrame);
875                 mContentInsets = extract(windowFramesProto.contentInsets);
876             }
877             mSurfaceInsets = extract(proto.surfaceInsets);
878             if (mName.startsWith(STARTING_WINDOW_PREFIX)) {
879                 mWindowType = WINDOW_TYPE_STARTING;
880                 // Existing code depends on the prefix being removed
881                 mName = mName.substring(STARTING_WINDOW_PREFIX.length());
882             } else if (proto.animatingExit) {
883                 mWindowType = WINDOW_TYPE_EXITING;
884             } else if (mName.startsWith(DEBUGGER_WINDOW_PREFIX)) {
885                 mWindowType = WINDOW_TYPE_STARTING;
886                 mName = mName.substring(DEBUGGER_WINDOW_PREFIX.length());
887             } else {
888                 mWindowType = 0;
889             }
890             for (int i = 0; i < proto.childWindows.length; i++) {
891                 WindowStateProto childProto = proto.childWindows[i];
892                 WindowState childWindow = new WindowState(childProto);
893                 mSubWindows.add(childWindow);
894                 mSubWindows.addAll(childWindow.getWindows());
895             }
896         }
897 
898         @NonNull
getName()899         public String getName() {
900             return mName;
901         }
902 
getToken()903         String getToken() {
904             return mAppToken;
905         }
906 
isStartingWindow()907         boolean isStartingWindow() {
908             return mWindowType == WINDOW_TYPE_STARTING;
909         }
910 
isExitingWindow()911         boolean isExitingWindow() {
912             return mWindowType == WINDOW_TYPE_EXITING;
913         }
914 
isDebuggerWindow()915         boolean isDebuggerWindow() {
916             return mWindowType == WINDOW_TYPE_DEBUGGER;
917         }
918 
getDisplayId()919         int getDisplayId() {
920             return mDisplayId;
921         }
922 
getStackId()923         int getStackId() {
924             return mStackId;
925         }
926 
getContainingFrame()927         Rect getContainingFrame() {
928             return mContainingFrame;
929         }
930 
getFrame()931         public Rect getFrame() {
932             return mFrame;
933         }
934 
getSurfaceInsets()935         Rect getSurfaceInsets() {
936             return mSurfaceInsets;
937         }
938 
getContentInsets()939         Rect getContentInsets() {
940             return mContentInsets;
941         }
942 
getGivenContentInsets()943         Rect getGivenContentInsets() {
944             return mGivenContentInsets;
945         }
946 
getContentFrame()947         public Rect getContentFrame() {
948             return mContentFrame;
949         }
950 
getParentFrame()951         Rect getParentFrame() {
952             return mParentFrame;
953         }
954 
getCrop()955         Rect getCrop() {
956             return mCrop;
957         }
958 
isShown()959         public boolean isShown() {
960             return mShown;
961         }
962 
getType()963         public int getType() {
964             return mType;
965         }
966 
getWindowTypeSuffix(int windowType)967         private String getWindowTypeSuffix(int windowType) {
968             switch (windowType) {
969                 case WINDOW_TYPE_STARTING:
970                     return " STARTING";
971                 case WINDOW_TYPE_EXITING:
972                     return " EXITING";
973                 case WINDOW_TYPE_DEBUGGER:
974                     return " DEBUGGER";
975                 default:
976                     break;
977             }
978             return "";
979         }
980 
981         @Override
toString()982         public String toString() {
983             return "WindowState: {" + mAppToken + " " + mName
984                     + getWindowTypeSuffix(mWindowType) + "}" + " type=" + mType
985                     + " cf=" + mContainingFrame + " pf=" + mParentFrame;
986         }
987     }
988 }
989