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