Home | History | Annotate | Download | only in wm
      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 
    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 
    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 
    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 
    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 
    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 
    331     List<WindowState> getMatchingWindowType(int type) {
    332         return getMatchingWindows(ws -> type == ws.mType).collect(Collectors.toList());
    333     }
    334 
    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 
    341     List<WindowState> getAllNavigationBarStates() {
    342         return getMatchingWindows(WindowManagerState::isValidNavBarType)
    343                 .collect(Collectors.toList());
    344     }
    345 
    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 
    359     private static boolean isValidNavBarType(WindowState navState) {
    360         return TYPE_NAVIGATION_BAR == navState.getType();
    361     }
    362 
    363     public List<WindowState> getMatchingVisibleWindowState(final String windowName) {
    364         return getMatchingWindows(ws -> ws.isShown() && windowName.equals(ws.getName()))
    365                 .collect(Collectors.toList());
    366     }
    367 
    368     List<WindowState> getExitingWindows() {
    369         return getMatchingWindows(WindowState::isExitingWindow)
    370                 .collect(Collectors.toList());
    371     }
    372 
    373     private Stream<WindowState> getMatchingWindows(Predicate<WindowState> condition) {
    374         return mWindowStates.stream().filter(condition);
    375     }
    376 
    377     @Nullable
    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 
    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 
    390     WindowState getWindowStateForAppToken(String appToken) {
    391         return getMatchingWindows(ws -> ws.getToken().equals(appToken))
    392                 .findFirst()
    393                 .orElse(null);
    394     }
    395 
    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 
    405     List<Display> getDisplays() {
    406         return mDisplays;
    407     }
    408 
    409     String getFrontWindow() {
    410         if (mWindowStates == null || mWindowStates.isEmpty()) {
    411             return null;
    412         }
    413         return mWindowStates.get(0).getName();
    414     }
    415 
    416     public String getFocusedWindow() {
    417         return mFocusedWindow;
    418     }
    419 
    420     public String getFocusedApp() {
    421         return mFocusedApp;
    422     }
    423 
    424     String getDefaultDisplayLastTransition() {
    425         return getDisplay(DEFAULT_DISPLAY).getLastTransition();
    426     }
    427 
    428     String getDefaultDisplayAppTransitionState() {
    429         return getDisplay(DEFAULT_DISPLAY).getAppTransitionState();
    430     }
    431 
    432     int getFrontStackId(int displayId) {
    433         return mDisplayStacks.get(displayId).get(0).mStackId;
    434     }
    435 
    436     int getFrontStackActivityType(int displayId) {
    437         return mDisplayStacks.get(displayId).get(0).getActivityType();
    438     }
    439 
    440     public int getRotation() {
    441         return mRotation;
    442     }
    443 
    444     int getLastOrientation() {
    445         return mLastOrientation;
    446     }
    447 
    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 
    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      */
    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      */
    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 
    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 
    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 
    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. */
    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 
    547     WindowState getInputMethodWindowState() {
    548         return getWindowStateForAppToken(mInputMethodWindowAppToken);
    549     }
    550 
    551     Rect getStableBounds() {
    552         return getDisplay(DEFAULT_DISPLAY).mStableBounds;
    553     }
    554 
    555     Rect getDefaultPinnedStackBounds() {
    556         return new Rect(mDefaultPinnedStackBounds);
    557     }
    558 
    559     Rect getPinnedStackMovementBounds() {
    560         return new Rect(mPinnedStackMovementBounds);
    561     }
    562 
    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 
    572     public boolean isDisplayFrozen() {
    573         return mDisplayFrozen;
    574     }
    575 
    576     public boolean isDockedStackMinimized() {
    577         return mIsDockedStackMinimized;
    578     }
    579 
    580     public int getZOrder(WindowState w) {
    581         return mWindowStates.size() - mWindowStates.indexOf(w);
    582     }
    583 
    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 
    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 
    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 
    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 
    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 
    664         int getSurfaceWidth() {
    665             return mSurfaceWidth;
    666         }
    667 
    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 
    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 
    687         int getWindowingMode() {
    688             if (mFullConfiguration == null) {
    689                 return WINDOWING_MODE_UNDEFINED;
    690             }
    691             return mFullConfiguration.windowConfiguration.getWindowingMode();
    692         }
    693 
    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 
    709         WindowContainer(WindowContainerProto proto) {
    710             super(proto.configurationContainer);
    711             mOrientation = proto.orientation;
    712         }
    713 
    714         Rect getBounds() {
    715             return mBounds;
    716         }
    717 
    718         boolean isFullscreen() {
    719             return mFullscreen;
    720         }
    721 
    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 
    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 
    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 
    786         int getDisplayId() {
    787             return mDisplayId;
    788         }
    789 
    790         int getDpi() {
    791             return mDpi;
    792         }
    793 
    794         Rect getDisplayRect() {
    795             return mDisplayRect;
    796         }
    797 
    798         Rect getAppRect() {
    799             return mAppRect;
    800         }
    801 
    802         String getName() {
    803             return mName;
    804         }
    805 
    806         int getSurfaceSize() {
    807             return mSurfaceSize;
    808         }
    809 
    810         String getFocusedApp() {
    811             return mFocusedApp;
    812         }
    813 
    814         String getLastTransition() { return mLastTransition; }
    815 
    816         String getAppTransitionState() { return mAppTransitionState; }
    817 
    818         @Override
    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 
    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
    899         public String getName() {
    900             return mName;
    901         }
    902 
    903         String getToken() {
    904             return mAppToken;
    905         }
    906 
    907         boolean isStartingWindow() {
    908             return mWindowType == WINDOW_TYPE_STARTING;
    909         }
    910 
    911         boolean isExitingWindow() {
    912             return mWindowType == WINDOW_TYPE_EXITING;
    913         }
    914 
    915         boolean isDebuggerWindow() {
    916             return mWindowType == WINDOW_TYPE_DEBUGGER;
    917         }
    918 
    919         int getDisplayId() {
    920             return mDisplayId;
    921         }
    922 
    923         int getStackId() {
    924             return mStackId;
    925         }
    926 
    927         Rect getContainingFrame() {
    928             return mContainingFrame;
    929         }
    930 
    931         public Rect getFrame() {
    932             return mFrame;
    933         }
    934 
    935         Rect getSurfaceInsets() {
    936             return mSurfaceInsets;
    937         }
    938 
    939         Rect getContentInsets() {
    940             return mContentInsets;
    941         }
    942 
    943         Rect getGivenContentInsets() {
    944             return mGivenContentInsets;
    945         }
    946 
    947         public Rect getContentFrame() {
    948             return mContentFrame;
    949         }
    950 
    951         Rect getParentFrame() {
    952             return mParentFrame;
    953         }
    954 
    955         Rect getCrop() {
    956             return mCrop;
    957         }
    958 
    959         public boolean isShown() {
    960             return mShown;
    961         }
    962 
    963         public int getType() {
    964             return mType;
    965         }
    966 
    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
    982         public String toString() {
    983             return "WindowState: {" + mAppToken + " " + mName
    984                     + getWindowTypeSuffix(mWindowType) + "}" + " type=" + mType
    985                     + " cf=" + mContainingFrame + " pf=" + mParentFrame;
    986         }
    987     }
    988 }
    989