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