DisplayContent.java revision 62a40f87b3f45cbd20fea101d977153e9a933891
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.HOME_STACK_ID; 21import static android.app.ActivityManager.StackId.PINNED_STACK_ID; 22import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 23import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 24import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 25import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 26import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 27import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 28import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; 29 30import android.app.ActivityManager.StackId; 31import android.content.pm.ApplicationInfo; 32import android.content.pm.PackageManager; 33import android.graphics.Rect; 34import android.graphics.Region; 35import android.graphics.Region.Op; 36import android.os.Build; 37import android.os.UserHandle; 38import android.util.DisplayMetrics; 39import android.util.Slog; 40import android.view.Display; 41import android.view.DisplayInfo; 42import android.view.Surface; 43import android.view.animation.Animation; 44 45import java.io.PrintWriter; 46import java.util.ArrayList; 47 48class DisplayContentList extends ArrayList<DisplayContent> { 49} 50 51/** 52 * Utility class for keeping track of the WindowStates and other pertinent contents of a 53 * particular Display. 54 * 55 * IMPORTANT: No method from this class should ever be used without holding 56 * WindowManagerService.mWindowMap. 57 */ 58class DisplayContent { 59 60 /** Unique identifier of this stack. */ 61 private final int mDisplayId; 62 63 /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element 64 * from mDisplayWindows; */ 65 private final WindowList mWindows = new WindowList(); 66 67 int mInitialDisplayWidth = 0; 68 int mInitialDisplayHeight = 0; 69 int mInitialDisplayDensity = 0; 70 int mBaseDisplayWidth = 0; 71 int mBaseDisplayHeight = 0; 72 int mBaseDisplayDensity = 0; 73 boolean mDisplayScalingDisabled; 74 private final DisplayInfo mDisplayInfo = new DisplayInfo(); 75 private final Display mDisplay; 76 private final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 77 78 Rect mBaseDisplayRect = new Rect(); 79 Rect mContentRect = new Rect(); 80 81 // Accessed directly by all users. 82 boolean layoutNeeded; 83 int pendingLayoutChanges; 84 final boolean isDefaultDisplay; 85 86 /** Window tokens that are in the process of exiting, but still on screen for animations. */ 87 final ArrayList<WindowToken> mExitingTokens = new ArrayList<>(); 88 89 /** Array containing all TaskStacks on this display. Array 90 * is stored in display order with the current bottom stack at 0. */ 91 private final ArrayList<TaskStack> mStacks = new ArrayList<>(); 92 93 /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack 94 * (except a future lockscreen TaskStack) moves to the top. */ 95 private TaskStack mHomeStack = null; 96 97 /** Detect user tapping outside of current focused task bounds .*/ 98 TaskTapPointerEventListener mTapDetector; 99 100 /** Detect user tapping outside of current focused stack bounds .*/ 101 Region mTouchExcludeRegion = new Region(); 102 103 /** Detect user tapping in a non-resizeable task in docked or fullscreen stack .*/ 104 Region mNonResizeableRegion = new Region(); 105 106 /** Save allocating when calculating rects */ 107 private final Rect mTmpRect = new Rect(); 108 private final Rect mTmpRect2 = new Rect(); 109 private final Region mTmpRegion = new Region(); 110 111 /** For gathering Task objects in order. */ 112 final ArrayList<Task> mTmpTaskHistory = new ArrayList<Task>(); 113 114 final WindowManagerService mService; 115 116 /** Remove this display when animation on it has completed. */ 117 boolean mDeferredRemoval; 118 119 final DockedStackDividerController mDividerControllerLocked; 120 121 final DimLayerController mDimLayerController; 122 123 final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>(); 124 125 /** 126 * @param display May not be null. 127 * @param service You know. 128 */ 129 DisplayContent(Display display, WindowManagerService service) { 130 mDisplay = display; 131 mDisplayId = display.getDisplayId(); 132 display.getDisplayInfo(mDisplayInfo); 133 display.getMetrics(mDisplayMetrics); 134 isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY; 135 mService = service; 136 initializeDisplayBaseInfo(); 137 mDividerControllerLocked = new DockedStackDividerController(service, this); 138 mDimLayerController = new DimLayerController(this); 139 } 140 141 int getDisplayId() { 142 return mDisplayId; 143 } 144 145 WindowList getWindowList() { 146 return mWindows; 147 } 148 149 Display getDisplay() { 150 return mDisplay; 151 } 152 153 DisplayInfo getDisplayInfo() { 154 return mDisplayInfo; 155 } 156 157 DisplayMetrics getDisplayMetrics() { 158 return mDisplayMetrics; 159 } 160 161 DockedStackDividerController getDockedDividerController() { 162 return mDividerControllerLocked; 163 } 164 165 /** 166 * Returns true if the specified UID has access to this display. 167 */ 168 public boolean hasAccess(int uid) { 169 return mDisplay.hasAccess(uid); 170 } 171 172 public boolean isPrivate() { 173 return (mDisplay.getFlags() & Display.FLAG_PRIVATE) != 0; 174 } 175 176 ArrayList<TaskStack> getStacks() { 177 return mStacks; 178 } 179 180 /** 181 * Retrieve the tasks on this display in stack order from the bottommost TaskStack up. 182 * @return All the Tasks, in order, on this display. 183 */ 184 ArrayList<Task> getTasks() { 185 mTmpTaskHistory.clear(); 186 final int numStacks = mStacks.size(); 187 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 188 mTmpTaskHistory.addAll(mStacks.get(stackNdx).getTasks()); 189 } 190 return mTmpTaskHistory; 191 } 192 193 TaskStack getHomeStack() { 194 if (mHomeStack == null && mDisplayId == Display.DEFAULT_DISPLAY) { 195 Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this); 196 } 197 return mHomeStack; 198 } 199 200 TaskStack getStackById(int stackId) { 201 for (int i = mStacks.size() - 1; i >= 0; --i) { 202 final TaskStack stack = mStacks.get(i); 203 if (stack.mStackId == stackId) { 204 return stack; 205 } 206 } 207 return null; 208 } 209 210 void updateDisplayInfo() { 211 mDisplay.getDisplayInfo(mDisplayInfo); 212 mDisplay.getMetrics(mDisplayMetrics); 213 for (int i = mStacks.size() - 1; i >= 0; --i) { 214 mStacks.get(i).updateDisplayInfo(null); 215 } 216 } 217 218 void initializeDisplayBaseInfo() { 219 // Bootstrap the default logical display from the display manager. 220 final DisplayInfo newDisplayInfo = 221 mService.mDisplayManagerInternal.getDisplayInfo(mDisplayId); 222 if (newDisplayInfo != null) { 223 mDisplayInfo.copyFrom(newDisplayInfo); 224 } 225 mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth; 226 mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight; 227 mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi; 228 mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight); 229 } 230 231 void getLogicalDisplayRect(Rect out) { 232 // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked. 233 final int orientation = mDisplayInfo.rotation; 234 boolean rotated = (orientation == Surface.ROTATION_90 235 || orientation == Surface.ROTATION_270); 236 final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; 237 final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; 238 int width = mDisplayInfo.logicalWidth; 239 int left = (physWidth - width) / 2; 240 int height = mDisplayInfo.logicalHeight; 241 int top = (physHeight - height) / 2; 242 out.set(left, top, left + width, top + height); 243 } 244 245 void getContentRect(Rect out) { 246 out.set(mContentRect); 247 } 248 249 /** Refer to {@link WindowManagerService#attachStack(int, int, boolean)} */ 250 void attachStack(TaskStack stack, boolean onTop) { 251 if (stack.mStackId == HOME_STACK_ID) { 252 if (mHomeStack != null) { 253 throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first."); 254 } 255 mHomeStack = stack; 256 } 257 if (onTop) { 258 mStacks.add(stack); 259 } else { 260 mStacks.add(0, stack); 261 } 262 layoutNeeded = true; 263 } 264 265 void moveStack(TaskStack stack, boolean toTop) { 266 if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) { 267 // This stack is always-on-top silly... 268 Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + stack + " to bottom"); 269 return; 270 } 271 272 if (!mStacks.remove(stack)) { 273 Slog.wtf(TAG_WM, "moving stack that was not added: " + stack, new Throwable()); 274 } 275 276 int addIndex = toTop ? mStacks.size() : 0; 277 278 if (toTop 279 && mService.isStackVisibleLocked(PINNED_STACK_ID) 280 && stack.mStackId != PINNED_STACK_ID) { 281 // The pinned stack is always the top most stack (always-on-top) when it is visible. 282 // So, stack is moved just below the pinned stack. 283 addIndex--; 284 TaskStack topStack = mStacks.get(addIndex); 285 if (topStack.mStackId != PINNED_STACK_ID) { 286 throw new IllegalStateException("Pinned stack isn't top stack??? " + mStacks); 287 } 288 } 289 mStacks.add(addIndex, stack); 290 } 291 292 void detachStack(TaskStack stack) { 293 mDimLayerController.removeDimLayerUser(stack); 294 mStacks.remove(stack); 295 } 296 297 /** 298 * Propagate the new bounds to all child stacks. 299 * @param contentRect The bounds to apply at the top level. 300 */ 301 void resize(Rect contentRect) { 302 mContentRect.set(contentRect); 303 } 304 305 int taskIdFromPoint(int x, int y) { 306 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 307 TaskStack stack = mStacks.get(stackNdx); 308 stack.getBounds(mTmpRect); 309 if (!mTmpRect.contains(x, y) || stack.isAdjustedForMinimizedDockedStack()) { 310 continue; 311 } 312 final ArrayList<Task> tasks = stack.getTasks(); 313 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 314 final Task task = tasks.get(taskNdx); 315 final WindowState win = task.getTopVisibleAppMainWindow(); 316 if (win == null) { 317 continue; 318 } 319 // We need to use the task's dim bounds (which is derived from the visible 320 // bounds of its apps windows) for any touch-related tests. Can't use 321 // the task's original bounds because it might be adjusted to fit the 322 // content frame. For example, the presence of the IME adjusting the 323 // windows frames when the app window is the IME target. 324 task.getDimBounds(mTmpRect); 325 if (mTmpRect.contains(x, y)) { 326 return task.mTaskId; 327 } 328 } 329 } 330 return -1; 331 } 332 333 /** 334 * Find the task whose outside touch area (for resizing) (x, y) falls within. 335 * Returns null if the touch doesn't fall into a resizing area. 336 */ 337 Task findTaskForControlPoint(int x, int y) { 338 final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics); 339 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 340 TaskStack stack = mStacks.get(stackNdx); 341 if (!StackId.isTaskResizeAllowed(stack.mStackId)) { 342 break; 343 } 344 final ArrayList<Task> tasks = stack.getTasks(); 345 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 346 final Task task = tasks.get(taskNdx); 347 if (task.isFullscreen()) { 348 return null; 349 } 350 351 // We need to use the task's dim bounds (which is derived from the visible 352 // bounds of its apps windows) for any touch-related tests. Can't use 353 // the task's original bounds because it might be adjusted to fit the 354 // content frame. One example is when the task is put to top-left quadrant, 355 // the actual visible area would not start at (0,0) after it's adjusted 356 // for the status bar. 357 task.getDimBounds(mTmpRect); 358 mTmpRect.inset(-delta, -delta); 359 if (mTmpRect.contains(x, y)) { 360 mTmpRect.inset(delta, delta); 361 if (!mTmpRect.contains(x, y)) { 362 return task; 363 } 364 // User touched inside the task. No need to look further, 365 // focus transfer will be handled in ACTION_UP. 366 return null; 367 } 368 } 369 } 370 return null; 371 } 372 373 void setTouchExcludeRegion(Task focusedTask) { 374 mTouchExcludeRegion.set(mBaseDisplayRect); 375 final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics); 376 boolean addBackFocusedTask = false; 377 mNonResizeableRegion.setEmpty(); 378 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 379 TaskStack stack = mStacks.get(stackNdx); 380 final ArrayList<Task> tasks = stack.getTasks(); 381 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 382 final Task task = tasks.get(taskNdx); 383 AppWindowToken token = task.getTopVisibleAppToken(); 384 if (token == null || !token.isVisible()) { 385 continue; 386 } 387 388 /** 389 * Exclusion region is the region that TapDetector doesn't care about. 390 * Here we want to remove all non-focused tasks from the exclusion region. 391 * We also remove the outside touch area for resizing for all freeform 392 * tasks (including the focused). 393 * 394 * We save the focused task region once we find it, and add it back at the end. 395 */ 396 397 task.getDimBounds(mTmpRect); 398 399 if (task == focusedTask) { 400 addBackFocusedTask = true; 401 mTmpRect2.set(mTmpRect); 402 } 403 404 final boolean isFreeformed = task.inFreeformWorkspace(); 405 if (task != focusedTask || isFreeformed) { 406 if (isFreeformed) { 407 // If the task is freeformed, enlarge the area to account for outside 408 // touch area for resize. 409 mTmpRect.inset(-delta, -delta); 410 // Intersect with display content rect. If we have system decor (status bar/ 411 // navigation bar), we want to exclude that from the tap detection. 412 // Otherwise, if the app is partially placed under some system button (eg. 413 // Recents, Home), pressing that button would cause a full series of 414 // unwanted transfer focus/resume/pause, before we could go home. 415 mTmpRect.intersect(mContentRect); 416 } 417 mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE); 418 } 419 if (task.isTwoFingerScrollMode()) { 420 stack.getBounds(mTmpRect); 421 mNonResizeableRegion.op(mTmpRect, Region.Op.UNION); 422 break; 423 } 424 } 425 } 426 // If we removed the focused task above, add it back and only leave its 427 // outside touch area in the exclusion. TapDectector is not interested in 428 // any touch inside the focused task itself. 429 if (addBackFocusedTask) { 430 mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION); 431 } 432 final WindowState inputMethod = mService.mInputMethodWindow; 433 if (inputMethod != null && inputMethod.isVisibleLw()) { 434 // If the input method is visible and the user is typing, we don't want these touch 435 // events to be intercepted and used to change focus. This would likely cause a 436 // disappearance of the input method. 437 inputMethod.getTouchableRegion(mTmpRegion); 438 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION); 439 } 440 for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) { 441 WindowState win = mTapExcludedWindows.get(i); 442 win.getTouchableRegion(mTmpRegion); 443 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION); 444 } 445 if (getDockedStackVisibleForUserLocked() != null) { 446 mDividerControllerLocked.getTouchRegion(mTmpRect); 447 mTmpRegion.set(mTmpRect); 448 mTouchExcludeRegion.op(mTmpRegion, Op.UNION); 449 } 450 if (mTapDetector != null) { 451 mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion, mNonResizeableRegion); 452 } 453 } 454 455 void switchUserStacks() { 456 final WindowList windows = getWindowList(); 457 for (int i = 0; i < windows.size(); i++) { 458 final WindowState win = windows.get(i); 459 if (win.isHiddenFromUserLocked()) { 460 if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + win 461 + ", attrs=" + win.mAttrs.type + ", belonging to " + win.mOwnerUid); 462 win.hideLw(false); 463 } 464 } 465 466 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 467 mStacks.get(stackNdx).switchUser(); 468 } 469 } 470 471 void resetAnimationBackgroundAnimator() { 472 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 473 mStacks.get(stackNdx).resetAnimationBackgroundAnimator(); 474 } 475 } 476 477 boolean animateDimLayers() { 478 return mDimLayerController.animateDimLayers(); 479 } 480 481 void resetDimming() { 482 mDimLayerController.resetDimming(); 483 } 484 485 boolean isDimming() { 486 return mDimLayerController.isDimming(); 487 } 488 489 void stopDimmingIfNeeded() { 490 mDimLayerController.stopDimmingIfNeeded(); 491 } 492 493 void close() { 494 mDimLayerController.close(); 495 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 496 mStacks.get(stackNdx).close(); 497 } 498 } 499 500 boolean isAnimating() { 501 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 502 final TaskStack stack = mStacks.get(stackNdx); 503 if (stack.isAnimating()) { 504 return true; 505 } 506 } 507 return false; 508 } 509 510 void checkForDeferredActions() { 511 boolean animating = false; 512 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 513 final TaskStack stack = mStacks.get(stackNdx); 514 if (stack.isAnimating()) { 515 animating = true; 516 } else { 517 if (stack.mDeferDetach) { 518 mService.detachStackLocked(this, stack); 519 } 520 final ArrayList<Task> tasks = stack.getTasks(); 521 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 522 final Task task = tasks.get(taskNdx); 523 AppTokenList tokens = task.mAppTokens; 524 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 525 AppWindowToken wtoken = tokens.get(tokenNdx); 526 if (wtoken.mIsExiting) { 527 wtoken.removeAppFromTaskLocked(); 528 } 529 } 530 } 531 } 532 } 533 if (!animating && mDeferredRemoval) { 534 mService.onDisplayRemoved(mDisplayId); 535 } 536 } 537 538 void rotateBounds(int oldRotation, int newRotation, Rect bounds) { 539 final int rotationDelta = DisplayContent.deltaRotation(oldRotation, newRotation); 540 getLogicalDisplayRect(mTmpRect); 541 switch (rotationDelta) { 542 case Surface.ROTATION_0: 543 mTmpRect2.set(bounds); 544 break; 545 case Surface.ROTATION_90: 546 mTmpRect2.top = mTmpRect.bottom - bounds.right; 547 mTmpRect2.left = bounds.top; 548 mTmpRect2.right = mTmpRect2.left + bounds.height(); 549 mTmpRect2.bottom = mTmpRect2.top + bounds.width(); 550 break; 551 case Surface.ROTATION_180: 552 mTmpRect2.top = mTmpRect.bottom - bounds.bottom; 553 mTmpRect2.left = mTmpRect.right - bounds.right; 554 mTmpRect2.right = mTmpRect2.left + bounds.width(); 555 mTmpRect2.bottom = mTmpRect2.top + bounds.height(); 556 break; 557 case Surface.ROTATION_270: 558 mTmpRect2.top = bounds.left; 559 mTmpRect2.left = mTmpRect.right - bounds.bottom; 560 mTmpRect2.right = mTmpRect2.left + bounds.height(); 561 mTmpRect2.bottom = mTmpRect2.top + bounds.width(); 562 break; 563 } 564 bounds.set(mTmpRect2); 565 } 566 567 static int deltaRotation(int oldRotation, int newRotation) { 568 int delta = newRotation - oldRotation; 569 if (delta < 0) delta += 4; 570 return delta; 571 } 572 573 public void dump(String prefix, PrintWriter pw) { 574 pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId); 575 final String subPrefix = " " + prefix; 576 pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x"); 577 pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity); 578 pw.print("dpi"); 579 if (mInitialDisplayWidth != mBaseDisplayWidth 580 || mInitialDisplayHeight != mBaseDisplayHeight 581 || mInitialDisplayDensity != mBaseDisplayDensity) { 582 pw.print(" base="); 583 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); 584 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi"); 585 } 586 if (mDisplayScalingDisabled) { 587 pw.println(" noscale"); 588 } 589 pw.print(" cur="); 590 pw.print(mDisplayInfo.logicalWidth); 591 pw.print("x"); pw.print(mDisplayInfo.logicalHeight); 592 pw.print(" app="); 593 pw.print(mDisplayInfo.appWidth); 594 pw.print("x"); pw.print(mDisplayInfo.appHeight); 595 pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth); 596 pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight); 597 pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth); 598 pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight); 599 pw.print(subPrefix); pw.print("deferred="); pw.print(mDeferredRemoval); 600 pw.print(" layoutNeeded="); pw.println(layoutNeeded); 601 602 pw.println(); 603 pw.println(" Application tokens in top down Z order:"); 604 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 605 final TaskStack stack = mStacks.get(stackNdx); 606 stack.dump(prefix + " ", pw); 607 } 608 609 pw.println(); 610 if (!mExitingTokens.isEmpty()) { 611 pw.println(); 612 pw.println(" Exiting tokens:"); 613 for (int i = mExitingTokens.size() - 1; i >= 0; i--) { 614 WindowToken token = mExitingTokens.get(i); 615 pw.print(" Exiting #"); pw.print(i); 616 pw.print(' '); pw.print(token); 617 pw.println(':'); 618 token.dump(pw, " "); 619 } 620 } 621 pw.println(); 622 mDimLayerController.dump(prefix + " ", pw); 623 pw.println(); 624 mDividerControllerLocked.dump(prefix + " ", pw); 625 } 626 627 @Override 628 public String toString() { 629 return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mStacks; 630 } 631 632 /** 633 * @return The docked stack, but only if it is visible, and {@code null} otherwise. 634 */ 635 TaskStack getDockedStackLocked() { 636 final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID); 637 return (stack != null && stack.isVisibleLocked()) ? stack : null; 638 } 639 640 /** 641 * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not 642 * visible, as long as it's not hidden because the current user doesn't have any tasks there. 643 */ 644 TaskStack getDockedStackVisibleForUserLocked() { 645 final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID); 646 return (stack != null && stack.isVisibleLocked(true /* ignoreKeyguard */)) ? stack : null; 647 } 648 649 /** 650 * Find the visible, touch-deliverable window under the given point 651 */ 652 WindowState getTouchableWinAtPointLocked(float xf, float yf) { 653 WindowState touchedWin = null; 654 final int x = (int) xf; 655 final int y = (int) yf; 656 657 for (int i = mWindows.size() - 1; i >= 0; i--) { 658 WindowState window = mWindows.get(i); 659 final int flags = window.mAttrs.flags; 660 if (!window.isVisibleLw()) { 661 continue; 662 } 663 if ((flags & FLAG_NOT_TOUCHABLE) != 0) { 664 continue; 665 } 666 667 window.getVisibleBounds(mTmpRect); 668 if (!mTmpRect.contains(x, y)) { 669 continue; 670 } 671 672 window.getTouchableRegion(mTmpRegion); 673 674 final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL); 675 if (mTmpRegion.contains(x, y) || touchFlags == 0) { 676 touchedWin = window; 677 break; 678 } 679 } 680 681 return touchedWin; 682 } 683 684 /** 685 * See {@link WindowManagerService#overridePlayingAppAnimationsLw}. 686 */ 687 void overridePlayingAppAnimationsLw(Animation a) { 688 for (int i = mStacks.size() - 1; i >= 0; i--) { 689 mStacks.get(i).overridePlayingAppAnimations(a); 690 } 691 } 692 693 boolean canAddToastWindowForUid(int uid) { 694 // We allow one toast window per UID being shown at a time. 695 WindowList windows = getWindowList(); 696 final int windowCount = windows.size(); 697 for (int i = 0; i < windowCount; i++) { 698 WindowState window = windows.get(i); 699 if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == uid 700 && !window.mPermanentlyHidden && !window.mAnimatingExit 701 && !window.mRemoveOnExit) { 702 return false; 703 } 704 } 705 return true; 706 } 707 708 void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, 709 WindowState newFocus) { 710 if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) { 711 return; 712 } 713 final int lostFocusUid = oldFocus.mOwnerUid; 714 WindowList windows = getWindowList(); 715 final int windowCount = windows.size(); 716 for (int i = 0; i < windowCount; i++) { 717 WindowState window = windows.get(i); 718 if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == lostFocusUid) { 719 if (!mService.mH.hasMessages(WindowManagerService.H.WINDOW_HIDE_TIMEOUT, window)) { 720 mService.mH.sendMessageDelayed( 721 mService.mH.obtainMessage( 722 WindowManagerService.H.WINDOW_HIDE_TIMEOUT, window), 723 window.mAttrs.hideTimeoutMilliseconds); 724 } 725 } 726 } 727 } 728} 729