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