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 
RootWindowContainer(WindowManagerService service)153     RootWindowContainer(WindowManagerService service) {
154         super(service);
155         mHandler = new MyHandler(service.mH.getLooper());
156         mWallpaperController = new WallpaperController(mService);
157     }
158 
computeFocusedWindow()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      */
getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder)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 
getDisplayContent(int displayId)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 
createDisplayContent(final Display display, DisplayWindowController controller)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 
isLayoutNeeded()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 
getWindowsByName(ArrayList<WindowState> output, String name)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 
getWindowsByName(ArrayList<WindowState> output, String name, int objectId)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      */
getAppWindowToken(IBinder binder)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. */
getWindowTokenDisplay(WindowToken token)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      */
setDisplayOverrideConfigurationIfNeeded(Configuration newConfiguration, int displayId)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 
setGlobalConfigurationIfNeeded(Configuration newConfiguration, List<TaskStack> changedStacks)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
onConfigurationChanged(Configuration newParentConfig)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      */
updateStackBoundsAfterConfigChange(List<TaskStack> changedStacks)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. */
updateStackBoundsAfterConfigChange(int displayId, List<TaskStack> changedStacks)398     private void updateStackBoundsAfterConfigChange(int displayId, List<TaskStack> changedStacks) {
399         final DisplayContent dc = getDisplayContent(displayId);
400         dc.updateStackBoundsAfterConfigChange(changedStacks);
401     }
402 
prepareFreezingTaskBounds()403     private void prepareFreezingTaskBounds() {
404         for (int i = mChildren.size() - 1; i >= 0; i--) {
405             mChildren.get(i).prepareFreezingTaskBounds();
406         }
407     }
408 
getStack(int windowingMode, int activityType)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 
setSecureSurfaceState(int userId, boolean disabled)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 
updateHiddenWhileSuspendedState(final ArraySet<String> packages, final boolean suspended)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 
updateAppOpsState()436     void updateAppOpsState() {
437         forAllWindows((w) -> {
438             w.updateAppOpsState();
439         }, false /* traverseTopToBottom */);
440     }
441 
canShowStrictModeViolation(int pid)442     boolean canShowStrictModeViolation(int pid) {
443         final WindowState win = getWindow((w) -> w.mSession.mPid == pid && w.isVisibleLw());
444         return win != null;
445     }
446 
closeSystemDialogs(String reason)447     void closeSystemDialogs(String reason) {
448         mCloseSystemDialogsReason = reason;
449         forAllWindows(mCloseSystemDialogsConsumer, false /* traverseTopToBottom */);
450     }
451 
removeReplacedWindows()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 
hasPendingLayoutChanges(WindowAnimator animator)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 
reclaimSomeSurfaceMemory(WindowStateAnimator winAnimator, String operation, boolean secure)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...
performSurfacePlacement(boolean recoveringMemory)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 
applySurfaceChangesTransaction(boolean recoveringMemory, int defaultDw, int defaultDh)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      */
handleResizingWindows()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      */
handleNotObscuredLocked(WindowState w, boolean obscured, boolean syswin)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 
copyAnimToLayoutParams()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 
toBrightnessOverride(float value)994     private static int toBrightnessOverride(float value) {
995         return (int)(value * PowerManager.BRIGHTNESS_ON);
996     }
997 
998     private final class MyHandler extends Handler {
999 
MyHandler(Looper looper)1000         public MyHandler(Looper looper) {
1001             super(looper);
1002         }
1003 
1004         @Override
handleMessage(Message msg)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 
dumpDisplayContents(PrintWriter pw)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 
dumpLayoutNeededDisplayIds(PrintWriter pw)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 
dumpWindowsNoHeader(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows)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 
dumpTokens(PrintWriter pw, boolean dumpAll)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
writeToProto(ProtoOutputStream proto, long fieldId, boolean trim)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
getName()1088     String getName() {
1089         return "ROOT";
1090     }
1091 
1092     @Override
scheduleAnimation()1093     void scheduleAnimation() {
1094         mService.scheduleAnimationLocked();
1095     }
1096 }
1097