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 com.android.server.wm;
     18 
     19 import android.content.res.Configuration;
     20 import android.graphics.Rect;
     21 import android.hardware.display.DisplayManager;
     22 import android.hardware.power.V1_0.PowerHint;
     23 import android.os.Binder;
     24 import android.os.Debug;
     25 import android.os.Handler;
     26 import android.os.IBinder;
     27 import android.os.Looper;
     28 import android.os.Message;
     29 import android.os.ParcelFileDescriptor;
     30 import android.os.PowerManager;
     31 import android.os.RemoteException;
     32 import android.os.SystemClock;
     33 import android.os.UserHandle;
     34 import android.provider.Settings;
     35 import android.util.ArraySet;
     36 import android.util.EventLog;
     37 import android.util.Slog;
     38 import android.util.SparseIntArray;
     39 import android.view.Display;
     40 import android.view.DisplayInfo;
     41 import android.view.WindowManager;
     42 
     43 import com.android.internal.os.SomeArgs;
     44 import com.android.internal.util.ArrayUtils;
     45 import com.android.server.EventLogTags;
     46 
     47 import java.io.FileDescriptor;
     48 import java.io.PrintWriter;
     49 import java.util.ArrayList;
     50 import java.util.function.Consumer;
     51 
     52 import static android.app.AppOpsManager.MODE_ALLOWED;
     53 import static android.app.AppOpsManager.MODE_DEFAULT;
     54 import static android.app.AppOpsManager.OP_NONE;
     55 import static android.view.Display.DEFAULT_DISPLAY;
     56 import static android.view.Display.INVALID_DISPLAY;
     57 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
     58 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
     59 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
     60 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
     61 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
     62 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
     63 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
     64 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
     65 
     66 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
     67 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
     68 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
     69 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
     70 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
     71 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
     72 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
     73 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
     74 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
     75 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
     76 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
     77 import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
     78 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
     79 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
     80 import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
     81 import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
     82 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
     83 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
     84 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
     85 import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
     86 import static com.android.server.wm.WindowManagerService.logSurface;
     87 import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
     88 import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
     89 import static com.android.server.wm.WindowSurfacePlacer.SET_TURN_ON_SCREEN;
     90 import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
     91 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
     92 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
     93 
     94 /** Root {@link WindowContainer} for the device. */
     95 class RootWindowContainer extends WindowContainer<DisplayContent> {
     96     private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM;
     97 
     98     private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1;
     99     private static final int SET_USER_ACTIVITY_TIMEOUT = 2;
    100 
    101     WindowManagerService mService;
    102 
    103     private boolean mWallpaperForceHidingChanged = false;
    104     private Object mLastWindowFreezeSource = null;
    105     private Session mHoldScreen = null;
    106     private float mScreenBrightness = -1;
    107     private long mUserActivityTimeout = -1;
    108     private boolean mUpdateRotation = false;
    109     // Following variables are for debugging screen wakelock only.
    110     // Last window that requires screen wakelock
    111     WindowState mHoldScreenWindow = null;
    112     // Last window that obscures all windows below
    113     WindowState mObscuringWindow = null;
    114     // Only set while traversing the default display based on its content.
    115     // Affects the behavior of mirroring on secondary displays.
    116     private boolean mObscureApplicationContentOnSecondaryDisplays = false;
    117 
    118     private boolean mSustainedPerformanceModeEnabled = false;
    119     private boolean mSustainedPerformanceModeCurrent = false;
    120 
    121     boolean mWallpaperMayChange = false;
    122     // During an orientation change, we track whether all windows have rendered
    123     // at the new orientation, and this will be false from changing orientation until that occurs.
    124     // For seamless rotation cases this always stays true, as the windows complete their orientation
    125     // changes 1 by 1 without disturbing global state.
    126     boolean mOrientationChangeComplete = true;
    127     boolean mWallpaperActionPending = false;
    128 
    129     private final ArrayList<Integer> mChangedStackList = new ArrayList();
    130 
    131     // State for the RemoteSurfaceTrace system used in testing. If this is enabled SurfaceControl
    132     // instances will be replaced with an instance that writes a binary representation of all
    133     // commands to mSurfaceTraceFd.
    134     boolean mSurfaceTraceEnabled;
    135     ParcelFileDescriptor mSurfaceTraceFd;
    136     RemoteEventTrace mRemoteEventTrace;
    137 
    138     private final WindowLayersController mLayersController;
    139     final WallpaperController mWallpaperController;
    140 
    141     private final Handler mHandler;
    142 
    143     private String mCloseSystemDialogsReason;
    144     private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> {
    145         if (w.mHasSurface) {
    146             try {
    147                 w.mClient.closeSystemDialogs(mCloseSystemDialogsReason);
    148             } catch (RemoteException e) {
    149             }
    150         }
    151     };
    152 
    153     private static final Consumer<WindowState> sRemoveReplacedWindowsConsumer = w -> {
    154         final AppWindowToken aToken = w.mAppToken;
    155         if (aToken != null) {
    156             aToken.removeReplacedWindowIfNeeded(w);
    157         }
    158     };
    159 
    160     RootWindowContainer(WindowManagerService service) {
    161         mService = service;
    162         mHandler = new MyHandler(service.mH.getLooper());
    163         mLayersController = new WindowLayersController(mService);
    164         mWallpaperController = new WallpaperController(mService);
    165     }
    166 
    167     WindowState computeFocusedWindow() {
    168         for (int i = mChildren.size() - 1; i >= 0; i--) {
    169             final DisplayContent dc = mChildren.get(i);
    170             final WindowState win = dc.findFocusedWindow();
    171             if (win != null) {
    172                 return win;
    173             }
    174         }
    175         return null;
    176     }
    177 
    178     /**
    179      * Get an array with display ids ordered by focus priority - last items should be given
    180      * focus first. Sparse array just maps position to displayId.
    181      */
    182     void getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder) {
    183         displaysInFocusOrder.clear();
    184 
    185         final int size = mChildren.size();
    186         for (int i = 0; i < size; ++i) {
    187             final DisplayContent displayContent = mChildren.get(i);
    188             if (displayContent.isRemovalDeferred()) {
    189                 // Don't report displays that are going to be removed soon.
    190                 continue;
    191             }
    192             displaysInFocusOrder.put(i, displayContent.getDisplayId());
    193         }
    194     }
    195 
    196     /**
    197      * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
    198      * there is a Display for the displayId.
    199      *
    200      * @param displayId The display the caller is interested in.
    201      * @return The DisplayContent associated with displayId or null if there is no Display for it.
    202      */
    203     DisplayContent getDisplayContentOrCreate(int displayId) {
    204         DisplayContent dc = getDisplayContent(displayId);
    205 
    206         if (dc == null) {
    207             final Display display = mService.mDisplayManager.getDisplay(displayId);
    208             if (display != null) {
    209                 final long callingIdentity = Binder.clearCallingIdentity();
    210                 try {
    211                     dc = createDisplayContent(display);
    212                 } finally {
    213                     Binder.restoreCallingIdentity(callingIdentity);
    214                 }
    215             }
    216         }
    217         return dc;
    218     }
    219 
    220     DisplayContent getDisplayContent(int displayId) {
    221         for (int i = mChildren.size() - 1; i >= 0; --i) {
    222             final DisplayContent current = mChildren.get(i);
    223             if (current.getDisplayId() == displayId) {
    224                 return current;
    225             }
    226         }
    227         return null;
    228     }
    229 
    230     private DisplayContent createDisplayContent(final Display display) {
    231         final DisplayContent dc = new DisplayContent(display, mService, mLayersController,
    232                 mWallpaperController);
    233         final int displayId = display.getDisplayId();
    234 
    235         if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
    236 
    237         final DisplayInfo displayInfo = dc.getDisplayInfo();
    238         final Rect rect = new Rect();
    239         mService.mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
    240         displayInfo.overscanLeft = rect.left;
    241         displayInfo.overscanTop = rect.top;
    242         displayInfo.overscanRight = rect.right;
    243         displayInfo.overscanBottom = rect.bottom;
    244         if (mService.mDisplayManagerInternal != null) {
    245             mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
    246                     displayId, displayInfo);
    247             mService.configureDisplayPolicyLocked(dc);
    248 
    249             // Tap Listeners are supported for:
    250             // 1. All physical displays (multi-display).
    251             // 2. VirtualDisplays that support virtual touch input. (Only VR for now)
    252             // TODO(multi-display): Support VirtualDisplays with no virtual touch input.
    253             if ((display.getType() != Display.TYPE_VIRTUAL
    254                     || (display.getType() == Display.TYPE_VIRTUAL
    255                         // Only VR VirtualDisplays
    256                         && displayId == mService.mVr2dDisplayId))
    257                     && mService.canDispatchPointerEvents()) {
    258                 if (DEBUG_DISPLAY) {
    259                     Slog.d(TAG,
    260                             "Registering PointerEventListener for DisplayId: " + displayId);
    261                 }
    262                 dc.mTapDetector = new TaskTapPointerEventListener(mService, dc);
    263                 mService.registerPointerEventListener(dc.mTapDetector);
    264                 if (displayId == DEFAULT_DISPLAY) {
    265                     mService.registerPointerEventListener(mService.mMousePositionTracker);
    266                 }
    267             }
    268         }
    269 
    270         return dc;
    271     }
    272 
    273     boolean isLayoutNeeded() {
    274         final int numDisplays = mChildren.size();
    275         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
    276             final DisplayContent displayContent = mChildren.get(displayNdx);
    277             if (displayContent.isLayoutNeeded()) {
    278                 return true;
    279             }
    280         }
    281         return false;
    282     }
    283 
    284     void getWindowsByName(ArrayList<WindowState> output, String name) {
    285         int objectId = 0;
    286         // See if this is an object ID.
    287         try {
    288             objectId = Integer.parseInt(name, 16);
    289             name = null;
    290         } catch (RuntimeException e) {
    291         }
    292 
    293         getWindowsByName(output, name, objectId);
    294     }
    295 
    296     private void getWindowsByName(ArrayList<WindowState> output, String name, int objectId) {
    297         forAllWindows((w) -> {
    298             if (name != null) {
    299                 if (w.mAttrs.getTitle().toString().contains(name)) {
    300                     output.add(w);
    301                 }
    302             } else if (System.identityHashCode(w) == objectId) {
    303                 output.add(w);
    304             }
    305         }, true /* traverseTopToBottom */);
    306     }
    307 
    308     /**
    309      * Returns the app window token for the input binder if it exist in the system.
    310      * NOTE: Only one AppWindowToken is allowed to exist in the system for a binder token, since
    311      * AppWindowToken represents an activity which can only exist on one display.
    312      */
    313     AppWindowToken getAppWindowToken(IBinder binder) {
    314         for (int i = mChildren.size() - 1; i >= 0; --i) {
    315             final DisplayContent dc = mChildren.get(i);
    316             final AppWindowToken atoken = dc.getAppWindowToken(binder);
    317             if (atoken != null) {
    318                 return atoken;
    319             }
    320         }
    321         return null;
    322     }
    323 
    324     /** Returns the display object the input window token is currently mapped on. */
    325     DisplayContent getWindowTokenDisplay(WindowToken token) {
    326         if (token == null) {
    327             return null;
    328         }
    329 
    330         for (int i = mChildren.size() - 1; i >= 0; --i) {
    331             final DisplayContent dc = mChildren.get(i);
    332             final WindowToken current = dc.getWindowToken(token.token);
    333             if (current == token) {
    334                 return dc;
    335             }
    336         }
    337 
    338         return null;
    339     }
    340 
    341     /**
    342      * Set new display override config and return array of ids of stacks that were changed during
    343      * update. If called for the default display, global configuration will also be updated.
    344      */
    345     int[] setDisplayOverrideConfigurationIfNeeded(Configuration newConfiguration, int displayId) {
    346         final DisplayContent displayContent = getDisplayContent(displayId);
    347         if (displayContent == null) {
    348             throw new IllegalArgumentException("Display not found for id: " + displayId);
    349         }
    350 
    351         final Configuration currentConfig = displayContent.getOverrideConfiguration();
    352         final boolean configChanged = currentConfig.diff(newConfiguration) != 0;
    353         if (!configChanged) {
    354             return null;
    355         }
    356         displayContent.onOverrideConfigurationChanged(newConfiguration);
    357 
    358         if (displayId == DEFAULT_DISPLAY) {
    359             // Override configuration of the default display duplicates global config. In this case
    360             // we also want to update the global config.
    361             return setGlobalConfigurationIfNeeded(newConfiguration);
    362         } else {
    363             return updateStackBoundsAfterConfigChange(displayId);
    364         }
    365     }
    366 
    367     private int[] setGlobalConfigurationIfNeeded(Configuration newConfiguration) {
    368         final boolean configChanged = getConfiguration().diff(newConfiguration) != 0;
    369         if (!configChanged) {
    370             return null;
    371         }
    372         onConfigurationChanged(newConfiguration);
    373         return updateStackBoundsAfterConfigChange();
    374     }
    375 
    376     @Override
    377     void onConfigurationChanged(Configuration newParentConfig) {
    378         prepareFreezingTaskBounds();
    379         super.onConfigurationChanged(newParentConfig);
    380 
    381         mService.mPolicy.onConfigurationChanged();
    382     }
    383 
    384     /**
    385      * Callback used to trigger bounds update after configuration change and get ids of stacks whose
    386      * bounds were updated.
    387      */
    388     private int[] updateStackBoundsAfterConfigChange() {
    389         mChangedStackList.clear();
    390 
    391         final int numDisplays = mChildren.size();
    392         for (int i = 0; i < numDisplays; ++i) {
    393             final DisplayContent dc = mChildren.get(i);
    394             dc.updateStackBoundsAfterConfigChange(mChangedStackList);
    395         }
    396 
    397         return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList);
    398     }
    399 
    400     /** Same as {@link #updateStackBoundsAfterConfigChange()} but only for a specific display. */
    401     private int[] updateStackBoundsAfterConfigChange(int displayId) {
    402         mChangedStackList.clear();
    403 
    404         final DisplayContent dc = getDisplayContent(displayId);
    405         dc.updateStackBoundsAfterConfigChange(mChangedStackList);
    406 
    407         return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList);
    408     }
    409 
    410     private void prepareFreezingTaskBounds() {
    411         for (int i = mChildren.size() - 1; i >= 0; i--) {
    412             mChildren.get(i).prepareFreezingTaskBounds();
    413         }
    414     }
    415 
    416     TaskStack getStackById(int stackId) {
    417         for (int i = mChildren.size() - 1; i >= 0; i--) {
    418             final DisplayContent dc = mChildren.get(i);
    419             final TaskStack stack = dc.getStackById(stackId);
    420             if (stack != null) {
    421                 return stack;
    422             }
    423         }
    424         return null;
    425     }
    426 
    427     void setSecureSurfaceState(int userId, boolean disabled) {
    428         forAllWindows((w) -> {
    429             if (w.mHasSurface && userId == UserHandle.getUserId(w.mOwnerUid)) {
    430                 w.mWinAnimator.setSecureLocked(disabled);
    431             }
    432         }, true /* traverseTopToBottom */);
    433     }
    434 
    435     void updateAppOpsState() {
    436         forAllWindows((w) -> {
    437             if (w.mAppOp == OP_NONE) {
    438                 return;
    439             }
    440             final int mode = mService.mAppOps.checkOpNoThrow(w.mAppOp, w.getOwningUid(),
    441                     w.getOwningPackage());
    442             w.setAppOpVisibilityLw(mode == MODE_ALLOWED || mode == MODE_DEFAULT);
    443         }, false /* traverseTopToBottom */);
    444     }
    445 
    446     boolean canShowStrictModeViolation(int pid) {
    447         final WindowState win = getWindow((w) -> w.mSession.mPid == pid && w.isVisibleLw());
    448         return win != null;
    449     }
    450 
    451     void closeSystemDialogs(String reason) {
    452         mCloseSystemDialogsReason = reason;
    453         forAllWindows(mCloseSystemDialogsConsumer, false /* traverseTopToBottom */);
    454     }
    455 
    456     void removeReplacedWindows() {
    457         if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
    458         mService.openSurfaceTransaction();
    459         try {
    460             forAllWindows(sRemoveReplacedWindowsConsumer, true /* traverseTopToBottom */);
    461         } finally {
    462             mService.closeSurfaceTransaction();
    463             if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
    464         }
    465     }
    466 
    467     boolean hasPendingLayoutChanges(WindowAnimator animator) {
    468         boolean hasChanges = false;
    469 
    470         final int count = mChildren.size();
    471         for (int i = 0; i < count; ++i) {
    472             final DisplayContent dc = mChildren.get(i);
    473             final int pendingChanges = animator.getPendingLayoutChanges(dc.getDisplayId());
    474             if ((pendingChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
    475                 animator.mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
    476             }
    477             if (pendingChanges != 0) {
    478                 hasChanges = true;
    479             }
    480         }
    481 
    482         return hasChanges;
    483     }
    484 
    485     boolean reclaimSomeSurfaceMemory(WindowStateAnimator winAnimator, String operation,
    486             boolean secure) {
    487         final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
    488         boolean leakedSurface = false;
    489         boolean killedApps = false;
    490 
    491         EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
    492                 winAnimator.mSession.mPid, operation);
    493 
    494         final long callingIdentity = Binder.clearCallingIdentity();
    495         try {
    496             // There was some problem...first, do a sanity check of the window list to make sure
    497             // we haven't left any dangling surfaces around.
    498 
    499             Slog.i(TAG_WM, "Out of memory for surface!  Looking for leaks...");
    500             final int numDisplays = mChildren.size();
    501             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
    502                 leakedSurface |= mChildren.get(displayNdx).destroyLeakedSurfaces();
    503             }
    504 
    505             if (!leakedSurface) {
    506                 Slog.w(TAG_WM, "No leaked surfaces; killing applications!");
    507                 final SparseIntArray pidCandidates = new SparseIntArray();
    508                 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
    509                     mChildren.get(displayNdx).forAllWindows((w) -> {
    510                         if (mService.mForceRemoves.contains(w)) {
    511                             return;
    512                         }
    513                         final WindowStateAnimator wsa = w.mWinAnimator;
    514                         if (wsa.mSurfaceController != null) {
    515                             pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
    516                         }
    517                     }, false /* traverseTopToBottom */);
    518 
    519                     if (pidCandidates.size() > 0) {
    520                         int[] pids = new int[pidCandidates.size()];
    521                         for (int i = 0; i < pids.length; i++) {
    522                             pids[i] = pidCandidates.keyAt(i);
    523                         }
    524                         try {
    525                             if (mService.mActivityManager.killPids(pids, "Free memory", secure)) {
    526                                 killedApps = true;
    527                             }
    528                         } catch (RemoteException e) {
    529                         }
    530                     }
    531                 }
    532             }
    533 
    534             if (leakedSurface || killedApps) {
    535                 // We managed to reclaim some memory, so get rid of the trouble surface and ask the
    536                 // app to request another one.
    537                 Slog.w(TAG_WM,
    538                         "Looks like we have reclaimed some memory, clearing surface for retry.");
    539                 if (surfaceController != null) {
    540                     if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
    541                             "RECOVER DESTROY", false);
    542                     winAnimator.destroySurface();
    543                     if (winAnimator.mWin.mAppToken != null
    544                             && winAnimator.mWin.mAppToken.getController() != null) {
    545                         winAnimator.mWin.mAppToken.getController().removeStartingWindow();
    546                     }
    547                 }
    548 
    549                 try {
    550                     winAnimator.mWin.mClient.dispatchGetNewSurface();
    551                 } catch (RemoteException e) {
    552                 }
    553             }
    554         } finally {
    555             Binder.restoreCallingIdentity(callingIdentity);
    556         }
    557 
    558         return leakedSurface || killedApps;
    559     }
    560 
    561     // "Something has changed!  Let's make it correct now."
    562     // TODO: Super crazy long method that should be broken down...
    563     void performSurfacePlacement(boolean recoveringMemory) {
    564         if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
    565                 + Debug.getCallers(3));
    566 
    567         int i;
    568         boolean updateInputWindowsNeeded = false;
    569 
    570         if (mService.mFocusMayChange) {
    571             mService.mFocusMayChange = false;
    572             updateInputWindowsNeeded = mService.updateFocusedWindowLocked(
    573                     UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
    574         }
    575 
    576         // Initialize state of exiting tokens.
    577         final int numDisplays = mChildren.size();
    578         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
    579             final DisplayContent displayContent = mChildren.get(displayNdx);
    580             displayContent.setExitingTokensHasVisible(false);
    581         }
    582 
    583         mHoldScreen = null;
    584         mScreenBrightness = -1;
    585         mUserActivityTimeout = -1;
    586         mObscureApplicationContentOnSecondaryDisplays = false;
    587         mSustainedPerformanceModeCurrent = false;
    588         mService.mTransactionSequence++;
    589 
    590         // TODO(multi-display):
    591         final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
    592         final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
    593         final int defaultDw = defaultInfo.logicalWidth;
    594         final int defaultDh = defaultInfo.logicalHeight;
    595 
    596         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
    597                 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
    598         mService.openSurfaceTransaction();
    599         try {
    600             applySurfaceChangesTransaction(recoveringMemory, defaultDw, defaultDh);
    601         } catch (RuntimeException e) {
    602             Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
    603         } finally {
    604             mService.closeSurfaceTransaction();
    605             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
    606                     "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
    607         }
    608 
    609         final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
    610 
    611         // If we are ready to perform an app transition, check through all of the app tokens to be
    612         // shown and see if they are ready to go.
    613         if (mService.mAppTransition.isReady()) {
    614             defaultDisplay.pendingLayoutChanges |=
    615                     surfacePlacer.handleAppTransitionReadyLocked();
    616             if (DEBUG_LAYOUT_REPEATS)
    617                 surfacePlacer.debugLayoutRepeats("after handleAppTransitionReadyLocked",
    618                         defaultDisplay.pendingLayoutChanges);
    619         }
    620 
    621         if (!mService.mAnimator.mAppWindowAnimating && mService.mAppTransition.isRunning()) {
    622             // We have finished the animation of an app transition. To do this, we have delayed a
    623             // lot of operations like showing and hiding apps, moving apps in Z-order, etc. The app
    624             // token list reflects the correct Z-order, but the window list may now be out of sync
    625             // with it. So here we will just rebuild the entire app window list. Fun!
    626             defaultDisplay.pendingLayoutChanges |=
    627                     mService.handleAnimatingStoppedAndTransitionLocked();
    628             if (DEBUG_LAYOUT_REPEATS)
    629                 surfacePlacer.debugLayoutRepeats("after handleAnimStopAndXitionLock",
    630                         defaultDisplay.pendingLayoutChanges);
    631         }
    632 
    633         if (mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
    634                 && !mService.mAppTransition.isReady()) {
    635             // At this point, there was a window with a wallpaper that was force hiding other
    636             // windows behind it, but now it is going away. This may be simple -- just animate away
    637             // the wallpaper and its window -- or it may be hard -- the wallpaper now needs to be
    638             // shown behind something that was hidden.
    639             defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
    640             if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
    641                     "after animateAwayWallpaperLocked", defaultDisplay.pendingLayoutChanges);
    642         }
    643         mWallpaperForceHidingChanged = false;
    644 
    645         if (mWallpaperMayChange) {
    646             if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change!  Adjusting");
    647             defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
    648             if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("WallpaperMayChange",
    649                     defaultDisplay.pendingLayoutChanges);
    650         }
    651 
    652         if (mService.mFocusMayChange) {
    653             mService.mFocusMayChange = false;
    654             if (mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
    655                     false /*updateInputWindows*/)) {
    656                 updateInputWindowsNeeded = true;
    657                 defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
    658             }
    659         }
    660 
    661         if (isLayoutNeeded()) {
    662             defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
    663             if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("mLayoutNeeded",
    664                     defaultDisplay.pendingLayoutChanges);
    665         }
    666 
    667         final ArraySet<DisplayContent> touchExcludeRegionUpdateDisplays = handleResizingWindows();
    668 
    669         if (DEBUG_ORIENTATION && mService.mDisplayFrozen) Slog.v(TAG,
    670                 "With display frozen, orientationChangeComplete=" + mOrientationChangeComplete);
    671         if (mOrientationChangeComplete) {
    672             if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
    673                 mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
    674                 mService.mLastFinishedFreezeSource = mLastWindowFreezeSource;
    675                 mService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT);
    676             }
    677             mService.stopFreezingDisplayLocked();
    678         }
    679 
    680         // Destroy the surface of any windows that are no longer visible.
    681         boolean wallpaperDestroyed = false;
    682         i = mService.mDestroySurface.size();
    683         if (i > 0) {
    684             do {
    685                 i--;
    686                 WindowState win = mService.mDestroySurface.get(i);
    687                 win.mDestroying = false;
    688                 if (mService.mInputMethodWindow == win) {
    689                     mService.setInputMethodWindowLocked(null);
    690                 }
    691                 if (win.getDisplayContent().mWallpaperController.isWallpaperTarget(win)) {
    692                     wallpaperDestroyed = true;
    693                 }
    694                 win.destroyOrSaveSurfaceUnchecked();
    695             } while (i > 0);
    696             mService.mDestroySurface.clear();
    697         }
    698 
    699         // Time to remove any exiting tokens?
    700         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
    701             final DisplayContent displayContent = mChildren.get(displayNdx);
    702             displayContent.removeExistingTokensIfPossible();
    703         }
    704 
    705         if (wallpaperDestroyed) {
    706             defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
    707             defaultDisplay.setLayoutNeeded();
    708         }
    709 
    710         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
    711             final DisplayContent displayContent = mChildren.get(displayNdx);
    712             if (displayContent.pendingLayoutChanges != 0) {
    713                 displayContent.setLayoutNeeded();
    714             }
    715         }
    716 
    717         // Finally update all input windows now that the window changes have stabilized.
    718         mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
    719 
    720         mService.setHoldScreenLocked(mHoldScreen);
    721         if (!mService.mDisplayFrozen) {
    722             final int brightness = mScreenBrightness < 0 || mScreenBrightness > 1.0f
    723                     ? -1 : toBrightnessOverride(mScreenBrightness);
    724 
    725             // Post these on a handler such that we don't call into power manager service while
    726             // holding the window manager lock to avoid lock contention with power manager lock.
    727             mHandler.obtainMessage(SET_SCREEN_BRIGHTNESS_OVERRIDE, brightness, 0).sendToTarget();
    728             mHandler.obtainMessage(SET_USER_ACTIVITY_TIMEOUT, mUserActivityTimeout).sendToTarget();
    729         }
    730 
    731         if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) {
    732             mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent;
    733             mService.mPowerManagerInternal.powerHint(
    734                     PowerHint.SUSTAINED_PERFORMANCE,
    735                     (mSustainedPerformanceModeEnabled ? 1 : 0));
    736         }
    737 
    738         if (mService.mTurnOnScreen) {
    739             if (mService.mAllowTheaterModeWakeFromLayout
    740                     || Settings.Global.getInt(mService.mContext.getContentResolver(),
    741                     Settings.Global.THEATER_MODE_ON, 0) == 0) {
    742                 if (DEBUG_VISIBILITY || DEBUG_POWER) {
    743                     Slog.v(TAG, "Turning screen on after layout!");
    744                 }
    745                 mService.mPowerManager.wakeUp(SystemClock.uptimeMillis(),
    746                         "android.server.wm:TURN_ON");
    747             }
    748             mService.mTurnOnScreen = false;
    749         }
    750 
    751         if (mUpdateRotation) {
    752             if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
    753             // TODO(multi-display): Update rotation for different displays separately.
    754             final int displayId = defaultDisplay.getDisplayId();
    755             if (defaultDisplay.updateRotationUnchecked(false /* inTransaction */)) {
    756                 mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
    757             } else {
    758                 mUpdateRotation = false;
    759             }
    760             // Update rotation of VR virtual display separately. Currently this is the only kind of
    761             // secondary display that can be rotated because of the single-display limitations in
    762             // PhoneWindowManager.
    763             final DisplayContent vrDisplay = mService.mVr2dDisplayId != INVALID_DISPLAY
    764                     ? getDisplayContent(mService.mVr2dDisplayId) : null;
    765             if (vrDisplay != null && vrDisplay.updateRotationUnchecked(false /* inTransaction */)) {
    766                 mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mService.mVr2dDisplayId)
    767                         .sendToTarget();
    768             }
    769         }
    770 
    771         if (mService.mWaitingForDrawnCallback != null ||
    772                 (mOrientationChangeComplete && !defaultDisplay.isLayoutNeeded()
    773                         && !mUpdateRotation)) {
    774             mService.checkDrawnWindowsLocked();
    775         }
    776 
    777         final int N = mService.mPendingRemove.size();
    778         if (N > 0) {
    779             if (mService.mPendingRemoveTmp.length < N) {
    780                 mService.mPendingRemoveTmp = new WindowState[N+10];
    781             }
    782             mService.mPendingRemove.toArray(mService.mPendingRemoveTmp);
    783             mService.mPendingRemove.clear();
    784             ArrayList<DisplayContent> displayList = new ArrayList();
    785             for (i = 0; i < N; i++) {
    786                 final WindowState w = mService.mPendingRemoveTmp[i];
    787                 w.removeImmediately();
    788                 final DisplayContent displayContent = w.getDisplayContent();
    789                 if (displayContent != null && !displayList.contains(displayContent)) {
    790                     displayList.add(displayContent);
    791                 }
    792             }
    793 
    794             for (int j = displayList.size() - 1; j >= 0; --j) {
    795                 final DisplayContent dc = displayList.get(j);
    796                 dc.assignWindowLayers(true /*setLayoutNeeded*/);
    797             }
    798         }
    799 
    800         // Remove all deferred displays stacks, tasks, and activities.
    801         for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
    802             mChildren.get(displayNdx).checkCompleteDeferredRemoval();
    803         }
    804 
    805         if (updateInputWindowsNeeded) {
    806             mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
    807         }
    808         mService.setFocusTaskRegionLocked(null);
    809         if (touchExcludeRegionUpdateDisplays != null) {
    810             final DisplayContent focusedDc = mService.mFocusedApp != null
    811                     ? mService.mFocusedApp.getDisplayContent() : null;
    812             for (DisplayContent dc : touchExcludeRegionUpdateDisplays) {
    813                 // The focused DisplayContent was recalcuated in setFocusTaskRegionLocked
    814                 if (focusedDc != dc) {
    815                     dc.setTouchExcludeRegion(null /* focusedTask */);
    816                 }
    817             }
    818         }
    819 
    820         // Check to see if we are now in a state where the screen should
    821         // be enabled, because the window obscured flags have changed.
    822         mService.enableScreenIfNeededLocked();
    823 
    824         mService.scheduleAnimationLocked();
    825         mService.mWindowPlacerLocked.destroyPendingSurfaces();
    826 
    827         if (DEBUG_WINDOW_TRACE) Slog.e(TAG,
    828                 "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating());
    829     }
    830 
    831     private void applySurfaceChangesTransaction(boolean recoveringMemory, int defaultDw,
    832             int defaultDh) {
    833         mHoldScreenWindow = null;
    834         mObscuringWindow = null;
    835 
    836         // TODO(multi-display): Support these features on secondary screens.
    837         if (mService.mWatermark != null) {
    838             mService.mWatermark.positionSurface(defaultDw, defaultDh);
    839         }
    840         if (mService.mStrictModeFlash != null) {
    841             mService.mStrictModeFlash.positionSurface(defaultDw, defaultDh);
    842         }
    843         if (mService.mCircularDisplayMask != null) {
    844             mService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh,
    845                     mService.getDefaultDisplayRotation());
    846         }
    847         if (mService.mEmulatorDisplayOverlay != null) {
    848             mService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
    849                     mService.getDefaultDisplayRotation());
    850         }
    851 
    852         boolean focusDisplayed = false;
    853 
    854         final int count = mChildren.size();
    855         for (int j = 0; j < count; ++j) {
    856             final DisplayContent dc = mChildren.get(j);
    857             focusDisplayed |= dc.applySurfaceChangesTransaction(recoveringMemory);
    858         }
    859 
    860         if (focusDisplayed) {
    861             mService.mH.sendEmptyMessage(REPORT_LOSING_FOCUS);
    862         }
    863 
    864         // Give the display manager a chance to adjust properties like display rotation if it needs
    865         // to.
    866         mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
    867     }
    868 
    869     /**
    870      * Handles resizing windows during surface placement.
    871      *
    872      * @return A set of any DisplayContent whose touch exclude region needs to be recalculated due
    873      *         to a tap-exclude window resizing, or null if no such DisplayContents were found.
    874      */
    875     private ArraySet<DisplayContent> handleResizingWindows() {
    876         ArraySet<DisplayContent> touchExcludeRegionUpdateSet = null;
    877         for (int i = mService.mResizingWindows.size() - 1; i >= 0; i--) {
    878             WindowState win = mService.mResizingWindows.get(i);
    879             if (win.mAppFreezing) {
    880                 // Don't remove this window until rotation has completed.
    881                 continue;
    882             }
    883             // Discard the saved surface if window size is changed, it can't be reused.
    884             if (win.mAppToken != null) {
    885                 win.mAppToken.destroySavedSurfaces();
    886             }
    887             win.reportResized();
    888             mService.mResizingWindows.remove(i);
    889             if (WindowManagerService.excludeWindowTypeFromTapOutTask(win.mAttrs.type)) {
    890                 final DisplayContent dc = win.getDisplayContent();
    891                 if (touchExcludeRegionUpdateSet == null) {
    892                     touchExcludeRegionUpdateSet = new ArraySet<>();
    893                 }
    894                 touchExcludeRegionUpdateSet.add(dc);
    895             }
    896         }
    897         return touchExcludeRegionUpdateSet;
    898     }
    899 
    900     /**
    901      * @param w WindowState this method is applied to.
    902      * @param obscured True if there is a window on top of this obscuring the display.
    903      * @param syswin System window?
    904      * @return True when the display contains content to show the user. When false, the display
    905      *          manager may choose to mirror or blank the display.
    906      */
    907     boolean handleNotObscuredLocked(WindowState w, boolean obscured, boolean syswin) {
    908         final WindowManager.LayoutParams attrs = w.mAttrs;
    909         final int attrFlags = attrs.flags;
    910         final boolean canBeSeen = w.isDisplayedLw();
    911         final int privateflags = attrs.privateFlags;
    912         boolean displayHasContent = false;
    913 
    914         if (w.mHasSurface && canBeSeen) {
    915             if ((attrFlags & FLAG_KEEP_SCREEN_ON) != 0) {
    916                 mHoldScreen = w.mSession;
    917                 mHoldScreenWindow = w;
    918             } else if (DEBUG_KEEP_SCREEN_ON && w == mService.mLastWakeLockHoldingWindow) {
    919                 Slog.d(TAG_KEEP_SCREEN_ON, "handleNotObscuredLocked: " + w + " was holding "
    920                         + "screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by"
    921                         + Debug.getCallers(10));
    922             }
    923             if (!syswin && w.mAttrs.screenBrightness >= 0 && mScreenBrightness < 0) {
    924                 mScreenBrightness = w.mAttrs.screenBrightness;
    925             }
    926             if (!syswin && w.mAttrs.userActivityTimeout >= 0 && mUserActivityTimeout < 0) {
    927                 mUserActivityTimeout = w.mAttrs.userActivityTimeout;
    928             }
    929 
    930             final int type = attrs.type;
    931             // This function assumes that the contents of the default display are processed first
    932             // before secondary displays.
    933             final DisplayContent displayContent = w.getDisplayContent();
    934             if (displayContent != null && displayContent.isDefaultDisplay) {
    935                 // While a dream or keyguard is showing, obscure ordinary application content on
    936                 // secondary displays (by forcibly enabling mirroring unless there is other content
    937                 // we want to show) but still allow opaque keyguard dialogs to be shown.
    938                 if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
    939                     mObscureApplicationContentOnSecondaryDisplays = true;
    940                 }
    941                 displayHasContent = true;
    942             } else if (displayContent != null &&
    943                     (!mObscureApplicationContentOnSecondaryDisplays
    944                             || (obscured && type == TYPE_KEYGUARD_DIALOG))) {
    945                 // Allow full screen keyguard presentation dialogs to be seen.
    946                 displayHasContent = true;
    947             }
    948             if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) {
    949                 mSustainedPerformanceModeCurrent = true;
    950             }
    951         }
    952 
    953         return displayHasContent;
    954     }
    955 
    956     boolean copyAnimToLayoutParams() {
    957         boolean doRequest = false;
    958 
    959         final int bulkUpdateParams = mService.mAnimator.mBulkUpdateParams;
    960         if ((bulkUpdateParams & SET_UPDATE_ROTATION) != 0) {
    961             mUpdateRotation = true;
    962             doRequest = true;
    963         }
    964         if ((bulkUpdateParams & SET_WALLPAPER_MAY_CHANGE) != 0) {
    965             mWallpaperMayChange = true;
    966             doRequest = true;
    967         }
    968         if ((bulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0) {
    969             mWallpaperForceHidingChanged = true;
    970             doRequest = true;
    971         }
    972         if ((bulkUpdateParams & SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
    973             mOrientationChangeComplete = false;
    974         } else {
    975             mOrientationChangeComplete = true;
    976             mLastWindowFreezeSource = mService.mAnimator.mLastWindowFreezeSource;
    977             if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
    978                 doRequest = true;
    979             }
    980         }
    981         if ((bulkUpdateParams & SET_TURN_ON_SCREEN) != 0) {
    982             mService.mTurnOnScreen = true;
    983         }
    984         if ((bulkUpdateParams & SET_WALLPAPER_ACTION_PENDING) != 0) {
    985             mWallpaperActionPending = true;
    986         }
    987 
    988         return doRequest;
    989     }
    990 
    991     private static int toBrightnessOverride(float value) {
    992         return (int)(value * PowerManager.BRIGHTNESS_ON);
    993     }
    994 
    995     private final class MyHandler extends Handler {
    996 
    997         public MyHandler(Looper looper) {
    998             super(looper);
    999         }
   1000 
   1001         @Override
   1002         public void handleMessage(Message msg) {
   1003             switch (msg.what) {
   1004                 case SET_SCREEN_BRIGHTNESS_OVERRIDE:
   1005                     mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
   1006                             msg.arg1);
   1007                     break;
   1008                 case SET_USER_ACTIVITY_TIMEOUT:
   1009                     mService.mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
   1010                             (Long) msg.obj);
   1011                     break;
   1012                 default:
   1013                     break;
   1014             }
   1015         }
   1016     }
   1017 
   1018     void enableSurfaceTrace(ParcelFileDescriptor pfd) {
   1019         final FileDescriptor fd = pfd.getFileDescriptor();
   1020         if (mSurfaceTraceEnabled) {
   1021             disableSurfaceTrace();
   1022         }
   1023         mSurfaceTraceEnabled = true;
   1024         mRemoteEventTrace = new RemoteEventTrace(mService, fd);
   1025         mSurfaceTraceFd = pfd;
   1026         for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
   1027             final DisplayContent dc = mChildren.get(displayNdx);
   1028             dc.enableSurfaceTrace(fd);
   1029         }
   1030     }
   1031 
   1032     void disableSurfaceTrace() {
   1033         mSurfaceTraceEnabled = false;
   1034         mRemoteEventTrace = null;
   1035         mSurfaceTraceFd = null;
   1036         for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
   1037             final DisplayContent dc = mChildren.get(displayNdx);
   1038             dc.disableSurfaceTrace();
   1039         }
   1040     }
   1041 
   1042     void dumpDisplayContents(PrintWriter pw) {
   1043         pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
   1044         if (mService.mDisplayReady) {
   1045             final int count = mChildren.size();
   1046             for (int i = 0; i < count; ++i) {
   1047                 final DisplayContent displayContent = mChildren.get(i);
   1048                 displayContent.dump("  ", pw);
   1049             }
   1050         } else {
   1051             pw.println("  NO DISPLAY");
   1052         }
   1053     }
   1054 
   1055     void dumpLayoutNeededDisplayIds(PrintWriter pw) {
   1056         if (!isLayoutNeeded()) {
   1057             return;
   1058         }
   1059         pw.print("  mLayoutNeeded on displays=");
   1060         final int count = mChildren.size();
   1061         for (int displayNdx = 0; displayNdx < count; ++displayNdx) {
   1062             final DisplayContent displayContent = mChildren.get(displayNdx);
   1063             if (displayContent.isLayoutNeeded()) {
   1064                 pw.print(displayContent.getDisplayId());
   1065             }
   1066         }
   1067         pw.println();
   1068     }
   1069 
   1070     void dumpWindowsNoHeader(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows) {
   1071         final int[] index = new int[1];
   1072         forAllWindows((w) -> {
   1073             if (windows == null || windows.contains(w)) {
   1074                 pw.println("  Window #" + index[0] + " " + w + ":");
   1075                 w.dump(pw, "    ", dumpAll || windows != null);
   1076                 index[0] = index[0] + 1;
   1077             }
   1078         }, true /* traverseTopToBottom */);
   1079     }
   1080 
   1081     void dumpTokens(PrintWriter pw, boolean dumpAll) {
   1082         pw.println("  All tokens:");
   1083         for (int i = mChildren.size() - 1; i >= 0; --i) {
   1084             mChildren.get(i).dumpTokens(pw, dumpAll);
   1085         }
   1086     }
   1087 
   1088     @Override
   1089     String getName() {
   1090         return "ROOT";
   1091     }
   1092 }
   1093