DisplayContent.java revision 9adfe5776d42c9ddfd4394958993304c9d355229
1/* 2 * Copyright (C) 2012 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 17package com.android.server.wm; 18 19import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; 20import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; 21import static android.app.ActivityManager.StackId.HOME_STACK_ID; 22import static android.app.ActivityManager.StackId.PINNED_STACK_ID; 23import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; 24import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; 25import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 26import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 27import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 28import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 29import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 30import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 31import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; 32import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 33import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 34import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 35import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS; 36import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; 37import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT; 38import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 39import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; 40import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 41import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; 42 43import android.app.ActivityManager.StackId; 44import android.graphics.Rect; 45import android.graphics.Region; 46import android.graphics.Region.Op; 47import android.hardware.display.DisplayManagerInternal; 48import android.os.Debug; 49import android.util.DisplayMetrics; 50import android.util.Slog; 51import android.view.Display; 52import android.view.DisplayInfo; 53import android.view.IWindow; 54import android.view.Surface; 55import android.view.animation.Animation; 56import com.android.internal.util.FastPrintWriter; 57 58import java.io.PrintWriter; 59import java.io.StringWriter; 60import java.util.ArrayList; 61import java.util.Arrays; 62 63class DisplayContentList extends ArrayList<DisplayContent> { 64} 65 66/** 67 * Utility class for keeping track of the WindowStates and other pertinent contents of a 68 * particular Display. 69 * 70 * IMPORTANT: No method from this class should ever be used without holding 71 * WindowManagerService.mWindowMap. 72 */ 73class DisplayContent { 74 75 /** Unique identifier of this stack. */ 76 private final int mDisplayId; 77 78 /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element 79 * from mDisplayWindows; */ 80 private final WindowList mWindows = new WindowList(); 81 82 int mInitialDisplayWidth = 0; 83 int mInitialDisplayHeight = 0; 84 int mInitialDisplayDensity = 0; 85 int mBaseDisplayWidth = 0; 86 int mBaseDisplayHeight = 0; 87 int mBaseDisplayDensity = 0; 88 boolean mDisplayScalingDisabled; 89 private final DisplayInfo mDisplayInfo = new DisplayInfo(); 90 private final Display mDisplay; 91 private final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 92 93 Rect mBaseDisplayRect = new Rect(); 94 private Rect mContentRect = new Rect(); 95 96 // Accessed directly by all users. 97 boolean layoutNeeded; 98 int pendingLayoutChanges; 99 final boolean isDefaultDisplay; 100 101 /** Window tokens that are in the process of exiting, but still on screen for animations. */ 102 final ArrayList<WindowToken> mExitingTokens = new ArrayList<>(); 103 104 /** Array containing all TaskStacks on this display. Array 105 * is stored in display order with the current bottom stack at 0. */ 106 private final ArrayList<TaskStack> mStacks = new ArrayList<>(); 107 108 /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack 109 * (except a future lockscreen TaskStack) moves to the top. */ 110 private TaskStack mHomeStack = null; 111 112 /** Detect user tapping outside of current focused task bounds .*/ 113 TaskTapPointerEventListener mTapDetector; 114 115 /** Detect user tapping outside of current focused stack bounds .*/ 116 private Region mTouchExcludeRegion = new Region(); 117 118 /** Save allocating when calculating rects */ 119 private final Rect mTmpRect = new Rect(); 120 private final Rect mTmpRect2 = new Rect(); 121 private final Region mTmpRegion = new Region(); 122 123 /** For gathering Task objects in order. */ 124 private final ArrayList<Task> mTmpTaskHistory = new ArrayList<Task>(); 125 126 final WindowManagerService mService; 127 128 /** Remove this display when animation on it has completed. */ 129 boolean mDeferredRemoval; 130 131 final DockedStackDividerController mDividerControllerLocked; 132 133 final DimLayerController mDimLayerController; 134 135 final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>(); 136 137 /** Used when rebuilding window list to keep track of windows that have been removed. */ 138 private WindowState[] mRebuildTmp = new WindowState[20]; 139 140 /** 141 * @param display May not be null. 142 * @param service You know. 143 */ 144 DisplayContent(Display display, WindowManagerService service) { 145 mDisplay = display; 146 mDisplayId = display.getDisplayId(); 147 display.getDisplayInfo(mDisplayInfo); 148 display.getMetrics(mDisplayMetrics); 149 isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY; 150 mService = service; 151 initializeDisplayBaseInfo(); 152 mDividerControllerLocked = new DockedStackDividerController(service, this); 153 mDimLayerController = new DimLayerController(this); 154 } 155 156 int getDisplayId() { 157 return mDisplayId; 158 } 159 160 WindowList getWindowList() { 161 return mWindows; 162 } 163 164 Display getDisplay() { 165 return mDisplay; 166 } 167 168 DisplayInfo getDisplayInfo() { 169 return mDisplayInfo; 170 } 171 172 DisplayMetrics getDisplayMetrics() { 173 return mDisplayMetrics; 174 } 175 176 DockedStackDividerController getDockedDividerController() { 177 return mDividerControllerLocked; 178 } 179 180 /** 181 * Returns true if the specified UID has access to this display. 182 */ 183 public boolean hasAccess(int uid) { 184 return mDisplay.hasAccess(uid); 185 } 186 187 public boolean isPrivate() { 188 return (mDisplay.getFlags() & Display.FLAG_PRIVATE) != 0; 189 } 190 191 ArrayList<TaskStack> getStacks() { 192 return mStacks; 193 } 194 195 /** 196 * Retrieve the tasks on this display in stack order from the bottommost TaskStack up. 197 * @return All the Tasks, in order, on this display. 198 */ 199 ArrayList<Task> getTasks() { 200 mTmpTaskHistory.clear(); 201 final int numStacks = mStacks.size(); 202 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 203 mTmpTaskHistory.addAll(mStacks.get(stackNdx).getTasks()); 204 } 205 return mTmpTaskHistory; 206 } 207 208 TaskStack getHomeStack() { 209 if (mHomeStack == null && mDisplayId == Display.DEFAULT_DISPLAY) { 210 Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this); 211 } 212 return mHomeStack; 213 } 214 215 TaskStack getStackById(int stackId) { 216 for (int i = mStacks.size() - 1; i >= 0; --i) { 217 final TaskStack stack = mStacks.get(i); 218 if (stack.mStackId == stackId) { 219 return stack; 220 } 221 } 222 return null; 223 } 224 225 void onAppTransitionDone() { 226 for (int i = mStacks.size() - 1; i >= 0; --i) { 227 final TaskStack stack = mStacks.get(i); 228 stack.onAppTransitionDone(); 229 } 230 231 rebuildAppWindowList(); 232 } 233 234 int getOrientation() { 235 // TODO: Most of the logic here can be removed once this class is converted to use 236 // WindowContainer which has an abstract implementation of getOrientation that 237 // should cover this. 238 if (mService.isStackVisibleLocked(DOCKED_STACK_ID) 239 || mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) { 240 // Apps and their containers are not allowed to specify an orientation while the docked 241 // or freeform stack is visible...except for the home stack/task if the docked stack is 242 // minimized and it actually set something. 243 if (mHomeStack.isVisible() && mDividerControllerLocked.isMinimizedDock()) { 244 final int orientation = mHomeStack.getOrientation(); 245 if (orientation != SCREEN_ORIENTATION_UNSET) { 246 return orientation; 247 } 248 } 249 return SCREEN_ORIENTATION_UNSPECIFIED; 250 } 251 252 for (int i = mStacks.size() - 1; i >= 0; --i) { 253 final TaskStack stack = mStacks.get(i); 254 if (!stack.isVisible()) { 255 continue; 256 } 257 258 final int orientation = stack.getOrientation(); 259 260 if (orientation == SCREEN_ORIENTATION_BEHIND) { 261 continue; 262 } 263 264 if (orientation != SCREEN_ORIENTATION_UNSET) { 265 if (stack.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) { 266 return orientation; 267 } 268 } 269 } 270 271 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 272 "No app is requesting an orientation, return " + mService.mLastOrientation); 273 // The next app has not been requested to be visible, so we keep the current orientation 274 // to prevent freezing/unfreezing the display too early. 275 return mService.mLastOrientation; 276 } 277 278 void updateDisplayInfo() { 279 mDisplay.getDisplayInfo(mDisplayInfo); 280 mDisplay.getMetrics(mDisplayMetrics); 281 for (int i = mStacks.size() - 1; i >= 0; --i) { 282 mStacks.get(i).updateDisplayInfo(null); 283 } 284 } 285 286 void initializeDisplayBaseInfo() { 287 final DisplayManagerInternal displayManagerInternal = mService.mDisplayManagerInternal; 288 if (displayManagerInternal != null) { 289 // Bootstrap the default logical display from the display manager. 290 final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId); 291 if (newDisplayInfo != null) { 292 mDisplayInfo.copyFrom(newDisplayInfo); 293 } 294 } 295 296 mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth; 297 mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight; 298 mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi; 299 mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight); 300 } 301 302 void getLogicalDisplayRect(Rect out) { 303 // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked. 304 final int orientation = mDisplayInfo.rotation; 305 boolean rotated = (orientation == Surface.ROTATION_90 306 || orientation == Surface.ROTATION_270); 307 final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; 308 final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; 309 int width = mDisplayInfo.logicalWidth; 310 int left = (physWidth - width) / 2; 311 int height = mDisplayInfo.logicalHeight; 312 int top = (physHeight - height) / 2; 313 out.set(left, top, left + width, top + height); 314 } 315 316 void getContentRect(Rect out) { 317 out.set(mContentRect); 318 } 319 320 /** Refer to {@link WindowManagerService#attachStack(int, int, boolean)} */ 321 void attachStack(TaskStack stack, boolean onTop) { 322 if (stack.mStackId == HOME_STACK_ID) { 323 if (mHomeStack != null) { 324 throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first."); 325 } 326 mHomeStack = stack; 327 } 328 if (onTop) { 329 mStacks.add(stack); 330 } else { 331 mStacks.add(0, stack); 332 } 333 layoutNeeded = true; 334 } 335 336 void moveStack(TaskStack stack, boolean toTop) { 337 if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) { 338 // This stack is always-on-top silly... 339 Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + stack + " to bottom"); 340 return; 341 } 342 343 if (!mStacks.remove(stack)) { 344 Slog.wtf(TAG_WM, "moving stack that was not added: " + stack, new Throwable()); 345 } 346 347 int addIndex = toTop ? mStacks.size() : 0; 348 349 if (toTop 350 && mService.isStackVisibleLocked(PINNED_STACK_ID) 351 && stack.mStackId != PINNED_STACK_ID) { 352 // The pinned stack is always the top most stack (always-on-top) when it is visible. 353 // So, stack is moved just below the pinned stack. 354 addIndex--; 355 TaskStack topStack = mStacks.get(addIndex); 356 if (topStack.mStackId != PINNED_STACK_ID) { 357 throw new IllegalStateException("Pinned stack isn't top stack??? " + mStacks); 358 } 359 } 360 mStacks.add(addIndex, stack); 361 } 362 363 void detachStack(TaskStack stack) { 364 mDimLayerController.removeDimLayerUser(stack); 365 mStacks.remove(stack); 366 } 367 368 /** 369 * Propagate the new bounds to all child stacks. 370 * @param contentRect The bounds to apply at the top level. 371 */ 372 void resize(Rect contentRect) { 373 mContentRect.set(contentRect); 374 } 375 376 int taskIdFromPoint(int x, int y) { 377 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 378 TaskStack stack = mStacks.get(stackNdx); 379 stack.getBounds(mTmpRect); 380 if (!mTmpRect.contains(x, y) || stack.isAdjustedForMinimizedDockedStack()) { 381 continue; 382 } 383 final ArrayList<Task> tasks = stack.getTasks(); 384 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 385 final Task task = tasks.get(taskNdx); 386 final WindowState win = task.getTopVisibleAppMainWindow(); 387 if (win == null) { 388 continue; 389 } 390 // We need to use the task's dim bounds (which is derived from the visible 391 // bounds of its apps windows) for any touch-related tests. Can't use 392 // the task's original bounds because it might be adjusted to fit the 393 // content frame. For example, the presence of the IME adjusting the 394 // windows frames when the app window is the IME target. 395 task.getDimBounds(mTmpRect); 396 if (mTmpRect.contains(x, y)) { 397 return task.mTaskId; 398 } 399 } 400 } 401 return -1; 402 } 403 404 /** 405 * Find the task whose outside touch area (for resizing) (x, y) falls within. 406 * Returns null if the touch doesn't fall into a resizing area. 407 */ 408 Task findTaskForResizePoint(int x, int y) { 409 final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics); 410 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 411 TaskStack stack = mStacks.get(stackNdx); 412 if (!StackId.isTaskResizeAllowed(stack.mStackId)) { 413 break; 414 } 415 final ArrayList<Task> tasks = stack.getTasks(); 416 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 417 final Task task = tasks.get(taskNdx); 418 if (task.isFullscreen()) { 419 return null; 420 } 421 422 // We need to use the task's dim bounds (which is derived from the visible 423 // bounds of its apps windows) for any touch-related tests. Can't use 424 // the task's original bounds because it might be adjusted to fit the 425 // content frame. One example is when the task is put to top-left quadrant, 426 // the actual visible area would not start at (0,0) after it's adjusted 427 // for the status bar. 428 task.getDimBounds(mTmpRect); 429 mTmpRect.inset(-delta, -delta); 430 if (mTmpRect.contains(x, y)) { 431 mTmpRect.inset(delta, delta); 432 if (!mTmpRect.contains(x, y)) { 433 return task; 434 } 435 // User touched inside the task. No need to look further, 436 // focus transfer will be handled in ACTION_UP. 437 return null; 438 } 439 } 440 } 441 return null; 442 } 443 444 void setTouchExcludeRegion(Task focusedTask) { 445 mTouchExcludeRegion.set(mBaseDisplayRect); 446 final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics); 447 boolean addBackFocusedTask = false; 448 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 449 TaskStack stack = mStacks.get(stackNdx); 450 final ArrayList<Task> tasks = stack.getTasks(); 451 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 452 final Task task = tasks.get(taskNdx); 453 AppWindowToken token = task.getTopVisibleAppToken(); 454 if (token == null || !token.isVisible()) { 455 continue; 456 } 457 458 /** 459 * Exclusion region is the region that TapDetector doesn't care about. 460 * Here we want to remove all non-focused tasks from the exclusion region. 461 * We also remove the outside touch area for resizing for all freeform 462 * tasks (including the focused). 463 * 464 * We save the focused task region once we find it, and add it back at the end. 465 */ 466 467 task.getDimBounds(mTmpRect); 468 469 if (task == focusedTask) { 470 addBackFocusedTask = true; 471 mTmpRect2.set(mTmpRect); 472 } 473 474 final boolean isFreeformed = task.inFreeformWorkspace(); 475 if (task != focusedTask || isFreeformed) { 476 if (isFreeformed) { 477 // If the task is freeformed, enlarge the area to account for outside 478 // touch area for resize. 479 mTmpRect.inset(-delta, -delta); 480 // Intersect with display content rect. If we have system decor (status bar/ 481 // navigation bar), we want to exclude that from the tap detection. 482 // Otherwise, if the app is partially placed under some system button (eg. 483 // Recents, Home), pressing that button would cause a full series of 484 // unwanted transfer focus/resume/pause, before we could go home. 485 mTmpRect.intersect(mContentRect); 486 } 487 mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE); 488 } 489 } 490 } 491 // If we removed the focused task above, add it back and only leave its 492 // outside touch area in the exclusion. TapDectector is not interested in 493 // any touch inside the focused task itself. 494 if (addBackFocusedTask) { 495 mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION); 496 } 497 final WindowState inputMethod = mService.mInputMethodWindow; 498 if (inputMethod != null && inputMethod.isVisibleLw()) { 499 // If the input method is visible and the user is typing, we don't want these touch 500 // events to be intercepted and used to change focus. This would likely cause a 501 // disappearance of the input method. 502 inputMethod.getTouchableRegion(mTmpRegion); 503 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION); 504 } 505 for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) { 506 WindowState win = mTapExcludedWindows.get(i); 507 win.getTouchableRegion(mTmpRegion); 508 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION); 509 } 510 if (getDockedStackVisibleForUserLocked() != null) { 511 mDividerControllerLocked.getTouchRegion(mTmpRect); 512 mTmpRegion.set(mTmpRect); 513 mTouchExcludeRegion.op(mTmpRegion, Op.UNION); 514 } 515 if (mTapDetector != null) { 516 mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion); 517 } 518 } 519 520 void switchUserStacks() { 521 final WindowList windows = getWindowList(); 522 for (int i = 0; i < windows.size(); i++) { 523 final WindowState win = windows.get(i); 524 if (win.isHiddenFromUserLocked()) { 525 if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + win 526 + ", attrs=" + win.mAttrs.type + ", belonging to " + win.mOwnerUid); 527 win.hideLw(false); 528 } 529 } 530 531 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 532 mStacks.get(stackNdx).switchUser(); 533 } 534 535 rebuildAppWindowList(); 536 } 537 538 void resetAnimationBackgroundAnimator() { 539 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 540 mStacks.get(stackNdx).resetAnimationBackgroundAnimator(); 541 } 542 } 543 544 boolean animateDimLayers() { 545 return mDimLayerController.animateDimLayers(); 546 } 547 548 void resetDimming() { 549 mDimLayerController.resetDimming(); 550 } 551 552 boolean isDimming() { 553 return mDimLayerController.isDimming(); 554 } 555 556 void stopDimmingIfNeeded() { 557 mDimLayerController.stopDimmingIfNeeded(); 558 } 559 560 void close() { 561 mDimLayerController.close(); 562 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 563 mStacks.get(stackNdx).close(); 564 } 565 } 566 567 boolean isAnimating() { 568 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 569 final TaskStack stack = mStacks.get(stackNdx); 570 if (stack.isAnimating()) { 571 return true; 572 } 573 } 574 return false; 575 } 576 577 void onCompleteDeferredRemoval() { 578 boolean animating = false; 579 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 580 final TaskStack stack = mStacks.get(stackNdx); 581 if (stack.isAnimating()) { 582 animating = true; 583 } else { 584 if (stack.mDeferDetach) { 585 mService.detachStackLocked(this, stack); 586 } 587 final ArrayList<Task> tasks = stack.getTasks(); 588 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 589 final Task task = tasks.get(taskNdx); 590 AppTokenList tokens = task.mAppTokens; 591 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 592 AppWindowToken wtoken = tokens.get(tokenNdx); 593 if (wtoken.mIsExiting) { 594 wtoken.removeIfPossible(); 595 } 596 } 597 } 598 } 599 } 600 if (!animating && mDeferredRemoval) { 601 mService.onDisplayRemoved(mDisplayId); 602 } 603 } 604 605 void rotateBounds(int oldRotation, int newRotation, Rect bounds) { 606 final int rotationDelta = DisplayContent.deltaRotation(oldRotation, newRotation); 607 getLogicalDisplayRect(mTmpRect); 608 switch (rotationDelta) { 609 case Surface.ROTATION_0: 610 mTmpRect2.set(bounds); 611 break; 612 case Surface.ROTATION_90: 613 mTmpRect2.top = mTmpRect.bottom - bounds.right; 614 mTmpRect2.left = bounds.top; 615 mTmpRect2.right = mTmpRect2.left + bounds.height(); 616 mTmpRect2.bottom = mTmpRect2.top + bounds.width(); 617 break; 618 case Surface.ROTATION_180: 619 mTmpRect2.top = mTmpRect.bottom - bounds.bottom; 620 mTmpRect2.left = mTmpRect.right - bounds.right; 621 mTmpRect2.right = mTmpRect2.left + bounds.width(); 622 mTmpRect2.bottom = mTmpRect2.top + bounds.height(); 623 break; 624 case Surface.ROTATION_270: 625 mTmpRect2.top = bounds.left; 626 mTmpRect2.left = mTmpRect.right - bounds.bottom; 627 mTmpRect2.right = mTmpRect2.left + bounds.height(); 628 mTmpRect2.bottom = mTmpRect2.top + bounds.width(); 629 break; 630 } 631 bounds.set(mTmpRect2); 632 } 633 634 static int deltaRotation(int oldRotation, int newRotation) { 635 int delta = newRotation - oldRotation; 636 if (delta < 0) delta += 4; 637 return delta; 638 } 639 640 public void dump(String prefix, PrintWriter pw) { 641 pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId); 642 final String subPrefix = " " + prefix; 643 pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x"); 644 pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity); 645 pw.print("dpi"); 646 if (mInitialDisplayWidth != mBaseDisplayWidth 647 || mInitialDisplayHeight != mBaseDisplayHeight 648 || mInitialDisplayDensity != mBaseDisplayDensity) { 649 pw.print(" base="); 650 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); 651 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi"); 652 } 653 if (mDisplayScalingDisabled) { 654 pw.println(" noscale"); 655 } 656 pw.print(" cur="); 657 pw.print(mDisplayInfo.logicalWidth); 658 pw.print("x"); pw.print(mDisplayInfo.logicalHeight); 659 pw.print(" app="); 660 pw.print(mDisplayInfo.appWidth); 661 pw.print("x"); pw.print(mDisplayInfo.appHeight); 662 pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth); 663 pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight); 664 pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth); 665 pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight); 666 pw.print(subPrefix); pw.print("deferred="); pw.print(mDeferredRemoval); 667 pw.print(" layoutNeeded="); pw.println(layoutNeeded); 668 669 pw.println(); 670 pw.println(" Application tokens in top down Z order:"); 671 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 672 final TaskStack stack = mStacks.get(stackNdx); 673 stack.dump(prefix + " ", pw); 674 } 675 676 pw.println(); 677 if (!mExitingTokens.isEmpty()) { 678 pw.println(); 679 pw.println(" Exiting tokens:"); 680 for (int i = mExitingTokens.size() - 1; i >= 0; i--) { 681 WindowToken token = mExitingTokens.get(i); 682 pw.print(" Exiting #"); pw.print(i); 683 pw.print(' '); pw.print(token); 684 pw.println(':'); 685 token.dump(pw, " "); 686 } 687 } 688 pw.println(); 689 mDimLayerController.dump(prefix + " ", pw); 690 pw.println(); 691 mDividerControllerLocked.dump(prefix + " ", pw); 692 } 693 694 @Override 695 public String toString() { 696 return getName() + " stacks=" + mStacks; 697 } 698 699 String getName() { 700 return "Display " + mDisplayId + " info=" + mDisplayInfo; 701 } 702 703 /** 704 * @return The docked stack, but only if it is visible, and {@code null} otherwise. 705 */ 706 TaskStack getDockedStackLocked() { 707 final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID); 708 return (stack != null && stack.isVisible()) ? stack : null; 709 } 710 711 /** 712 * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not 713 * visible, as long as it's not hidden because the current user doesn't have any tasks there. 714 */ 715 TaskStack getDockedStackVisibleForUserLocked() { 716 final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID); 717 return (stack != null && stack.isVisible(true /* ignoreKeyguard */)) ? stack : null; 718 } 719 720 /** Find the visible, touch-deliverable window under the given point */ 721 WindowState getTouchableWinAtPointLocked(float xf, float yf) { 722 WindowState touchedWin = null; 723 final int x = (int) xf; 724 final int y = (int) yf; 725 726 for (int i = mWindows.size() - 1; i >= 0; i--) { 727 WindowState window = mWindows.get(i); 728 final int flags = window.mAttrs.flags; 729 if (!window.isVisibleLw()) { 730 continue; 731 } 732 if ((flags & FLAG_NOT_TOUCHABLE) != 0) { 733 continue; 734 } 735 736 window.getVisibleBounds(mTmpRect); 737 if (!mTmpRect.contains(x, y)) { 738 continue; 739 } 740 741 window.getTouchableRegion(mTmpRegion); 742 743 final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL); 744 if (mTmpRegion.contains(x, y) || touchFlags == 0) { 745 touchedWin = window; 746 break; 747 } 748 } 749 750 return touchedWin; 751 } 752 753 /** 754 * See {@link WindowManagerService#overridePlayingAppAnimationsLw}. 755 */ 756 void overridePlayingAppAnimationsLw(Animation a) { 757 for (int i = mStacks.size() - 1; i >= 0; i--) { 758 mStacks.get(i).overridePlayingAppAnimations(a); 759 } 760 } 761 762 boolean canAddToastWindowForUid(int uid) { 763 // We allow one toast window per UID being shown at a time. 764 WindowList windows = getWindowList(); 765 final int windowCount = windows.size(); 766 for (int i = 0; i < windowCount; i++) { 767 WindowState window = windows.get(i); 768 if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == uid 769 && !window.mPermanentlyHidden && !window.mAnimatingExit) { 770 return false; 771 } 772 } 773 return true; 774 } 775 776 void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, 777 WindowState newFocus) { 778 if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) { 779 return; 780 } 781 final int lostFocusUid = oldFocus.mOwnerUid; 782 WindowList windows = getWindowList(); 783 final int windowCount = windows.size(); 784 for (int i = 0; i < windowCount; i++) { 785 WindowState window = windows.get(i); 786 if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == lostFocusUid) { 787 if (!mService.mH.hasMessages(WindowManagerService.H.WINDOW_HIDE_TIMEOUT, window)) { 788 mService.mH.sendMessageDelayed( 789 mService.mH.obtainMessage( 790 WindowManagerService.H.WINDOW_HIDE_TIMEOUT, window), 791 window.mAttrs.hideTimeoutMilliseconds); 792 } 793 } 794 } 795 } 796 797 WindowState findFocusedWindow() { 798 final AppWindowToken focusedApp = mService.mFocusedApp; 799 800 for (int i = mWindows.size() - 1; i >= 0; i--) { 801 final WindowState win = mWindows.get(i); 802 803 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + i + " = " + win 804 + ", flags=" + win.mAttrs.flags + ", canReceive=" + win.canReceiveKeys()); 805 806 if (!win.canReceiveKeys()) { 807 continue; 808 } 809 810 final AppWindowToken wtoken = win.mAppToken; 811 812 // If this window's application has been removed, just skip it. 813 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 814 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because " 815 + (wtoken.removed ? "removed" : "sendingToBottom")); 816 continue; 817 } 818 819 if (focusedApp == null) { 820 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null" 821 + " using new focus @ " + i + " = " + win); 822 return win; 823 } 824 825 if (!focusedApp.windowsAreFocusable()) { 826 // Current focused app windows aren't focusable... 827 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not" 828 + " focusable using new focus @ " + i + " = " + win); 829 return win; 830 } 831 832 // Descend through all of the app tokens and find the first that either matches 833 // win.mAppToken (return win) or mFocusedApp (return null). 834 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING) { 835 final TaskStack focusedAppStack = focusedApp.mTask.mStack; 836 final TaskStack appStack = wtoken.mTask.mStack; 837 838 // TODO: Use WindowContainer.compareTo() once everything is using WindowContainer 839 if ((focusedAppStack == appStack 840 && appStack.isFirstGreaterThanSecond(focusedApp, wtoken)) 841 || mStacks.indexOf(focusedAppStack) > mStacks.indexOf(appStack)) { 842 // App stack below focused app stack. No focus for you!!! 843 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, 844 "findFocusedWindow: Reached focused app=" + focusedApp); 845 return null; 846 } 847 } 848 849 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " 850 + i + " = " + win); 851 return win; 852 } 853 854 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows."); 855 return null; 856 } 857 858 int addAppWindowToWindowList(final WindowState win) { 859 final IWindow client = win.mClient; 860 861 WindowList tokenWindowList = getTokenWindowsOnDisplay(win.mToken); 862 if (!tokenWindowList.isEmpty()) { 863 return addAppWindowExisting(win, tokenWindowList); 864 } 865 866 // No windows from this token on this display 867 if (mService.localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window " 868 + client.asBinder() + " (token=" + this + ")"); 869 870 final WindowToken wToken = win.mToken; 871 872 // Figure out where the window should go, based on the order of applications. 873 final GetWindowOnDisplaySearchResults result = new GetWindowOnDisplaySearchResults(); 874 for (int i = mStacks.size() - 1; i >= 0; --i) { 875 final TaskStack stack = mStacks.get(i); 876 stack.getWindowOnDisplayBeforeToken(this, wToken, result); 877 if (result.reachedToken) { 878 // We have reach the token we are interested in. End search. 879 break; 880 } 881 } 882 883 WindowState pos = result.foundWindow; 884 885 // We now know the index into the apps. If we found an app window above, that gives us the 886 // position; else we need to look some more. 887 if (pos != null) { 888 // Move behind any windows attached to this one. 889 final WindowToken atoken = mService.mTokenMap.get(pos.mClient.asBinder()); 890 if (atoken != null) { 891 tokenWindowList = getTokenWindowsOnDisplay(atoken); 892 final int NC = tokenWindowList.size(); 893 if (NC > 0) { 894 WindowState bottom = tokenWindowList.get(0); 895 if (bottom.mSubLayer < 0) { 896 pos = bottom; 897 } 898 } 899 } 900 addWindowToListBefore(win, pos); 901 return 0; 902 } 903 904 // Continue looking down until we find the first token that has windows on this display. 905 result.reset(); 906 for (int i = mStacks.size() - 1; i >= 0; --i) { 907 final TaskStack stack = mStacks.get(i); 908 stack.getWindowOnDisplayAfterToken(this, wToken, result); 909 if (result.foundWindow != null) { 910 // We have found a window after the token. End search. 911 break; 912 } 913 } 914 915 pos = result.foundWindow; 916 917 if (pos != null) { 918 // Move in front of any windows attached to this one. 919 final WindowToken atoken = mService.mTokenMap.get(pos.mClient.asBinder()); 920 if (atoken != null) { 921 final WindowState top = atoken.getTopWindow(); 922 if (top != null && top.mSubLayer >= 0) { 923 pos = top; 924 } 925 } 926 addWindowToListAfter(win, pos); 927 return 0; 928 } 929 930 // Just search for the start of this layer. 931 final int myLayer = win.mBaseLayer; 932 int i; 933 for (i = mWindows.size() - 1; i >= 0; --i) { 934 final WindowState w = mWindows.get(i); 935 // Dock divider shares the base layer with application windows, but we want to always 936 // keep it above the application windows. The sharing of the base layer is intended 937 // for window animations, which need to be above the dock divider for the duration 938 // of the animation. 939 if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) { 940 break; 941 } 942 } 943 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 944 "Based on layer: Adding window " + win + " at " + (i + 1) + " of " 945 + mWindows.size()); 946 mWindows.add(i + 1, win); 947 mService.mWindowsChanged = true; 948 return 0; 949 } 950 951 /** Adds this non-app window to the window list. */ 952 void addNonAppWindowToWindowList(WindowState win) { 953 // Figure out where window should go, based on layer. 954 int i; 955 for (i = mWindows.size() - 1; i >= 0; i--) { 956 final WindowState otherWin = mWindows.get(i); 957 if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= win.mBaseLayer) { 958 // Wallpaper wanders through the window list, for example to position itself 959 // directly behind keyguard. Because of this it will break the ordering based on 960 // WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and 961 // we don't want the new window to appear above them. An example of this is adding 962 // of the docked stack divider. Consider a scenario with the following ordering (top 963 // to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider 964 // to land below the assist preview, so the dock divider must ignore the wallpaper, 965 // with which it shares the base layer. 966 break; 967 } 968 } 969 970 i++; 971 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 972 "Free window: Adding window " + this + " at " + i + " of " + mWindows.size()); 973 mWindows.add(i, win); 974 mService.mWindowsChanged = true; 975 } 976 977 void addChildWindowToWindowList(WindowState win) { 978 final WindowState parentWindow = win.getParentWindow(); 979 980 WindowList windowsOnSameDisplay = getTokenWindowsOnDisplay(win.mToken); 981 982 // Figure out this window's ordering relative to the parent window. 983 final int wCount = windowsOnSameDisplay.size(); 984 final int sublayer = win.mSubLayer; 985 int largestSublayer = Integer.MIN_VALUE; 986 WindowState windowWithLargestSublayer = null; 987 int i; 988 for (i = 0; i < wCount; i++) { 989 WindowState w = windowsOnSameDisplay.get(i); 990 final int wSublayer = w.mSubLayer; 991 if (wSublayer >= largestSublayer) { 992 largestSublayer = wSublayer; 993 windowWithLargestSublayer = w; 994 } 995 if (sublayer < 0) { 996 // For negative sublayers, we go below all windows in the same sublayer. 997 if (wSublayer >= sublayer) { 998 addWindowToListBefore(win, wSublayer >= 0 ? parentWindow : w); 999 break; 1000 } 1001 } else { 1002 // For positive sublayers, we go above all windows in the same sublayer. 1003 if (wSublayer > sublayer) { 1004 addWindowToListBefore(win, w); 1005 break; 1006 } 1007 } 1008 } 1009 if (i >= wCount) { 1010 if (sublayer < 0) { 1011 addWindowToListBefore(win, parentWindow); 1012 } else { 1013 addWindowToListAfter(win, 1014 largestSublayer >= 0 ? windowWithLargestSublayer : parentWindow); 1015 } 1016 } 1017 } 1018 1019 /** 1020 * Z-orders the display window list so that: 1021 * <ul> 1022 * <li>Any windows that are currently below the wallpaper window stay below the wallpaper 1023 * window. 1024 * <li>Exiting application windows are at the bottom, but above the wallpaper window. 1025 * <li>All other application windows are above the exiting application windows and ordered based 1026 * on the ordering of their stacks and tasks on the display. 1027 * <li>Non-application windows are at the very top. 1028 * </ul> 1029 * <p> 1030 * NOTE: This isn't a complete picture of what the user see. Further manipulation of the window 1031 * surface layering is done in {@link WindowLayersController}. 1032 */ 1033 void rebuildAppWindowList() { 1034 int count = mWindows.size(); 1035 int i; 1036 int lastBelow = -1; 1037 int numRemoved = 0; 1038 1039 if (mRebuildTmp.length < count) { 1040 mRebuildTmp = new WindowState[count + 10]; 1041 } 1042 1043 // First remove all existing app windows. 1044 i = 0; 1045 while (i < count) { 1046 final WindowState w = mWindows.get(i); 1047 if (w.mAppToken != null) { 1048 final WindowState win = mWindows.remove(i); 1049 win.mRebuilding = true; 1050 mRebuildTmp[numRemoved] = win; 1051 mService.mWindowsChanged = true; 1052 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win); 1053 count--; 1054 numRemoved++; 1055 continue; 1056 } else if (lastBelow == i-1) { 1057 if (w.mAttrs.type == TYPE_WALLPAPER) { 1058 lastBelow = i; 1059 } 1060 } 1061 i++; 1062 } 1063 1064 // Keep whatever windows were below the app windows still below, by skipping them. 1065 lastBelow++; 1066 i = lastBelow; 1067 1068 // First add all of the exiting app tokens... these are no longer in the main app list, 1069 // but still have windows shown. We put them in the back because now that the animation is 1070 // over we no longer will care about them. 1071 final int numStacks = mStacks.size(); 1072 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 1073 AppTokenList exitingAppTokens = mStacks.get(stackNdx).mExitingAppTokens; 1074 int NT = exitingAppTokens.size(); 1075 for (int j = 0; j < NT; j++) { 1076 i = exitingAppTokens.get(j).rebuildWindowList(this, i); 1077 } 1078 } 1079 1080 // And add in the still active app tokens in Z order. 1081 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 1082 i = mStacks.get(stackNdx).rebuildWindowList(this, i); 1083 } 1084 1085 i -= lastBelow; 1086 if (i != numRemoved) { 1087 layoutNeeded = true; 1088 Slog.w(TAG_WM, "On display=" + mDisplayId + " Rebuild removed " + numRemoved 1089 + " windows but added " + i + " rebuildAppWindowListLocked() " 1090 + " callers=" + Debug.getCallers(10)); 1091 for (i = 0; i < numRemoved; i++) { 1092 WindowState ws = mRebuildTmp[i]; 1093 if (ws.mRebuilding) { 1094 StringWriter sw = new StringWriter(); 1095 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 1096 ws.dump(pw, "", true); 1097 pw.flush(); 1098 Slog.w(TAG_WM, "This window was lost: " + ws); 1099 Slog.w(TAG_WM, sw.toString()); 1100 ws.mWinAnimator.destroySurfaceLocked(); 1101 } 1102 } 1103 Slog.w(TAG_WM, "Current app token list:"); 1104 dumpChildrenNames(); 1105 Slog.w(TAG_WM, "Final window list:"); 1106 dumpWindows(); 1107 } 1108 Arrays.fill(mRebuildTmp, null); 1109 } 1110 1111 /** Return the list of Windows on this display associated with the input token. */ 1112 WindowList getTokenWindowsOnDisplay(WindowToken token) { 1113 final WindowList windowList = new WindowList(); 1114 final int count = mWindows.size(); 1115 for (int i = 0; i < count; i++) { 1116 final WindowState win = mWindows.get(i); 1117 if (win.mToken == token) { 1118 windowList.add(win); 1119 } 1120 } 1121 return windowList; 1122 } 1123 1124 private int addAppWindowExisting(WindowState win, WindowList tokenWindowList) { 1125 1126 int tokenWindowsPos; 1127 // If this application has existing windows, we simply place the new window on top of 1128 // them... but keep the starting window on top. 1129 if (win.mAttrs.type == TYPE_BASE_APPLICATION) { 1130 // Base windows go behind everything else. 1131 final WindowState lowestWindow = tokenWindowList.get(0); 1132 addWindowToListBefore(win, lowestWindow); 1133 tokenWindowsPos = win.mToken.getWindowIndex(lowestWindow); 1134 } else { 1135 final AppWindowToken atoken = win.mAppToken; 1136 final int windowListPos = tokenWindowList.size(); 1137 final WindowState lastWindow = tokenWindowList.get(windowListPos - 1); 1138 if (atoken != null && lastWindow == atoken.startingWindow) { 1139 addWindowToListBefore(win, lastWindow); 1140 tokenWindowsPos = win.mToken.getWindowIndex(lastWindow); 1141 } else { 1142 int newIdx = findIdxBasedOnAppTokens(win); 1143 // There is a window above this one associated with the same apptoken note that the 1144 // window could be a floating window that was created later or a window at the top 1145 // of the list of windows associated with this token. 1146 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1147 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " 1148 + mWindows.size()); 1149 mWindows.add(newIdx + 1, win); 1150 if (newIdx < 0) { 1151 // No window from token found on win's display. 1152 tokenWindowsPos = 0; 1153 } else { 1154 tokenWindowsPos = win.mToken.getWindowIndex(mWindows.get(newIdx)) + 1; 1155 } 1156 mService.mWindowsChanged = true; 1157 } 1158 } 1159 return tokenWindowsPos; 1160 } 1161 1162 /** Places the first input window after the second input window in the window list. */ 1163 private void addWindowToListAfter(WindowState first, WindowState second) { 1164 final int i = mWindows.indexOf(second); 1165 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1166 "Adding window " + this + " at " + (i + 1) + " of " + mWindows.size() 1167 + " (after " + second + ")"); 1168 mWindows.add(i + 1, first); 1169 mService.mWindowsChanged = true; 1170 } 1171 1172 /** Places the first input window before the second input window in the window list. */ 1173 private void addWindowToListBefore(WindowState first, WindowState second) { 1174 int i = mWindows.indexOf(second); 1175 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1176 "Adding window " + this + " at " + i + " of " + mWindows.size() 1177 + " (before " + second + ")"); 1178 if (i < 0) { 1179 Slog.w(TAG_WM, "addWindowToListBefore: Unable to find " + second + " in " + mWindows); 1180 i = 0; 1181 } 1182 mWindows.add(i, first); 1183 mService.mWindowsChanged = true; 1184 } 1185 1186 /** 1187 * This method finds out the index of a window that has the same app token as win. used for z 1188 * ordering the windows in mWindows 1189 */ 1190 private int findIdxBasedOnAppTokens(WindowState win) { 1191 for(int j = mWindows.size() - 1; j >= 0; j--) { 1192 final WindowState wentry = mWindows.get(j); 1193 if(wentry.mAppToken == win.mAppToken) { 1194 return j; 1195 } 1196 } 1197 return -1; 1198 } 1199 1200 private void dumpChildrenNames() { 1201 StringWriter sw = new StringWriter(); 1202 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 1203 dumpChildrenNames(pw, " "); 1204 } 1205 1206 private void dumpChildrenNames(PrintWriter pw, String prefix) { 1207 final String childPrefix = prefix + prefix; 1208 for (int j = mStacks.size() - 1; j >= 0; j--) { 1209 final TaskStack stack = mStacks.get(j); 1210 pw.println("#" + j + " " + getName()); 1211 stack.dumpChildrenNames(pw, childPrefix); 1212 } 1213 } 1214 1215 private void dumpWindows() { 1216 final int numDisplays = mService.mDisplayContents.size(); 1217 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 1218 final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx); 1219 Slog.v(TAG_WM, " Display #" + displayContent.getDisplayId()); 1220 final WindowList windows = displayContent.getWindowList(); 1221 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 1222 Slog.v(TAG_WM, " #" + winNdx + ": " + windows.get(winNdx)); 1223 } 1224 } 1225 } 1226 1227 static final class GetWindowOnDisplaySearchResults { 1228 boolean reachedToken; 1229 WindowState foundWindow; 1230 1231 void reset() { 1232 reachedToken = false; 1233 foundWindow = null; 1234 } 1235 } 1236} 1237