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