DisplayContent.java revision 7156b650f0d57522ebde67cebd201b339e08cf8e
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.Display.DEFAULT_DISPLAY; 27import static android.view.Display.FLAG_PRIVATE; 28import static android.view.Surface.ROTATION_0; 29import static android.view.Surface.ROTATION_180; 30import static android.view.Surface.ROTATION_270; 31import static android.view.Surface.ROTATION_90; 32import static android.view.WindowManager.DOCKED_BOTTOM; 33import static android.view.WindowManager.DOCKED_INVALID; 34import static android.view.WindowManager.DOCKED_TOP; 35import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 36import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 37import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 38import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 39import static android.view.WindowManager.LayoutParams.FLAG_SECURE; 40import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 41import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE; 42import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET; 43import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 44import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 45import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 46import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; 47import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; 48import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION; 49import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; 50import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 51import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 52import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 53import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 54import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS; 55import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE; 56import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER; 57import static com.android.server.wm.WindowAnimator.KEYGUARD_ANIMATING_OUT; 58import static com.android.server.wm.WindowAnimator.KEYGUARD_ANIM_TIMEOUT_MS; 59import static com.android.server.wm.WindowAnimator.KEYGUARD_NOT_SHOWN; 60import static com.android.server.wm.WindowAnimator.KEYGUARD_SHOWN; 61import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 62import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 63import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT; 64import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; 65import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS; 66import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; 67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; 68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD; 69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS; 70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; 71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; 72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON; 73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER; 74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT; 75import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 76import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; 77import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS; 78import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 79import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 80import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT; 81import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT; 82import static com.android.server.wm.WindowManagerService.dipToPixel; 83import static com.android.server.wm.WindowManagerService.localLOGV; 84import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; 85import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; 86import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW; 87import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM; 88import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED; 89import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE; 90 91import android.annotation.NonNull; 92import android.app.ActivityManager.StackId; 93import android.content.res.Configuration; 94import android.graphics.Matrix; 95import android.graphics.Rect; 96import android.graphics.RectF; 97import android.graphics.Region; 98import android.graphics.Region.Op; 99import android.hardware.display.DisplayManagerInternal; 100import android.os.Debug; 101import android.os.Handler; 102import android.os.IBinder; 103import android.os.RemoteException; 104import android.os.SystemClock; 105import android.util.DisplayMetrics; 106import android.util.Slog; 107import android.view.Display; 108import android.view.DisplayInfo; 109import android.view.IWindow; 110import android.view.WindowManager; 111import android.view.WindowManagerPolicy; 112import android.view.animation.AlphaAnimation; 113import android.view.animation.Animation; 114 115import com.android.internal.util.FastPrintWriter; 116import com.android.internal.view.IInputMethodClient; 117 118import java.io.FileDescriptor; 119import java.io.PrintWriter; 120import java.io.StringWriter; 121import java.util.ArrayList; 122import java.util.Arrays; 123import java.util.Comparator; 124import java.util.HashMap; 125import java.util.Iterator; 126import java.util.List; 127 128/** 129 * Utility class for keeping track of the WindowStates and other pertinent contents of a 130 * particular Display. 131 * 132 * IMPORTANT: No method from this class should ever be used without holding 133 * WindowManagerService.mWindowMap. 134 */ 135class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> { 136 private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM; 137 138 /** Unique identifier of this stack. */ 139 private final int mDisplayId; 140 141 // The display only has 2 child window containers. mTaskStackContainers which contains all 142 // window containers that are related to apps (Activities) and mNonAppWindowContainers which 143 // contains all window containers not related to apps (e.g. Status bar). 144 private final TaskStackContainers mTaskStackContainers = new TaskStackContainers(); 145 private final NonAppWindowContainers mNonAppWindowContainers = new NonAppWindowContainers(); 146 147 /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element 148 * from mDisplayWindows; */ 149 private final WindowList mWindows = new WindowList(); 150 151 // Mapping from a token IBinder to a WindowToken object on this display. 152 private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap(); 153 154 int mInitialDisplayWidth = 0; 155 int mInitialDisplayHeight = 0; 156 int mInitialDisplayDensity = 0; 157 int mBaseDisplayWidth = 0; 158 int mBaseDisplayHeight = 0; 159 int mBaseDisplayDensity = 0; 160 boolean mDisplayScalingDisabled; 161 private final DisplayInfo mDisplayInfo = new DisplayInfo(); 162 private final Display mDisplay; 163 private final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 164 165 Rect mBaseDisplayRect = new Rect(); 166 private Rect mContentRect = new Rect(); 167 168 // Accessed directly by all users. 169 private boolean mLayoutNeeded; 170 int pendingLayoutChanges; 171 final boolean isDefaultDisplay; 172 173 /** Window tokens that are in the process of exiting, but still on screen for animations. */ 174 final ArrayList<WindowToken> mExitingTokens = new ArrayList<>(); 175 176 /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack 177 * (except a future lockscreen TaskStack) moves to the top. */ 178 private TaskStack mHomeStack = null; 179 180 /** Detect user tapping outside of current focused task bounds .*/ 181 TaskTapPointerEventListener mTapDetector; 182 183 /** Detect user tapping outside of current focused stack bounds .*/ 184 private Region mTouchExcludeRegion = new Region(); 185 186 /** Save allocating when calculating rects */ 187 private final Rect mTmpRect = new Rect(); 188 private final Rect mTmpRect2 = new Rect(); 189 private final RectF mTmpRectF = new RectF(); 190 private final Matrix mTmpMatrix = new Matrix(); 191 private final Region mTmpRegion = new Region(); 192 193 final WindowManagerService mService; 194 195 /** Remove this display when animation on it has completed. */ 196 private boolean mDeferredRemoval; 197 198 final DockedStackDividerController mDividerControllerLocked; 199 200 final DimLayerController mDimLayerController; 201 202 final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>(); 203 204 /** Used when rebuilding window list to keep track of windows that have been removed. */ 205 private WindowState[] mRebuildTmp = new WindowState[20]; 206 207 private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult = 208 new TaskForResizePointSearchResult(); 209 private final GetWindowOnDisplaySearchResult mTmpGetWindowOnDisplaySearchResult = 210 new GetWindowOnDisplaySearchResult(); 211 212 // True if this display is in the process of being removed. Used to determine if the removal of 213 // the display's direct children should be allowed. 214 private boolean mRemovingDisplay = false; 215 216 private final WindowLayersController mLayersController; 217 final WallpaperController mWallpaperController; 218 int mInputMethodAnimLayerAdjustment; 219 220 /** 221 * @param display May not be null. 222 * @param service You know. 223 * @param layersController window layer controller used to assign layer to the windows on this 224 * display. 225 * @param wallpaperController wallpaper windows controller used to adjust the positioning of the 226 * wallpaper windows in the window list. 227 */ 228 DisplayContent(Display display, WindowManagerService service, 229 WindowLayersController layersController, WallpaperController wallpaperController) { 230 mDisplay = display; 231 mDisplayId = display.getDisplayId(); 232 mLayersController = layersController; 233 mWallpaperController = wallpaperController; 234 display.getDisplayInfo(mDisplayInfo); 235 display.getMetrics(mDisplayMetrics); 236 isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY; 237 mService = service; 238 initializeDisplayBaseInfo(); 239 mDividerControllerLocked = new DockedStackDividerController(service, this); 240 mDimLayerController = new DimLayerController(this); 241 242 // These are the only direct children we should ever have and they are permanent. 243 super.addChild(mTaskStackContainers, null); 244 super.addChild(mNonAppWindowContainers, null); 245 } 246 247 int getDisplayId() { 248 return mDisplayId; 249 } 250 251 WindowList getWindowList() { 252 return mWindows; 253 } 254 255 WindowToken getWindowToken(IBinder binder) { 256 return mTokenMap.get(binder); 257 } 258 259 AppWindowToken getAppWindowToken(IBinder binder) { 260 final WindowToken token = getWindowToken(binder); 261 if (token == null) { 262 return null; 263 } 264 return token.asAppWindowToken(); 265 } 266 267 void setWindowToken(IBinder binder, WindowToken token) { 268 final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token); 269 if (dc != null) { 270 // We currently don't support adding a window token to the display if the display 271 // already has the binder mapped to another token. If there is a use case for supporting 272 // this moving forward we will either need to merge the WindowTokens some how or have 273 // the binder map to a list of window tokens. 274 throw new IllegalArgumentException("Can't map token=" + token + " to display=" + this 275 + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap); 276 } 277 mTokenMap.put(binder, token); 278 279 if (token.asAppWindowToken() == null) { 280 // Add non-app token to container hierarchy on the display. App tokens are added through 281 // the parent container managing them (e.g. Tasks). 282 mNonAppWindowContainers.addChild(token, null); 283 } 284 } 285 286 WindowToken removeWindowToken(IBinder binder) { 287 final WindowToken token = mTokenMap.remove(binder); 288 if (token != null && token.asAppWindowToken() == null) { 289 mNonAppWindowContainers.removeChild(token); 290 } 291 return token; 292 } 293 294 Display getDisplay() { 295 return mDisplay; 296 } 297 298 DisplayInfo getDisplayInfo() { 299 return mDisplayInfo; 300 } 301 302 DisplayMetrics getDisplayMetrics() { 303 return mDisplayMetrics; 304 } 305 306 DockedStackDividerController getDockedDividerController() { 307 return mDividerControllerLocked; 308 } 309 310 /** 311 * Returns true if the specified UID has access to this display. 312 */ 313 boolean hasAccess(int uid) { 314 return mDisplay.hasAccess(uid); 315 } 316 317 boolean isPrivate() { 318 return (mDisplay.getFlags() & FLAG_PRIVATE) != 0; 319 } 320 321 TaskStack getHomeStack() { 322 if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) { 323 Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this); 324 } 325 return mHomeStack; 326 } 327 328 TaskStack getStackById(int stackId) { 329 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 330 final TaskStack stack = mTaskStackContainers.get(i); 331 if (stack.mStackId == stackId) { 332 return stack; 333 } 334 } 335 return null; 336 } 337 338 @Override 339 void onConfigurationChanged(Configuration newParentConfig) { 340 super.onConfigurationChanged(newParentConfig); 341 342 // The display size information is heavily dependent on the resources in the current 343 // configuration, so we need to reconfigure it every time the configuration changes. 344 // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh... 345 mService.reconfigureDisplayLocked(this); 346 347 getDockedDividerController().onConfigurationChanged(); 348 } 349 350 /** 351 * Callback used to trigger bounds update after configuration change and get ids of stacks whose 352 * bounds were updated. 353 */ 354 void updateStackBoundsAfterConfigChange(@NonNull List<Integer> changedStackList) { 355 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 356 final TaskStack stack = mTaskStackContainers.get(i); 357 if (stack.updateBoundsAfterConfigChange()) { 358 changedStackList.add(stack.mStackId); 359 } 360 } 361 } 362 363 @Override 364 boolean fillsParent() { 365 return true; 366 } 367 368 @Override 369 boolean isVisible() { 370 return true; 371 } 372 373 @Override 374 void onAppTransitionDone() { 375 super.onAppTransitionDone(); 376 rebuildAppWindowList(); 377 } 378 379 @Override 380 int getOrientation() { 381 final WindowManagerPolicy policy = mService.mPolicy; 382 383 // TODO: All the logic before the last return statement in this method should really go in 384 // #NonAppWindowContainer.getOrientation() since it is trying to decide orientation based 385 // on non-app windows. But, we can not do that until the window list is always correct in 386 // terms of z-ordering based on layers. 387 if (mService.mDisplayFrozen) { 388 if (mService.mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) { 389 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 390 "Display is frozen, return " + mService.mLastWindowForcedOrientation); 391 // If the display is frozen, some activities may be in the middle of restarting, and 392 // thus have removed their old window. If the window has the flag to hide the lock 393 // screen, then the lock screen can re-appear and inflict its own orientation on us. 394 // Keep the orientation stable until this all settles down. 395 return mService.mLastWindowForcedOrientation; 396 } else if (policy.isKeyguardLocked()) { 397 // Use the last orientation the while the display is frozen with the keyguard 398 // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED 399 // window. We don't want to check the show when locked window directly though as 400 // things aren't stable while the display is frozen, for example the window could be 401 // momentarily unavailable due to activity relaunch. 402 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, " 403 + "return " + mService.mLastOrientation); 404 return mService.mLastOrientation; 405 } 406 } else { 407 for (int pos = mWindows.size() - 1; pos >= 0; --pos) { 408 final WindowState win = mWindows.get(pos); 409 if (win.mAppToken != null) { 410 // We hit an application window. so the orientation will be determined by the 411 // app window. No point in continuing further. 412 break; 413 } 414 if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) { 415 continue; 416 } 417 int req = win.mAttrs.screenOrientation; 418 if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND) { 419 continue; 420 } 421 422 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req); 423 if (policy.isKeyguardHostWindow(win.mAttrs)) { 424 mService.mLastKeyguardForcedOrientation = req; 425 } 426 return (mService.mLastWindowForcedOrientation = req); 427 } 428 mService.mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 429 430 if (policy.isKeyguardLocked()) { 431 // The screen is locked and no top system window is requesting an orientation. 432 // Return either the orientation of the show-when-locked app (if there is any) or 433 // the orientation of the keyguard. No point in searching from the rest of apps. 434 WindowState winShowWhenLocked = (WindowState) policy.getWinShowWhenLockedLw(); 435 AppWindowToken appShowWhenLocked = winShowWhenLocked == null 436 ? null : winShowWhenLocked.mAppToken; 437 if (appShowWhenLocked != null) { 438 int req = appShowWhenLocked.getOrientation(); 439 if (req == SCREEN_ORIENTATION_BEHIND) { 440 req = mService.mLastKeyguardForcedOrientation; 441 } 442 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Done at " + appShowWhenLocked 443 + " -- show when locked, return " + req); 444 return req; 445 } 446 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 447 "No one is requesting an orientation when the screen is locked"); 448 return mService.mLastKeyguardForcedOrientation; 449 } 450 } 451 452 // Top system windows are not requesting an orientation. Start searching from apps. 453 return mTaskStackContainers.getOrientation(); 454 } 455 456 void updateDisplayInfo() { 457 mDisplay.getDisplayInfo(mDisplayInfo); 458 mDisplay.getMetrics(mDisplayMetrics); 459 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 460 mTaskStackContainers.get(i).updateDisplayInfo(null); 461 } 462 } 463 464 void initializeDisplayBaseInfo() { 465 final DisplayManagerInternal displayManagerInternal = mService.mDisplayManagerInternal; 466 if (displayManagerInternal != null) { 467 // Bootstrap the default logical display from the display manager. 468 final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId); 469 if (newDisplayInfo != null) { 470 mDisplayInfo.copyFrom(newDisplayInfo); 471 } 472 } 473 474 mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth; 475 mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight; 476 mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi; 477 mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight); 478 } 479 480 void getLogicalDisplayRect(Rect out) { 481 // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked. 482 final int orientation = mDisplayInfo.rotation; 483 boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270); 484 final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; 485 final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; 486 int width = mDisplayInfo.logicalWidth; 487 int left = (physWidth - width) / 2; 488 int height = mDisplayInfo.logicalHeight; 489 int top = (physHeight - height) / 2; 490 out.set(left, top, left + width, top + height); 491 } 492 493 private void getLogicalDisplayRect(Rect out, int orientation) { 494 getLogicalDisplayRect(out); 495 496 // Rotate the Rect if needed. 497 final int currentRotation = mDisplayInfo.rotation; 498 final int rotationDelta = deltaRotation(currentRotation, orientation); 499 if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) { 500 createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix); 501 mTmpRectF.set(out); 502 mTmpMatrix.mapRect(mTmpRectF); 503 mTmpRectF.round(out); 504 } 505 } 506 507 void getContentRect(Rect out) { 508 out.set(mContentRect); 509 } 510 511 /** Refer to {@link WindowManagerService#attachStack(int, int, boolean)} */ 512 void attachStack(TaskStack stack, boolean onTop) { 513 mTaskStackContainers.attachStack(stack, onTop); 514 } 515 516 void moveStack(TaskStack stack, boolean toTop) { 517 mTaskStackContainers.moveStack(stack, toTop); 518 } 519 520 @Override 521 protected void addChild(DisplayChildWindowContainer child, 522 Comparator<DisplayChildWindowContainer> comparator) { 523 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 524 } 525 526 @Override 527 protected void addChild(DisplayChildWindowContainer child, int index) { 528 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 529 } 530 531 @Override 532 protected void removeChild(DisplayChildWindowContainer child) { 533 // Only allow removal of direct children from this display if the display is in the process 534 // of been removed. 535 if (mRemovingDisplay) { 536 super.removeChild(child); 537 return; 538 } 539 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 540 } 541 542 /** 543 * Propagate the new bounds to all child stacks. 544 * @param contentRect The bounds to apply at the top level. 545 */ 546 void resize(Rect contentRect) { 547 mContentRect.set(contentRect); 548 } 549 550 int taskIdFromPoint(int x, int y) { 551 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 552 final TaskStack stack = mTaskStackContainers.get(stackNdx); 553 final int taskId = stack.taskIdFromPoint(x, y); 554 if (taskId != -1) { 555 return taskId; 556 } 557 } 558 return -1; 559 } 560 561 /** 562 * Find the task whose outside touch area (for resizing) (x, y) falls within. 563 * Returns null if the touch doesn't fall into a resizing area. 564 */ 565 Task findTaskForResizePoint(int x, int y) { 566 final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics); 567 mTmpTaskForResizePointSearchResult.reset(); 568 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 569 final TaskStack stack = mTaskStackContainers.get(stackNdx); 570 if (!StackId.isTaskResizeAllowed(stack.mStackId)) { 571 return null; 572 } 573 574 stack.findTaskForResizePoint(x, y, delta, mTmpTaskForResizePointSearchResult); 575 if (mTmpTaskForResizePointSearchResult.searchDone) { 576 return mTmpTaskForResizePointSearchResult.taskForResize; 577 } 578 } 579 return null; 580 } 581 582 void setTouchExcludeRegion(Task focusedTask) { 583 mTouchExcludeRegion.set(mBaseDisplayRect); 584 final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics); 585 mTmpRect2.setEmpty(); 586 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 587 final TaskStack stack = mTaskStackContainers.get(stackNdx); 588 stack.setTouchExcludeRegion( 589 focusedTask, delta, mTouchExcludeRegion, mContentRect, mTmpRect2); 590 } 591 // If we removed the focused task above, add it back and only leave its 592 // outside touch area in the exclusion. TapDectector is not interested in 593 // any touch inside the focused task itself. 594 if (!mTmpRect2.isEmpty()) { 595 mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION); 596 } 597 final WindowState inputMethod = mService.mInputMethodWindow; 598 if (inputMethod != null && inputMethod.isVisibleLw()) { 599 // If the input method is visible and the user is typing, we don't want these touch 600 // events to be intercepted and used to change focus. This would likely cause a 601 // disappearance of the input method. 602 inputMethod.getTouchableRegion(mTmpRegion); 603 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION); 604 } 605 for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) { 606 WindowState win = mTapExcludedWindows.get(i); 607 win.getTouchableRegion(mTmpRegion); 608 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION); 609 } 610 if (getDockedStackVisibleForUserLocked() != null) { 611 mDividerControllerLocked.getTouchRegion(mTmpRect); 612 mTmpRegion.set(mTmpRect); 613 mTouchExcludeRegion.op(mTmpRegion, Op.UNION); 614 } 615 if (mTapDetector != null) { 616 mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion); 617 } 618 } 619 620 void switchUser() { 621 final WindowList windows = getWindowList(); 622 for (int i = 0; i < windows.size(); i++) { 623 final WindowState win = windows.get(i); 624 if (win.isHiddenFromUserLocked()) { 625 if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + win 626 + ", attrs=" + win.mAttrs.type + ", belonging to " + win.mOwnerUid); 627 win.hideLw(false); 628 } 629 } 630 631 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 632 mTaskStackContainers.get(stackNdx).switchUser(); 633 } 634 635 rebuildAppWindowList(); 636 } 637 638 void resetAnimationBackgroundAnimator() { 639 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 640 mTaskStackContainers.get(stackNdx).resetAnimationBackgroundAnimator(); 641 } 642 } 643 644 boolean animateDimLayers() { 645 return mDimLayerController.animateDimLayers(); 646 } 647 648 void resetDimming() { 649 mDimLayerController.resetDimming(); 650 } 651 652 boolean isDimming() { 653 return mDimLayerController.isDimming(); 654 } 655 656 void stopDimmingIfNeeded() { 657 mDimLayerController.stopDimmingIfNeeded(); 658 } 659 660 @Override 661 void removeIfPossible() { 662 if (isAnimating()) { 663 mDeferredRemoval = true; 664 return; 665 } 666 removeImmediately(); 667 } 668 669 @Override 670 void removeImmediately() { 671 mRemovingDisplay = true; 672 try { 673 super.removeImmediately(); 674 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this); 675 mDimLayerController.close(); 676 if (mDisplayId == DEFAULT_DISPLAY) { 677 mService.unregisterPointerEventListener(mTapDetector); 678 mService.unregisterPointerEventListener(mService.mMousePositionTracker); 679 } 680 } finally { 681 mRemovingDisplay = false; 682 } 683 } 684 685 /** Returns true if a removal action is still being deferred. */ 686 @Override 687 boolean checkCompleteDeferredRemoval() { 688 final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval(); 689 690 if (!stillDeferringRemoval && mDeferredRemoval) { 691 removeImmediately(); 692 mService.onDisplayRemoved(mDisplayId); 693 return false; 694 } 695 return true; 696 } 697 698 boolean animateForIme(float interpolatedValue, float animationTarget, 699 float dividerAnimationTarget) { 700 boolean updated = false; 701 702 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 703 final TaskStack stack = mTaskStackContainers.get(i); 704 if (stack == null || !stack.isAdjustedForIme()) { 705 continue; 706 } 707 708 if (interpolatedValue >= 1f && animationTarget == 0f && dividerAnimationTarget == 0f) { 709 stack.resetAdjustedForIme(true /* adjustBoundsNow */); 710 updated = true; 711 } else { 712 mDividerControllerLocked.mLastAnimationProgress = 713 mDividerControllerLocked.getInterpolatedAnimationValue(interpolatedValue); 714 mDividerControllerLocked.mLastDividerProgress = 715 mDividerControllerLocked.getInterpolatedDividerValue(interpolatedValue); 716 updated |= stack.updateAdjustForIme( 717 mDividerControllerLocked.mLastAnimationProgress, 718 mDividerControllerLocked.mLastDividerProgress, 719 false /* force */); 720 } 721 if (interpolatedValue >= 1f) { 722 stack.endImeAdjustAnimation(); 723 } 724 } 725 726 return updated; 727 } 728 729 boolean clearImeAdjustAnimation() { 730 boolean changed = false; 731 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 732 final TaskStack stack = mTaskStackContainers.get(i); 733 if (stack != null && stack.isAdjustedForIme()) { 734 stack.resetAdjustedForIme(true /* adjustBoundsNow */); 735 changed = true; 736 } 737 } 738 return changed; 739 } 740 741 void beginImeAdjustAnimation() { 742 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 743 final TaskStack stack = mTaskStackContainers.get(i); 744 if (stack.isVisible() && stack.isAdjustedForIme()) { 745 stack.beginImeAdjustAnimation(); 746 } 747 } 748 } 749 750 void adjustForImeIfNeeded() { 751 final WindowState imeWin = mService.mInputMethodWindow; 752 final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw() 753 && !mDividerControllerLocked.isImeHideRequested(); 754 final boolean dockVisible = mService.isStackVisibleLocked(DOCKED_STACK_ID); 755 final TaskStack imeTargetStack = mService.getImeFocusStackLocked(); 756 final int imeDockSide = (dockVisible && imeTargetStack != null) ? 757 imeTargetStack.getDockSide() : DOCKED_INVALID; 758 final boolean imeOnTop = (imeDockSide == DOCKED_TOP); 759 final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM); 760 final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock(); 761 final int imeHeight = mService.mPolicy.getInputMethodWindowVisibleHeightLw(); 762 final boolean imeHeightChanged = imeVisible && 763 imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor(); 764 765 // The divider could be adjusted for IME position, or be thinner than usual, 766 // or both. There are three possible cases: 767 // - If IME is visible, and focus is on top, divider is not moved for IME but thinner. 768 // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner. 769 // - If IME is not visible, divider is not moved and is normal width. 770 771 if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) { 772 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 773 final TaskStack stack = mTaskStackContainers.get(i); 774 final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM; 775 if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)) { 776 stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged); 777 } else { 778 stack.resetAdjustedForIme(false); 779 } 780 } 781 mDividerControllerLocked.setAdjustedForIme( 782 imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight); 783 } else { 784 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 785 final TaskStack stack = mTaskStackContainers.get(i); 786 stack.resetAdjustedForIme(!dockVisible); 787 } 788 mDividerControllerLocked.setAdjustedForIme( 789 false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight); 790 } 791 } 792 793 void setInputMethodAnimLayerAdjustment(int adj) { 794 if (DEBUG_LAYERS) Slog.v(TAG_WM, "Setting im layer adj to " + adj); 795 mInputMethodAnimLayerAdjustment = adj; 796 final WindowState imw = mService.mInputMethodWindow; 797 if (imw != null) { 798 imw.adjustAnimLayer(adj); 799 } 800 for (int i = mService.mInputMethodDialogs.size() - 1; i >= 0; i--) { 801 final WindowState dialog = mService.mInputMethodDialogs.get(i); 802 // TODO: This and other places setting mAnimLayer can probably use WS.adjustAnimLayer, 803 // but need to make sure we are not setting things twice for child windows that are 804 // already in the list. 805 dialog.mWinAnimator.mAnimLayer = dialog.mLayer + adj; 806 if (DEBUG_LAYERS) Slog.v(TAG_WM, "IM win " + imw 807 + " anim layer: " + dialog.mWinAnimator.mAnimLayer); 808 } 809 } 810 811 /** 812 * If a window that has an animation specifying a colored background and the current wallpaper 813 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 814 * suddenly disappear. 815 */ 816 int getLayerForAnimationBackground(WindowStateAnimator winAnimator) { 817 for (int i = mWindows.size() - 1; i >= 0; --i) { 818 final WindowState win = mWindows.get(i); 819 if (win.mIsWallpaper && win.isVisibleNow()) { 820 return win.mWinAnimator.mAnimLayer; 821 } 822 } 823 return winAnimator.mAnimLayer; 824 } 825 826 void prepareFreezingTaskBounds() { 827 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 828 final TaskStack stack = mTaskStackContainers.get(stackNdx); 829 stack.prepareFreezingTaskBounds(); 830 } 831 } 832 833 void rotateBounds(int oldRotation, int newRotation, Rect bounds) { 834 getLogicalDisplayRect(mTmpRect, newRotation); 835 836 // Compute a transform matrix to undo the coordinate space transformation, 837 // and present the window at the same physical position it previously occupied. 838 final int deltaRotation = deltaRotation(newRotation, oldRotation); 839 createRotationMatrix(deltaRotation, mTmpRect.width(), mTmpRect.height(), mTmpMatrix); 840 841 mTmpRectF.set(bounds); 842 mTmpMatrix.mapRect(mTmpRectF); 843 mTmpRectF.round(bounds); 844 } 845 846 static int deltaRotation(int oldRotation, int newRotation) { 847 int delta = newRotation - oldRotation; 848 if (delta < 0) delta += 4; 849 return delta; 850 } 851 852 private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight, 853 Matrix outMatrix) { 854 // For rotations without Z-ordering we don't need the target rectangle's position. 855 createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth, 856 displayHeight, outMatrix); 857 } 858 859 static void createRotationMatrix(int rotation, float rectLeft, float rectTop, 860 float displayWidth, float displayHeight, Matrix outMatrix) { 861 switch (rotation) { 862 case ROTATION_0: 863 outMatrix.reset(); 864 break; 865 case ROTATION_270: 866 outMatrix.setRotate(270, 0, 0); 867 outMatrix.postTranslate(0, displayHeight); 868 outMatrix.postTranslate(rectTop, 0); 869 break; 870 case ROTATION_180: 871 outMatrix.reset(); 872 break; 873 case ROTATION_90: 874 outMatrix.setRotate(90, 0, 0); 875 outMatrix.postTranslate(displayWidth, 0); 876 outMatrix.postTranslate(-rectTop, rectLeft); 877 break; 878 } 879 } 880 881 public void dump(String prefix, PrintWriter pw) { 882 pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId); 883 final String subPrefix = " " + prefix; 884 pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x"); 885 pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity); 886 pw.print("dpi"); 887 if (mInitialDisplayWidth != mBaseDisplayWidth 888 || mInitialDisplayHeight != mBaseDisplayHeight 889 || mInitialDisplayDensity != mBaseDisplayDensity) { 890 pw.print(" base="); 891 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); 892 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi"); 893 } 894 if (mDisplayScalingDisabled) { 895 pw.println(" noscale"); 896 } 897 pw.print(" cur="); 898 pw.print(mDisplayInfo.logicalWidth); 899 pw.print("x"); pw.print(mDisplayInfo.logicalHeight); 900 pw.print(" app="); 901 pw.print(mDisplayInfo.appWidth); 902 pw.print("x"); pw.print(mDisplayInfo.appHeight); 903 pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth); 904 pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight); 905 pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth); 906 pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight); 907 pw.println(subPrefix + "deferred=" + mDeferredRemoval 908 + " mLayoutNeeded=" + mLayoutNeeded); 909 910 pw.println(); 911 pw.println(" Application tokens in top down Z order:"); 912 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 913 final TaskStack stack = mTaskStackContainers.get(stackNdx); 914 stack.dump(prefix + " ", pw); 915 } 916 917 pw.println(); 918 if (!mExitingTokens.isEmpty()) { 919 pw.println(); 920 pw.println(" Exiting tokens:"); 921 for (int i = mExitingTokens.size() - 1; i >= 0; i--) { 922 final WindowToken token = mExitingTokens.get(i); 923 pw.print(" Exiting #"); pw.print(i); 924 pw.print(' '); pw.print(token); 925 pw.println(':'); 926 token.dump(pw, " "); 927 } 928 } 929 pw.println(); 930 mDimLayerController.dump(prefix + " ", pw); 931 pw.println(); 932 mDividerControllerLocked.dump(prefix + " ", pw); 933 934 if (mInputMethodAnimLayerAdjustment != 0) { 935 pw.println(subPrefix 936 + "mInputMethodAnimLayerAdjustment=" + mInputMethodAnimLayerAdjustment); 937 } 938 } 939 940 @Override 941 public String toString() { 942 return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren; 943 } 944 945 String getName() { 946 return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\""; 947 } 948 949 /** 950 * @return The docked stack, but only if it is visible, and {@code null} otherwise. 951 */ 952 TaskStack getDockedStackLocked() { 953 final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID); 954 return (stack != null && stack.isVisible()) ? stack : null; 955 } 956 957 /** 958 * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not 959 * visible, as long as it's not hidden because the current user doesn't have any tasks there. 960 */ 961 TaskStack getDockedStackVisibleForUserLocked() { 962 final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID); 963 return (stack != null && stack.isVisible(true /* ignoreKeyguard */)) ? stack : null; 964 } 965 966 /** Find the visible, touch-deliverable window under the given point */ 967 WindowState getTouchableWinAtPointLocked(float xf, float yf) { 968 WindowState touchedWin = null; 969 final int x = (int) xf; 970 final int y = (int) yf; 971 972 for (int i = mWindows.size() - 1; i >= 0; i--) { 973 WindowState window = mWindows.get(i); 974 final int flags = window.mAttrs.flags; 975 if (!window.isVisibleLw()) { 976 continue; 977 } 978 if ((flags & FLAG_NOT_TOUCHABLE) != 0) { 979 continue; 980 } 981 982 window.getVisibleBounds(mTmpRect); 983 if (!mTmpRect.contains(x, y)) { 984 continue; 985 } 986 987 window.getTouchableRegion(mTmpRegion); 988 989 final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL); 990 if (mTmpRegion.contains(x, y) || touchFlags == 0) { 991 touchedWin = window; 992 break; 993 } 994 } 995 996 return touchedWin; 997 } 998 999 boolean canAddToastWindowForUid(int uid) { 1000 // We allow one toast window per UID being shown at a time. 1001 WindowList windows = getWindowList(); 1002 final int windowCount = windows.size(); 1003 for (int i = 0; i < windowCount; i++) { 1004 WindowState window = windows.get(i); 1005 if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == uid 1006 && !window.mPermanentlyHidden && !window.mAnimatingExit 1007 && !window.mRemoveOnExit) { 1008 return false; 1009 } 1010 } 1011 return true; 1012 } 1013 1014 void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) { 1015 if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) { 1016 return; 1017 } 1018 final int lostFocusUid = oldFocus.mOwnerUid; 1019 final WindowList windows = getWindowList(); 1020 final int windowCount = windows.size(); 1021 final Handler handler = mService.mH; 1022 for (int i = 0; i < windowCount; i++) { 1023 final WindowState window = windows.get(i); 1024 if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == lostFocusUid) { 1025 if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, window)) { 1026 handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, window), 1027 window.mAttrs.hideTimeoutMilliseconds); 1028 } 1029 } 1030 } 1031 } 1032 1033 WindowState findFocusedWindow() { 1034 final AppWindowToken focusedApp = mService.mFocusedApp; 1035 1036 for (int i = mWindows.size() - 1; i >= 0; i--) { 1037 final WindowState win = mWindows.get(i); 1038 1039 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + i + " = " + win 1040 + ", flags=" + win.mAttrs.flags + ", canReceive=" + win.canReceiveKeys()); 1041 1042 if (!win.canReceiveKeys()) { 1043 continue; 1044 } 1045 1046 final AppWindowToken wtoken = win.mAppToken; 1047 1048 // If this window's application has been removed, just skip it. 1049 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 1050 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because " 1051 + (wtoken.removed ? "removed" : "sendingToBottom")); 1052 continue; 1053 } 1054 1055 if (focusedApp == null) { 1056 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null" 1057 + " using new focus @ " + i + " = " + win); 1058 return win; 1059 } 1060 1061 if (!focusedApp.windowsAreFocusable()) { 1062 // Current focused app windows aren't focusable... 1063 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not" 1064 + " focusable using new focus @ " + i + " = " + win); 1065 return win; 1066 } 1067 1068 // Descend through all of the app tokens and find the first that either matches 1069 // win.mAppToken (return win) or mFocusedApp (return null). 1070 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING) { 1071 if (focusedApp.compareTo(wtoken) > 0) { 1072 // App stack below focused app stack. No focus for you!!! 1073 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, 1074 "findFocusedWindow: Reached focused app=" + focusedApp); 1075 return null; 1076 } 1077 } 1078 1079 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " 1080 + i + " = " + win); 1081 return win; 1082 } 1083 1084 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows."); 1085 return null; 1086 } 1087 1088 int addAppWindowToWindowList(final WindowState win) { 1089 final IWindow client = win.mClient; 1090 1091 WindowList tokenWindowList = getTokenWindowsOnDisplay(win.mToken); 1092 if (!tokenWindowList.isEmpty()) { 1093 return addAppWindowExisting(win, tokenWindowList); 1094 } 1095 1096 // No windows from this token on this display 1097 if (localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window " 1098 + client.asBinder() + " (token=" + this + ")"); 1099 1100 final WindowToken wToken = win.mToken; 1101 1102 // Figure out where the window should go, based on the order of applications. 1103 mTmpGetWindowOnDisplaySearchResult.reset(); 1104 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1105 final TaskStack stack = mTaskStackContainers.get(i); 1106 stack.getWindowOnDisplayBeforeToken(this, wToken, mTmpGetWindowOnDisplaySearchResult); 1107 if (mTmpGetWindowOnDisplaySearchResult.reachedToken) { 1108 // We have reach the token we are interested in. End search. 1109 break; 1110 } 1111 } 1112 1113 WindowState pos = mTmpGetWindowOnDisplaySearchResult.foundWindow; 1114 1115 // We now know the index into the apps. If we found an app window above, that gives us the 1116 // position; else we need to look some more. 1117 if (pos != null) { 1118 // Move behind any windows attached to this one. 1119 final WindowToken atoken = getWindowToken(pos.mClient.asBinder()); 1120 if (atoken != null) { 1121 tokenWindowList = getTokenWindowsOnDisplay(atoken); 1122 final int NC = tokenWindowList.size(); 1123 if (NC > 0) { 1124 WindowState bottom = tokenWindowList.get(0); 1125 if (bottom.mSubLayer < 0) { 1126 pos = bottom; 1127 } 1128 } 1129 } 1130 addWindowToListBefore(win, pos); 1131 return 0; 1132 } 1133 1134 // Continue looking down until we find the first token that has windows on this display. 1135 mTmpGetWindowOnDisplaySearchResult.reset(); 1136 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1137 final TaskStack stack = mTaskStackContainers.get(i); 1138 stack.getWindowOnDisplayAfterToken(this, wToken, mTmpGetWindowOnDisplaySearchResult); 1139 if (mTmpGetWindowOnDisplaySearchResult.foundWindow != null) { 1140 // We have found a window after the token. End search. 1141 break; 1142 } 1143 } 1144 1145 pos = mTmpGetWindowOnDisplaySearchResult.foundWindow; 1146 1147 if (pos != null) { 1148 // Move in front of any windows attached to this one. 1149 final WindowToken atoken = getWindowToken(pos.mClient.asBinder()); 1150 if (atoken != null) { 1151 final WindowState top = atoken.getTopWindow(); 1152 if (top != null && top.mSubLayer >= 0) { 1153 pos = top; 1154 } 1155 } 1156 addWindowToListAfter(win, pos); 1157 return 0; 1158 } 1159 1160 // Just search for the start of this layer. 1161 final int myLayer = win.mBaseLayer; 1162 int i; 1163 for (i = mWindows.size() - 1; i >= 0; --i) { 1164 final WindowState w = mWindows.get(i); 1165 // Dock divider shares the base layer with application windows, but we want to always 1166 // keep it above the application windows. The sharing of the base layer is intended 1167 // for window animations, which need to be above the dock divider for the duration 1168 // of the animation. 1169 if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) { 1170 break; 1171 } 1172 } 1173 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1174 "Based on layer: Adding window " + win + " at " + (i + 1) + " of " 1175 + mWindows.size()); 1176 mWindows.add(i + 1, win); 1177 mService.mWindowsChanged = true; 1178 return 0; 1179 } 1180 1181 /** Adds this non-app window to the window list. */ 1182 void addNonAppWindowToWindowList(WindowState win) { 1183 // Figure out where window should go, based on layer. 1184 int i; 1185 for (i = mWindows.size() - 1; i >= 0; i--) { 1186 final WindowState otherWin = mWindows.get(i); 1187 if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= win.mBaseLayer) { 1188 // Wallpaper wanders through the window list, for example to position itself 1189 // directly behind keyguard. Because of this it will break the ordering based on 1190 // WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and 1191 // we don't want the new window to appear above them. An example of this is adding 1192 // of the docked stack divider. Consider a scenario with the following ordering (top 1193 // to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider 1194 // to land below the assist preview, so the dock divider must ignore the wallpaper, 1195 // with which it shares the base layer. 1196 break; 1197 } 1198 } 1199 1200 i++; 1201 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1202 "Free window: Adding window " + this + " at " + i + " of " + mWindows.size()); 1203 mWindows.add(i, win); 1204 mService.mWindowsChanged = true; 1205 } 1206 1207 void addToWindowList(WindowState win, int index) { 1208 mWindows.add(index, win); 1209 } 1210 1211 boolean removeFromWindowList(WindowState win) { 1212 return mWindows.remove(win); 1213 } 1214 1215 private int removeWindowAndChildrenFromWindowList(WindowState win, int interestingPos) { 1216 final WindowList windows = getWindowList(); 1217 int wpos = windows.indexOf(win); 1218 if (wpos < 0) { 1219 return interestingPos; 1220 } 1221 1222 if (wpos < interestingPos) interestingPos--; 1223 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing at " + wpos + ": " + this); 1224 windows.remove(wpos); 1225 mService.mWindowsChanged = true; 1226 int childWinCount = win.mChildren.size(); 1227 while (childWinCount > 0) { 1228 childWinCount--; 1229 final WindowState cw = win.mChildren.get(childWinCount); 1230 int cpos = windows.indexOf(cw); 1231 if (cpos >= 0) { 1232 if (cpos < interestingPos) interestingPos--; 1233 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, 1234 "Temp removing child at " + cpos + ": " + cw); 1235 windows.remove(cpos); 1236 } 1237 } 1238 return interestingPos; 1239 } 1240 1241 void addChildWindowToWindowList(WindowState win) { 1242 final WindowState parentWindow = win.getParentWindow(); 1243 1244 WindowList windowsOnSameDisplay = getTokenWindowsOnDisplay(win.mToken); 1245 1246 // Figure out this window's ordering relative to the parent window. 1247 final int wCount = windowsOnSameDisplay.size(); 1248 final int sublayer = win.mSubLayer; 1249 int largestSublayer = Integer.MIN_VALUE; 1250 WindowState windowWithLargestSublayer = null; 1251 int i; 1252 for (i = 0; i < wCount; i++) { 1253 WindowState w = windowsOnSameDisplay.get(i); 1254 final int wSublayer = w.mSubLayer; 1255 if (wSublayer >= largestSublayer) { 1256 largestSublayer = wSublayer; 1257 windowWithLargestSublayer = w; 1258 } 1259 if (sublayer < 0) { 1260 // For negative sublayers, we go below all windows in the same sublayer. 1261 if (wSublayer >= sublayer) { 1262 addWindowToListBefore(win, wSublayer >= 0 ? parentWindow : w); 1263 break; 1264 } 1265 } else { 1266 // For positive sublayers, we go above all windows in the same sublayer. 1267 if (wSublayer > sublayer) { 1268 addWindowToListBefore(win, w); 1269 break; 1270 } 1271 } 1272 } 1273 if (i >= wCount) { 1274 if (sublayer < 0) { 1275 addWindowToListBefore(win, parentWindow); 1276 } else { 1277 addWindowToListAfter(win, 1278 largestSublayer >= 0 ? windowWithLargestSublayer : parentWindow); 1279 } 1280 } 1281 } 1282 1283 /** Updates the layer assignment of windows on this display. */ 1284 void assignWindowLayers(boolean setLayoutNeeded) { 1285 mLayersController.assignWindowLayers(mWindows); 1286 if (setLayoutNeeded) { 1287 setLayoutNeeded(); 1288 } 1289 } 1290 1291 void adjustWallpaperWindows() { 1292 if (mWallpaperController.adjustWallpaperWindows(mWindows)) { 1293 assignWindowLayers(true /*setLayoutNeeded*/); 1294 } 1295 } 1296 1297 /** 1298 * Z-orders the display window list so that: 1299 * <ul> 1300 * <li>Any windows that are currently below the wallpaper window stay below the wallpaper 1301 * window. 1302 * <li>Exiting application windows are at the bottom, but above the wallpaper window. 1303 * <li>All other application windows are above the exiting application windows and ordered based 1304 * on the ordering of their stacks and tasks on the display. 1305 * <li>Non-application windows are at the very top. 1306 * </ul> 1307 * <p> 1308 * NOTE: This isn't a complete picture of what the user see. Further manipulation of the window 1309 * surface layering is done in {@link WindowLayersController}. 1310 */ 1311 void rebuildAppWindowList() { 1312 int count = mWindows.size(); 1313 int i; 1314 int lastBelow = -1; 1315 int numRemoved = 0; 1316 1317 if (mRebuildTmp.length < count) { 1318 mRebuildTmp = new WindowState[count + 10]; 1319 } 1320 1321 // First remove all existing app windows. 1322 i = 0; 1323 while (i < count) { 1324 final WindowState w = mWindows.get(i); 1325 if (w.mAppToken != null) { 1326 final WindowState win = mWindows.remove(i); 1327 win.mRebuilding = true; 1328 mRebuildTmp[numRemoved] = win; 1329 mService.mWindowsChanged = true; 1330 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win); 1331 count--; 1332 numRemoved++; 1333 continue; 1334 } else if (lastBelow == i-1) { 1335 if (w.mAttrs.type == TYPE_WALLPAPER) { 1336 lastBelow = i; 1337 } 1338 } 1339 i++; 1340 } 1341 1342 // Keep whatever windows were below the app windows still below, by skipping them. 1343 lastBelow++; 1344 i = lastBelow; 1345 1346 // First add all of the exiting app tokens... these are no longer in the main app list, 1347 // but still have windows shown. We put them in the back because now that the animation is 1348 // over we no longer will care about them. 1349 final int numStacks = mTaskStackContainers.size(); 1350 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 1351 AppTokenList exitingAppTokens = mTaskStackContainers.get(stackNdx).mExitingAppTokens; 1352 int NT = exitingAppTokens.size(); 1353 for (int j = 0; j < NT; j++) { 1354 i = exitingAppTokens.get(j).rebuildWindowListUnchecked(i); 1355 } 1356 } 1357 1358 // And add in the still active app tokens in Z order. 1359 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 1360 i = mTaskStackContainers.get(stackNdx).rebuildWindowList(i); 1361 } 1362 1363 i -= lastBelow; 1364 if (i != numRemoved) { 1365 setLayoutNeeded(); 1366 Slog.w(TAG_WM, "On display=" + mDisplayId + " Rebuild removed " + numRemoved 1367 + " windows but added " + i + " rebuildAppWindowListLocked() " 1368 + " callers=" + Debug.getCallers(10)); 1369 for (i = 0; i < numRemoved; i++) { 1370 WindowState ws = mRebuildTmp[i]; 1371 if (ws.mRebuilding) { 1372 StringWriter sw = new StringWriter(); 1373 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 1374 ws.dump(pw, "", true); 1375 pw.flush(); 1376 Slog.w(TAG_WM, "This window was lost: " + ws); 1377 Slog.w(TAG_WM, sw.toString()); 1378 ws.mWinAnimator.destroySurfaceLocked(); 1379 } 1380 } 1381 Slog.w(TAG_WM, "Current window hierarchy:"); 1382 dumpChildrenNames(); 1383 Slog.w(TAG_WM, "Final window list:"); 1384 dumpWindows(); 1385 } 1386 Arrays.fill(mRebuildTmp, null); 1387 } 1388 1389 /** Return the list of Windows on this display associated with the input token. */ 1390 WindowList getTokenWindowsOnDisplay(WindowToken token) { 1391 final WindowList windowList = new WindowList(); 1392 final int count = mWindows.size(); 1393 for (int i = 0; i < count; i++) { 1394 final WindowState win = mWindows.get(i); 1395 if (win.mToken == token) { 1396 windowList.add(win); 1397 } 1398 } 1399 return windowList; 1400 } 1401 1402 private void reAddToWindowList(WindowState win) { 1403 win.mToken.addWindow(win); 1404 // This is a hack to get all of the child windows added as well at the right position. Child 1405 // windows should be rare and this case should be rare, so it shouldn't be that big a deal. 1406 int wpos = mWindows.indexOf(win); 1407 if (wpos >= 0) { 1408 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "ReAdd removing from " + wpos + ": " + win); 1409 mWindows.remove(wpos); 1410 mService.mWindowsChanged = true; 1411 win.reAddWindow(wpos); 1412 } 1413 } 1414 1415 void moveInputMethodDialogs(int pos) { 1416 ArrayList<WindowState> dialogs = mService.mInputMethodDialogs; 1417 1418 final int N = dialogs.size(); 1419 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Removing " + N + " dialogs w/pos=" + pos); 1420 for (int i = 0; i < N; i++) { 1421 pos = removeWindowAndChildrenFromWindowList(dialogs.get(i), pos); 1422 } 1423 if (DEBUG_INPUT_METHOD) { 1424 Slog.v(TAG_WM, "Window list w/pos=" + pos); 1425 logWindowList(mWindows, " "); 1426 } 1427 1428 WindowState ime = mService.mInputMethodWindow; 1429 if (pos >= 0) { 1430 // Skip windows owned by the input method. 1431 if (ime != null) { 1432 while (pos < mWindows.size()) { 1433 WindowState wp = mWindows.get(pos); 1434 if (wp == ime || wp.getParentWindow() == ime) { 1435 pos++; 1436 continue; 1437 } 1438 break; 1439 } 1440 } 1441 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Adding " + N + " dialogs at pos=" + pos); 1442 for (int i=0; i<N; i++) { 1443 WindowState win = dialogs.get(i); 1444 pos = win.reAddWindow(pos); 1445 } 1446 if (DEBUG_INPUT_METHOD) { 1447 Slog.v(TAG_WM, "Final window list:"); 1448 logWindowList(mWindows, " "); 1449 } 1450 return; 1451 } 1452 for (int i=0; i<N; i++) { 1453 WindowState win = dialogs.get(i); 1454 reAddToWindowList(win); 1455 if (DEBUG_INPUT_METHOD) { 1456 Slog.v(TAG_WM, "No IM target, final list:"); 1457 logWindowList(mWindows, " "); 1458 } 1459 } 1460 } 1461 1462 boolean moveInputMethodWindowsIfNeeded(boolean needAssignLayers) { 1463 final WindowState imWin = mService.mInputMethodWindow; 1464 final int DN = mService.mInputMethodDialogs.size(); 1465 if (imWin == null && DN == 0) { 1466 return false; 1467 } 1468 1469 // TODO(multidisplay): IMEs are only supported on the default display. 1470 WindowList windows = mWindows; 1471 1472 int imPos = findDesiredInputMethodWindowIndex(true); 1473 if (imPos >= 0) { 1474 // In this case, the input method windows are to be placed 1475 // immediately above the window they are targeting. 1476 1477 // First check to see if the input method windows are already 1478 // located here, and contiguous. 1479 final int N = windows.size(); 1480 final WindowState firstImWin = imPos < N ? windows.get(imPos) : null; 1481 1482 // Figure out the actual input method window that should be 1483 // at the bottom of their stack. 1484 WindowState baseImWin = imWin != null ? imWin : mService.mInputMethodDialogs.get(0); 1485 final WindowState cw = baseImWin.getBottomChild(); 1486 if (cw != null && cw.mSubLayer < 0) { 1487 baseImWin = cw; 1488 } 1489 1490 if (firstImWin == baseImWin) { 1491 // The windows haven't moved... but are they still contiguous? 1492 // First find the top IM window. 1493 int pos = imPos+1; 1494 while (pos < N) { 1495 if (!(windows.get(pos)).mIsImWindow) { 1496 break; 1497 } 1498 pos++; 1499 } 1500 pos++; 1501 // Now there should be no more input method windows above. 1502 while (pos < N) { 1503 if ((windows.get(pos)).mIsImWindow) { 1504 break; 1505 } 1506 pos++; 1507 } 1508 if (pos >= N) { 1509 return false; 1510 } 1511 } 1512 1513 if (imWin != null) { 1514 if (DEBUG_INPUT_METHOD) { 1515 Slog.v(TAG_WM, "Moving IM from " + imPos); 1516 logWindowList(windows, " "); 1517 } 1518 imPos = removeWindowAndChildrenFromWindowList(imWin, imPos); 1519 if (DEBUG_INPUT_METHOD) { 1520 Slog.v(TAG_WM, "List after removing with new pos " + imPos + ":"); 1521 logWindowList(windows, " "); 1522 } 1523 imWin.reAddWindow(imPos); 1524 if (DEBUG_INPUT_METHOD) { 1525 Slog.v(TAG_WM, "List after moving IM to " + imPos + ":"); 1526 logWindowList(windows, " "); 1527 } 1528 if (DN > 0) moveInputMethodDialogs(imPos+1); 1529 } else { 1530 moveInputMethodDialogs(imPos); 1531 } 1532 1533 } else { 1534 // In this case, the input method windows go in a fixed layer, 1535 // because they aren't currently associated with a focus window. 1536 1537 if (imWin != null) { 1538 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Moving IM from " + imPos); 1539 removeWindowAndChildrenFromWindowList(imWin, 0); 1540 reAddToWindowList(imWin); 1541 if (DEBUG_INPUT_METHOD) { 1542 Slog.v(TAG_WM, "List with no IM target:"); 1543 logWindowList(windows, " "); 1544 } 1545 if (DN > 0) moveInputMethodDialogs(-1); 1546 } else { 1547 moveInputMethodDialogs(-1); 1548 } 1549 1550 } 1551 1552 if (needAssignLayers) { 1553 assignWindowLayers(false /* setLayoutNeeded */); 1554 } 1555 1556 return true; 1557 } 1558 1559 /** 1560 * Dig through the WindowStates and find the one that the Input Method will target. 1561 * @param willMove 1562 * @return The index+1 in mWindows of the discovered target. 1563 */ 1564 int findDesiredInputMethodWindowIndex(boolean willMove) { 1565 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the 1566 // same display. Or even when the current IME/target are not on the same screen as the next 1567 // IME/target. For now only look for input windows on the main screen. 1568 final WindowList windows = getWindowList(); 1569 WindowState w = null; 1570 int i; 1571 for (i = windows.size() - 1; i >= 0; --i) { 1572 WindowState win = windows.get(i); 1573 1574 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG_WM, "Checking window @" + i 1575 + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags)); 1576 if (canBeImeTarget(win)) { 1577 w = win; 1578 //Slog.i(TAG_WM, "Putting input method here!"); 1579 1580 // Yet more tricksyness! If this window is a "starting" window, we do actually want 1581 // to be on top of it, but it is not -really- where input will go. So if the caller 1582 // is not actually looking to move the IME, look down below for a real window to 1583 // target... 1584 if (!willMove && w.mAttrs.type == TYPE_APPLICATION_STARTING && i > 0) { 1585 WindowState wb = windows.get(i-1); 1586 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) { 1587 i--; 1588 w = wb; 1589 } 1590 } 1591 break; 1592 } 1593 } 1594 1595 // Now w is either mWindows[0] or an IME (or null if mWindows is empty). 1596 1597 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG_WM, "Proposed new IME target: " + w); 1598 1599 // Now, a special case -- if the last target's window is in the process of exiting, and is 1600 // above the new target, keep on the last target to avoid flicker. Consider for example a 1601 // Dialog with the IME shown: when the Dialog is dismissed, we want to keep the IME above it 1602 // until it is completely gone so it doesn't drop behind the dialog or its full-screen 1603 // scrim. 1604 final WindowState curTarget = mService.mInputMethodTarget; 1605 if (curTarget != null 1606 && curTarget.isDisplayedLw() 1607 && curTarget.isClosing() 1608 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) { 1609 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing"); 1610 return windows.indexOf(curTarget) + 1; 1611 } 1612 1613 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" 1614 + w + " willMove=" + willMove); 1615 1616 if (willMove && w != null) { 1617 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken; 1618 if (token != null) { 1619 1620 // Now some fun for dealing with window animations that modify the Z order. We need 1621 // to look at all windows below the current target that are in this app, finding the 1622 // highest visible one in layering. 1623 WindowState highestTarget = null; 1624 int highestPos = 0; 1625 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) { 1626 WindowList curWindows = token.getDisplayContent().getWindowList(); 1627 int pos = curWindows.indexOf(curTarget); 1628 while (pos >= 0) { 1629 WindowState win = curWindows.get(pos); 1630 if (win.mAppToken != token) { 1631 break; 1632 } 1633 if (!win.mRemoved) { 1634 if (highestTarget == null || win.mWinAnimator.mAnimLayer > 1635 highestTarget.mWinAnimator.mAnimLayer) { 1636 highestTarget = win; 1637 highestPos = pos; 1638 } 1639 } 1640 pos--; 1641 } 1642 } 1643 1644 if (highestTarget != null) { 1645 final AppTransition appTransition = mService.mAppTransition; 1646 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, appTransition + " " + highestTarget 1647 + " animating=" + highestTarget.mWinAnimator.isAnimationSet() 1648 + " layer=" + highestTarget.mWinAnimator.mAnimLayer 1649 + " new layer=" + w.mWinAnimator.mAnimLayer); 1650 1651 if (appTransition.isTransitionSet()) { 1652 // If we are currently setting up for an animation, hold everything until we 1653 // can find out what will happen. 1654 mService.mInputMethodTargetWaitingAnim = true; 1655 mService.mInputMethodTarget = highestTarget; 1656 return highestPos + 1; 1657 } else if (highestTarget.mWinAnimator.isAnimationSet() && 1658 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) { 1659 // If the window we are currently targeting is involved with an animation, 1660 // and it is on top of the next target we will be over, then hold off on 1661 // moving until that is done. 1662 mService.mInputMethodTargetWaitingAnim = true; 1663 mService.mInputMethodTarget = highestTarget; 1664 return highestPos + 1; 1665 } 1666 } 1667 } 1668 } 1669 1670 //Slog.i(TAG_WM, "Placing input method @" + (i+1)); 1671 if (w != null) { 1672 if (willMove) { 1673 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to " 1674 + w + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : "")); 1675 mService.mInputMethodTarget = w; 1676 mService.mInputMethodTargetWaitingAnim = false; 1677 if (w.mAppToken != null) { 1678 setInputMethodAnimLayerAdjustment( 1679 w.mAppToken.mAppAnimator.animLayerAdjustment); 1680 } else { 1681 setInputMethodAnimLayerAdjustment(0); 1682 } 1683 } 1684 1685 // If the docked divider is visible, we still need to go through this whole excercise to 1686 // find the appropriate input method target (used for animations and dialog 1687 // adjustments), but for purposes of Z ordering we simply wish to place it above the 1688 // docked divider. Unless it is already above the divider. 1689 final WindowState dockedDivider = mDividerControllerLocked.getWindow(); 1690 if (dockedDivider != null && dockedDivider.isVisibleLw()) { 1691 int dividerIndex = windows.indexOf(dockedDivider); 1692 if (dividerIndex > 0 && dividerIndex > i) { 1693 return dividerIndex + 1; 1694 } 1695 } 1696 return i+1; 1697 } 1698 if (willMove) { 1699 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget 1700 + " to null." + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : "")); 1701 mService.mInputMethodTarget = null; 1702 setInputMethodAnimLayerAdjustment(0); 1703 } 1704 return -1; 1705 } 1706 1707 private static boolean canBeImeTarget(WindowState w) { 1708 final int fl = w.mAttrs.flags & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); 1709 final int type = w.mAttrs.type; 1710 1711 if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM) 1712 && type != TYPE_APPLICATION_STARTING) { 1713 return false; 1714 } 1715 1716 if (DEBUG_INPUT_METHOD) { 1717 Slog.i(TAG_WM, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding()); 1718 if (!w.isVisibleOrAdding()) { 1719 Slog.i(TAG_WM, " mSurfaceController=" + w.mWinAnimator.mSurfaceController 1720 + " relayoutCalled=" + w.mRelayoutCalled 1721 + " viewVis=" + w.mViewVisibility 1722 + " policyVis=" + w.mPolicyVisibility 1723 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim 1724 + " parentHidden=" + w.isParentWindowHidden() 1725 + " exiting=" + w.mAnimatingExit + " destroying=" + w.mDestroying); 1726 if (w.mAppToken != null) { 1727 Slog.i(TAG_WM, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested); 1728 } 1729 } 1730 } 1731 return w.isVisibleOrAdding(); 1732 } 1733 1734 private void logWindowList(final WindowList windows, String prefix) { 1735 int N = windows.size(); 1736 while (N > 0) { 1737 N--; 1738 Slog.v(TAG_WM, prefix + "#" + N + ": " + windows.get(N)); 1739 } 1740 } 1741 1742 boolean getNeedsMenu(WindowState win, WindowManagerPolicy.WindowState bottom) { 1743 int index = -1; 1744 WindowList windows = getWindowList(); 1745 while (true) { 1746 if (win.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) { 1747 return win.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE; 1748 } 1749 // If we reached the bottom of the range of windows we are considering, 1750 // assume no menu is needed. 1751 if (win == bottom) { 1752 return false; 1753 } 1754 // The current window hasn't specified whether menu key is needed; look behind it. 1755 // First, we may need to determine the starting position. 1756 if (index < 0) { 1757 index = windows.indexOf(win); 1758 } 1759 index--; 1760 if (index < 0) { 1761 return false; 1762 } 1763 win = windows.get(index); 1764 } 1765 } 1766 1767 void setLayoutNeeded() { 1768 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3)); 1769 mLayoutNeeded = true; 1770 } 1771 1772 void clearLayoutNeeded() { 1773 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3)); 1774 mLayoutNeeded = false; 1775 } 1776 1777 boolean isLayoutNeeded() { 1778 return mLayoutNeeded; 1779 } 1780 1781 private int addAppWindowExisting(WindowState win, WindowList tokenWindowList) { 1782 1783 int tokenWindowsPos; 1784 // If this application has existing windows, we simply place the new window on top of 1785 // them... but keep the starting window on top. 1786 if (win.mAttrs.type == TYPE_BASE_APPLICATION) { 1787 // Base windows go behind everything else. 1788 final WindowState lowestWindow = tokenWindowList.get(0); 1789 addWindowToListBefore(win, lowestWindow); 1790 tokenWindowsPos = win.mToken.getWindowIndex(lowestWindow); 1791 } else { 1792 final AppWindowToken atoken = win.mAppToken; 1793 final int windowListPos = tokenWindowList.size(); 1794 final WindowState lastWindow = tokenWindowList.get(windowListPos - 1); 1795 if (atoken != null && lastWindow == atoken.startingWindow) { 1796 addWindowToListBefore(win, lastWindow); 1797 tokenWindowsPos = win.mToken.getWindowIndex(lastWindow); 1798 } else { 1799 int newIdx = findIdxBasedOnAppTokens(win); 1800 // There is a window above this one associated with the same apptoken note that the 1801 // window could be a floating window that was created later or a window at the top 1802 // of the list of windows associated with this token. 1803 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1804 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " 1805 + mWindows.size()); 1806 mWindows.add(newIdx + 1, win); 1807 if (newIdx < 0) { 1808 // No window from token found on win's display. 1809 tokenWindowsPos = 0; 1810 } else { 1811 tokenWindowsPos = win.mToken.getWindowIndex(mWindows.get(newIdx)) + 1; 1812 } 1813 mService.mWindowsChanged = true; 1814 } 1815 } 1816 return tokenWindowsPos; 1817 } 1818 1819 /** Places the first input window after the second input window in the window list. */ 1820 private void addWindowToListAfter(WindowState first, WindowState second) { 1821 final int i = mWindows.indexOf(second); 1822 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1823 "Adding window " + this + " at " + (i + 1) + " of " + mWindows.size() 1824 + " (after " + second + ")"); 1825 mWindows.add(i + 1, first); 1826 mService.mWindowsChanged = true; 1827 } 1828 1829 /** Places the first input window before the second input window in the window list. */ 1830 private void addWindowToListBefore(WindowState first, WindowState second) { 1831 int i = mWindows.indexOf(second); 1832 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1833 "Adding window " + this + " at " + i + " of " + mWindows.size() 1834 + " (before " + second + ")"); 1835 if (i < 0) { 1836 Slog.w(TAG_WM, "addWindowToListBefore: Unable to find " + second + " in " + mWindows); 1837 i = 0; 1838 } 1839 mWindows.add(i, first); 1840 mService.mWindowsChanged = true; 1841 } 1842 1843 /** 1844 * This method finds out the index of a window that has the same app token as win. used for z 1845 * ordering the windows in mWindows 1846 */ 1847 private int findIdxBasedOnAppTokens(WindowState win) { 1848 for(int j = mWindows.size() - 1; j >= 0; j--) { 1849 final WindowState wentry = mWindows.get(j); 1850 if(wentry.mAppToken == win.mAppToken) { 1851 return j; 1852 } 1853 } 1854 return -1; 1855 } 1856 1857 private void dumpChildrenNames() { 1858 StringBuilder output = new StringBuilder(); 1859 dumpChildrenNames(output, " "); 1860 Slog.v(TAG_WM, output.toString()); 1861 } 1862 1863 private void dumpWindows() { 1864 Slog.v(TAG_WM, " Display #" + mDisplayId); 1865 final WindowList windows = getWindowList(); 1866 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 1867 Slog.v(TAG_WM, " #" + winNdx + ": " + windows.get(winNdx)); 1868 } 1869 } 1870 1871 void dumpTokens(PrintWriter pw, boolean dumpAll) { 1872 if (mTokenMap.isEmpty()) { 1873 return; 1874 } 1875 pw.println(" Display #" + mDisplayId); 1876 final Iterator<WindowToken> it = mTokenMap.values().iterator(); 1877 while (it.hasNext()) { 1878 final WindowToken token = it.next(); 1879 pw.print(" "); 1880 pw.print(token); 1881 if (dumpAll) { 1882 pw.println(':'); 1883 token.dump(pw, " "); 1884 } else { 1885 pw.println(); 1886 } 1887 } 1888 } 1889 1890 void dumpWindowAnimators(PrintWriter pw, String subPrefix) { 1891 final int count = mWindows.size(); 1892 for (int j = 0; j < count; j++) { 1893 final WindowStateAnimator wAnim = mWindows.get(j).mWinAnimator; 1894 pw.println(subPrefix + "Window #" + j + ": " + wAnim); 1895 } 1896 } 1897 1898 void enableSurfaceTrace(FileDescriptor fd) { 1899 for (int i = mWindows.size() - 1; i >= 0; i--) { 1900 final WindowState win = mWindows.get(i); 1901 win.mWinAnimator.enableSurfaceTrace(fd); 1902 } 1903 } 1904 1905 void disableSurfaceTrace() { 1906 for (int i = mWindows.size() - 1; i >= 0; i--) { 1907 final WindowState win = mWindows.get(i); 1908 win.mWinAnimator.disableSurfaceTrace(); 1909 } 1910 } 1911 1912 boolean checkWaitingForWindows() { 1913 1914 boolean haveBootMsg = false; 1915 boolean haveApp = false; 1916 // if the wallpaper service is disabled on the device, we're never going to have 1917 // wallpaper, don't bother waiting for it 1918 boolean haveWallpaper = false; 1919 boolean wallpaperEnabled = mService.mContext.getResources().getBoolean( 1920 com.android.internal.R.bool.config_enableWallpaperService) 1921 && !mService.mOnlyCore; 1922 boolean haveKeyguard = true; 1923 final int count = mWindows.size(); 1924 for (int i = 0; i < count; i++) { 1925 final WindowState w = mWindows.get(i); 1926 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 1927 return true; 1928 } 1929 if (w.isDrawnLw()) { 1930 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { 1931 haveBootMsg = true; 1932 } else if (w.mAttrs.type == TYPE_APPLICATION 1933 || w.mAttrs.type == TYPE_DRAWN_APPLICATION) { 1934 haveApp = true; 1935 } else if (w.mAttrs.type == TYPE_WALLPAPER) { 1936 haveWallpaper = true; 1937 } else if (w.mAttrs.type == TYPE_STATUS_BAR) { 1938 haveKeyguard = mService.mPolicy.isKeyguardDrawnLw(); 1939 } 1940 } 1941 } 1942 1943 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, 1944 "******** booted=" + mService.mSystemBooted 1945 + " msg=" + mService.mShowingBootMessages 1946 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp 1947 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled 1948 + " haveKeyguard=" + haveKeyguard); 1949 1950 // If we are turning on the screen to show the boot message, don't do it until the boot 1951 // message is actually displayed. 1952 if (!mService.mSystemBooted && !haveBootMsg) { 1953 return true; 1954 } 1955 1956 // If we are turning on the screen after the boot is completed normally, don't do so until 1957 // we have the application and wallpaper. 1958 if (mService.mSystemBooted && ((!haveApp && !haveKeyguard) || 1959 (wallpaperEnabled && !haveWallpaper))) { 1960 return true; 1961 } 1962 1963 return false; 1964 } 1965 1966 void updateWindowsForAnimator(WindowAnimator animator) { 1967 final WindowManagerPolicy policy = animator.mPolicy; 1968 final int keyguardGoingAwayFlags = animator.mKeyguardGoingAwayFlags; 1969 final boolean keyguardGoingAwayToShade = 1970 (keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0; 1971 final boolean keyguardGoingAwayNoAnimation = 1972 (keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0; 1973 final boolean keyguardGoingAwayWithWallpaper = 1974 (keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0; 1975 1976 if (animator.mKeyguardGoingAway) { 1977 for (int i = mWindows.size() - 1; i >= 0; i--) { 1978 WindowState win = mWindows.get(i); 1979 if (!policy.isKeyguardHostWindow(win.mAttrs)) { 1980 continue; 1981 } 1982 final WindowStateAnimator winAnimator = win.mWinAnimator; 1983 if (policy.isKeyguardShowingAndNotOccluded()) { 1984 if (!winAnimator.mAnimating) { 1985 if (DEBUG_KEYGUARD) Slog.d(TAG, 1986 "updateWindowsForAnimator: creating delay animation"); 1987 1988 // Create a new animation to delay until keyguard is gone on its own. 1989 winAnimator.mAnimation = new AlphaAnimation(1.0f, 1.0f); 1990 winAnimator.mAnimation.setDuration(KEYGUARD_ANIM_TIMEOUT_MS); 1991 winAnimator.mAnimationIsEntrance = false; 1992 winAnimator.mAnimationStartTime = -1; 1993 winAnimator.mKeyguardGoingAwayAnimation = true; 1994 winAnimator.mKeyguardGoingAwayWithWallpaper 1995 = keyguardGoingAwayWithWallpaper; 1996 } 1997 } else { 1998 if (DEBUG_KEYGUARD) Slog.d(TAG, 1999 "updateWindowsForAnimator: StatusBar is no longer keyguard"); 2000 animator.mKeyguardGoingAway = false; 2001 winAnimator.clearAnimation(); 2002 } 2003 break; 2004 } 2005 } 2006 2007 animator.mForceHiding = KEYGUARD_NOT_SHOWN; 2008 2009 boolean wallpaperInUnForceHiding = false; 2010 boolean startingInUnForceHiding = false; 2011 ArrayList<WindowStateAnimator> unForceHiding = null; 2012 WindowState wallpaper = null; 2013 final WallpaperController wallpaperController = mWallpaperController; 2014 for (int i = mWindows.size() - 1; i >= 0; i--) { 2015 WindowState win = mWindows.get(i); 2016 WindowStateAnimator winAnimator = win.mWinAnimator; 2017 final int flags = win.mAttrs.flags; 2018 boolean canBeForceHidden = policy.canBeForceHidden(win, win.mAttrs); 2019 boolean shouldBeForceHidden = animator.shouldForceHide(win); 2020 if (winAnimator.hasSurface()) { 2021 final boolean wasAnimating = winAnimator.mWasAnimating; 2022 final boolean nowAnimating = winAnimator.stepAnimationLocked(animator.mCurrentTime); 2023 winAnimator.mWasAnimating = nowAnimating; 2024 animator.orAnimating(nowAnimating); 2025 2026 if (DEBUG_WALLPAPER) Slog.v(TAG, 2027 win + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating); 2028 2029 if (wasAnimating && !winAnimator.mAnimating 2030 && wallpaperController.isWallpaperTarget(win)) { 2031 animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 2032 pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2033 if (DEBUG_LAYOUT_REPEATS) { 2034 mService.mWindowPlacerLocked.debugLayoutRepeats( 2035 "updateWindowsAndWallpaperLocked 2", pendingLayoutChanges); 2036 } 2037 } 2038 2039 if (policy.isForceHiding(win.mAttrs)) { 2040 if (!wasAnimating && nowAnimating) { 2041 if (DEBUG_KEYGUARD || DEBUG_ANIM || DEBUG_VISIBILITY) Slog.v(TAG, 2042 "Animation started that could impact force hide: " + win); 2043 animator.mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED; 2044 pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2045 if (DEBUG_LAYOUT_REPEATS) { 2046 mService.mWindowPlacerLocked.debugLayoutRepeats( 2047 "updateWindowsAndWallpaperLocked 3", pendingLayoutChanges); 2048 } 2049 mService.mFocusMayChange = true; 2050 } else if (animator.mKeyguardGoingAway && !nowAnimating) { 2051 // Timeout!! 2052 Slog.e(TAG, "Timeout waiting for animation to startup"); 2053 policy.startKeyguardExitAnimation(0, 0); 2054 animator.mKeyguardGoingAway = false; 2055 } 2056 if (win.isReadyForDisplay()) { 2057 if (nowAnimating && win.mWinAnimator.mKeyguardGoingAwayAnimation) { 2058 animator.mForceHiding = KEYGUARD_ANIMATING_OUT; 2059 } else { 2060 animator.mForceHiding = win.isDrawnLw() 2061 ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN; 2062 } 2063 } 2064 if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG, 2065 "Force hide " + animator.forceHidingToString() 2066 + " hasSurface=" + win.mHasSurface 2067 + " policyVis=" + win.mPolicyVisibility 2068 + " destroying=" + win.mDestroying 2069 + " parentHidden=" + win.isParentWindowHidden() 2070 + " vis=" + win.mViewVisibility 2071 + " hidden=" + win.mToken.hidden 2072 + " anim=" + win.mWinAnimator.mAnimation); 2073 } else if (canBeForceHidden) { 2074 if (shouldBeForceHidden) { 2075 if (!win.hideLw(false, false)) { 2076 // Was already hidden 2077 continue; 2078 } 2079 if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG, 2080 "Now policy hidden: " + win); 2081 } else { 2082 final Animation postKeyguardExitAnimation = 2083 animator.mPostKeyguardExitAnimation; 2084 boolean applyExistingExitAnimation = postKeyguardExitAnimation != null 2085 && !postKeyguardExitAnimation.hasEnded() 2086 && !winAnimator.mKeyguardGoingAwayAnimation 2087 && win.hasDrawnLw() 2088 && !win.isChildWindow() 2089 && !win.mIsImWindow 2090 && isDefaultDisplay; 2091 2092 // If the window is already showing and we don't need to apply an existing 2093 // Keyguard exit animation, skip. 2094 if (!win.showLw(false, false) && !applyExistingExitAnimation) { 2095 continue; 2096 } 2097 final boolean visibleNow = win.isVisibleNow(); 2098 if (!visibleNow) { 2099 // Couldn't really show, must showLw() again when win becomes visible. 2100 win.hideLw(false, false); 2101 continue; 2102 } 2103 if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG, 2104 "Now policy shown: " + win); 2105 if ((animator.mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0 2106 && !win.isChildWindow()) { 2107 if (unForceHiding == null) { 2108 unForceHiding = new ArrayList<>(); 2109 } 2110 unForceHiding.add(winAnimator); 2111 if ((flags & FLAG_SHOW_WALLPAPER) != 0) { 2112 wallpaperInUnForceHiding = true; 2113 } 2114 if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { 2115 startingInUnForceHiding = true; 2116 } 2117 } else if (applyExistingExitAnimation) { 2118 // We're already in the middle of an animation. Use the existing 2119 // animation to bring in this window. 2120 if (DEBUG_KEYGUARD) Slog.v(TAG, 2121 "Applying existing Keyguard exit animation to new window: win=" 2122 + win); 2123 2124 final Animation a = policy.createForceHideEnterAnimation(false, 2125 keyguardGoingAwayToShade); 2126 winAnimator.setAnimation(a, postKeyguardExitAnimation.getStartTime(), 2127 STACK_CLIP_BEFORE_ANIM); 2128 winAnimator.mKeyguardGoingAwayAnimation = true; 2129 winAnimator.mKeyguardGoingAwayWithWallpaper 2130 = keyguardGoingAwayWithWallpaper; 2131 } 2132 final WindowState currentFocus = mService.mCurrentFocus; 2133 if (currentFocus == null || currentFocus.mLayer < win.mLayer) { 2134 // We are showing on top of the current 2135 // focus, so re-evaluate focus to make 2136 // sure it is correct. 2137 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, 2138 "updateWindowsForAnimator: setting mFocusMayChange true"); 2139 mService.mFocusMayChange = true; 2140 } 2141 } 2142 if ((flags & FLAG_SHOW_WALLPAPER) != 0) { 2143 animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 2144 pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2145 if (DEBUG_LAYOUT_REPEATS) { 2146 mService.mWindowPlacerLocked.debugLayoutRepeats( 2147 "updateWindowsAndWallpaperLocked 4", pendingLayoutChanges); 2148 } 2149 } 2150 } 2151 } 2152 2153 // If the window doesn't have a surface, the only thing we care about is the correct 2154 // policy visibility. 2155 else if (canBeForceHidden) { 2156 if (shouldBeForceHidden) { 2157 win.hideLw(false, false); 2158 } else { 2159 win.showLw(false, false); 2160 } 2161 } 2162 2163 final AppWindowToken atoken = win.mAppToken; 2164 if (winAnimator.mDrawState == READY_TO_SHOW) { 2165 if (atoken == null || atoken.allDrawn) { 2166 if (win.performShowLocked()) { 2167 pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 2168 if (DEBUG_LAYOUT_REPEATS) { 2169 mService.mWindowPlacerLocked.debugLayoutRepeats( 2170 "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges); 2171 } 2172 } 2173 } 2174 } 2175 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator; 2176 if (appAnimator != null && appAnimator.thumbnail != null) { 2177 if (appAnimator.thumbnailTransactionSeq != animator.mAnimTransactionSequence) { 2178 appAnimator.thumbnailTransactionSeq = animator.mAnimTransactionSequence; 2179 appAnimator.thumbnailLayer = 0; 2180 } 2181 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) { 2182 appAnimator.thumbnailLayer = winAnimator.mAnimLayer; 2183 } 2184 } 2185 if (win.mIsWallpaper) { 2186 wallpaper = win; 2187 } 2188 } // end forall windows 2189 2190 // If we have windows that are being shown due to them no longer being force-hidden, apply 2191 // the appropriate animation to them if animations are not disabled. 2192 if (unForceHiding != null) { 2193 if (!keyguardGoingAwayNoAnimation) { 2194 boolean first = true; 2195 for (int i=unForceHiding.size()-1; i>=0; i--) { 2196 final WindowStateAnimator winAnimator = unForceHiding.get(i); 2197 final Animation a = policy.createForceHideEnterAnimation( 2198 wallpaperInUnForceHiding && !startingInUnForceHiding, 2199 keyguardGoingAwayToShade); 2200 if (a != null) { 2201 if (DEBUG_KEYGUARD) Slog.v(TAG, 2202 "Starting keyguard exit animation on window " + winAnimator.mWin); 2203 winAnimator.setAnimation(a, STACK_CLIP_BEFORE_ANIM); 2204 winAnimator.mKeyguardGoingAwayAnimation = true; 2205 winAnimator.mKeyguardGoingAwayWithWallpaper 2206 = keyguardGoingAwayWithWallpaper; 2207 if (first) { 2208 animator.mPostKeyguardExitAnimation = a; 2209 animator.mPostKeyguardExitAnimation.setStartTime(animator.mCurrentTime); 2210 first = false; 2211 } 2212 } 2213 } 2214 } else if (animator.mKeyguardGoingAway) { 2215 policy.startKeyguardExitAnimation(animator.mCurrentTime, 0 /* duration */); 2216 animator.mKeyguardGoingAway = false; 2217 } 2218 2219 2220 // Wallpaper is going away in un-force-hide motion, animate it as well. 2221 if (!wallpaperInUnForceHiding && wallpaper != null && !keyguardGoingAwayNoAnimation) { 2222 if (DEBUG_KEYGUARD) Slog.d(TAG, 2223 "updateWindowsForAnimator: wallpaper animating away"); 2224 final Animation a = policy.createForceHideWallpaperExitAnimation( 2225 keyguardGoingAwayToShade); 2226 if (a != null) { 2227 wallpaper.mWinAnimator.setAnimation(a); 2228 } 2229 } 2230 } 2231 2232 if (animator.mPostKeyguardExitAnimation != null) { 2233 // We're in the midst of a keyguard exit animation. 2234 if (animator.mKeyguardGoingAway) { 2235 policy.startKeyguardExitAnimation(animator.mCurrentTime + 2236 animator.mPostKeyguardExitAnimation.getStartOffset(), 2237 animator.mPostKeyguardExitAnimation.getDuration()); 2238 animator.mKeyguardGoingAway = false; 2239 } 2240 // mPostKeyguardExitAnimation might either be ended normally, cancelled, or "orphaned", 2241 // meaning that the window it was running on was removed. We check for hasEnded() for 2242 // ended normally and cancelled case, and check the time for the "orphaned" case. 2243 else if (animator.mPostKeyguardExitAnimation.hasEnded() 2244 || animator.mCurrentTime - animator.mPostKeyguardExitAnimation.getStartTime() 2245 > animator.mPostKeyguardExitAnimation.getDuration()) { 2246 // Done with the animation, reset. 2247 if (DEBUG_KEYGUARD) Slog.v(TAG, "Done with Keyguard exit animations."); 2248 animator.mPostKeyguardExitAnimation = null; 2249 } 2250 } 2251 2252 final WindowState winShowWhenLocked = (WindowState) policy.getWinShowWhenLockedLw(); 2253 if (winShowWhenLocked != null) { 2254 animator.mLastShowWinWhenLocked = winShowWhenLocked; 2255 } 2256 } 2257 2258 void updateWallpaperForAnimator(WindowAnimator animator) { 2259 resetAnimationBackgroundAnimator(); 2260 2261 final WindowList windows = mWindows; 2262 WindowState detachedWallpaper = null; 2263 2264 for (int i = windows.size() - 1; i >= 0; i--) { 2265 final WindowState win = windows.get(i); 2266 final WindowStateAnimator winAnimator = win.mWinAnimator; 2267 if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) { 2268 continue; 2269 } 2270 2271 final int flags = win.mAttrs.flags; 2272 2273 // If this window is animating, make a note that we have an animating window and take 2274 // care of a request to run a detached wallpaper animation. 2275 if (winAnimator.mAnimating) { 2276 if (winAnimator.mAnimation != null) { 2277 if ((flags & FLAG_SHOW_WALLPAPER) != 0 2278 && winAnimator.mAnimation.getDetachWallpaper()) { 2279 detachedWallpaper = win; 2280 } 2281 final int color = winAnimator.mAnimation.getBackgroundColor(); 2282 if (color != 0) { 2283 final TaskStack stack = win.getStack(); 2284 if (stack != null) { 2285 stack.setAnimationBackground(winAnimator, color); 2286 } 2287 } 2288 } 2289 animator.setAnimating(true); 2290 } 2291 2292 // If this window's app token is running a detached wallpaper animation, make a note so 2293 // we can ensure the wallpaper is displayed behind it. 2294 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator; 2295 if (appAnimator != null && appAnimator.animation != null 2296 && appAnimator.animating) { 2297 if ((flags & FLAG_SHOW_WALLPAPER) != 0 2298 && appAnimator.animation.getDetachWallpaper()) { 2299 detachedWallpaper = win; 2300 } 2301 2302 final int color = appAnimator.animation.getBackgroundColor(); 2303 if (color != 0) { 2304 final TaskStack stack = win.getStack(); 2305 if (stack != null) { 2306 stack.setAnimationBackground(winAnimator, color); 2307 } 2308 } 2309 } 2310 } // end forall windows 2311 2312 if (animator.mWindowDetachedWallpaper != detachedWallpaper) { 2313 if (DEBUG_WALLPAPER) Slog.v(TAG, "Detached wallpaper changed from " 2314 + animator.mWindowDetachedWallpaper + " to " + detachedWallpaper); 2315 animator.mWindowDetachedWallpaper = detachedWallpaper; 2316 animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 2317 } 2318 } 2319 2320 void prepareWindowSurfaces() { 2321 final int count = mWindows.size(); 2322 for (int j = 0; j < count; j++) { 2323 mWindows.get(j).mWinAnimator.prepareSurfaceLocked(true); 2324 } 2325 } 2326 2327 boolean inputMethodClientHasFocus(IInputMethodClient client) { 2328 // The focus for the client is the window immediately below where we would place the input 2329 // method window. 2330 int idx = findDesiredInputMethodWindowIndex(false); 2331 if (idx <= 0) { 2332 return false; 2333 } 2334 2335 WindowState imFocus = mWindows.get(idx - 1); 2336 if (DEBUG_INPUT_METHOD) { 2337 Slog.i(TAG_WM, "Desired input method target: " + imFocus); 2338 Slog.i(TAG_WM, "Current focus: " + mService.mCurrentFocus); 2339 Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus); 2340 } 2341 2342 if (imFocus == null) { 2343 return false; 2344 } 2345 2346 // This may be a starting window, in which case we still want to count it as okay. 2347 if (imFocus.mAttrs.type == TYPE_APPLICATION_STARTING && imFocus.mAppToken != null) { 2348 // The client has definitely started, so it really should have a window in this app 2349 // token. Let's look for it. 2350 final WindowState w = imFocus.mAppToken.getFirstNonStartingWindow(); 2351 if (w != null) { 2352 if (DEBUG_INPUT_METHOD) Slog.i(TAG_WM, "Switching to real app window: " + w); 2353 imFocus = w; 2354 } 2355 } 2356 2357 final IInputMethodClient imeClient = imFocus.mSession.mClient; 2358 2359 if (DEBUG_INPUT_METHOD) { 2360 Slog.i(TAG_WM, "IM target client: " + imeClient); 2361 if (imeClient != null) { 2362 Slog.i(TAG_WM, "IM target client binder: " + imeClient.asBinder()); 2363 Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder()); 2364 } 2365 } 2366 2367 return imeClient != null && imeClient.asBinder() == client.asBinder(); 2368 } 2369 2370 boolean hasSecureWindowOnScreen() { 2371 for (int i = mWindows.size() - 1; i >= 0; --i) { 2372 final WindowState ws = mWindows.get(i); 2373 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) { 2374 return true; 2375 } 2376 } 2377 return false; 2378 } 2379 2380 void updateSystemUiVisibility(int visibility, int globalDiff) { 2381 for (int i = mWindows.size() - 1; i >= 0; --i) { 2382 final WindowState ws = mWindows.get(i); 2383 try { 2384 int curValue = ws.mSystemUiVisibility; 2385 int diff = (curValue ^ visibility) & globalDiff; 2386 int newValue = (curValue & ~diff) | (visibility & diff); 2387 if (newValue != curValue) { 2388 ws.mSeq++; 2389 ws.mSystemUiVisibility = newValue; 2390 } 2391 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 2392 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 2393 visibility, newValue, diff); 2394 } 2395 } catch (RemoteException e) { 2396 // so sorry 2397 } 2398 } 2399 } 2400 2401 void onWindowFreezeTimeout() { 2402 Slog.w(TAG_WM, "Window freeze timeout expired."); 2403 mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT; 2404 for (int i = mWindows.size() - 1; i >= 0; --i) { 2405 final WindowState w = mWindows.get(i); 2406 if (!w.mOrientationChanging) { 2407 continue; 2408 } 2409 w.mOrientationChanging = false; 2410 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 2411 - mService.mDisplayFreezeTime); 2412 Slog.w(TAG_WM, "Force clearing orientation change: " + w); 2413 } 2414 mService.mWindowPlacerLocked.performSurfacePlacement(); 2415 } 2416 2417 void waitForAllWindowsDrawn() { 2418 final WindowManagerPolicy policy = mService.mPolicy; 2419 for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) { 2420 final WindowState win = mWindows.get(winNdx); 2421 final boolean isForceHiding = policy.isForceHiding(win.mAttrs); 2422 final boolean keyguard = policy.isKeyguardHostWindow(win.mAttrs); 2423 if (win.isVisibleLw() && (win.mAppToken != null || isForceHiding || keyguard)) { 2424 win.mWinAnimator.mDrawState = DRAW_PENDING; 2425 // Force add to mResizingWindows. 2426 win.mLastContentInsets.set(-1, -1, -1, -1); 2427 mService.mWaitingForDrawn.add(win); 2428 2429 // No need to wait for the windows below Keyguard. 2430 if (isForceHiding) { 2431 return; 2432 } 2433 } 2434 } 2435 } 2436 2437 static final class GetWindowOnDisplaySearchResult { 2438 boolean reachedToken; 2439 WindowState foundWindow; 2440 2441 void reset() { 2442 reachedToken = false; 2443 foundWindow = null; 2444 } 2445 } 2446 2447 static final class TaskForResizePointSearchResult { 2448 boolean searchDone; 2449 Task taskForResize; 2450 2451 void reset() { 2452 searchDone = false; 2453 taskForResize = null; 2454 } 2455 } 2456 2457 /** 2458 * Base class for any direct child window container of {@link #DisplayContent} need to inherit 2459 * from. This is mainly a pass through class that allows {@link #DisplayContent} to have 2460 * homogeneous children type which is currently required by sub-classes of 2461 * {@link WindowContainer} class. 2462 */ 2463 static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> { 2464 2465 int size() { 2466 return mChildren.size(); 2467 } 2468 2469 E get(int index) { 2470 return mChildren.get(index); 2471 } 2472 2473 @Override 2474 boolean fillsParent() { 2475 return true; 2476 } 2477 2478 @Override 2479 boolean isVisible() { 2480 return true; 2481 } 2482 } 2483 2484 /** 2485 * Window container class that contains all containers on this display relating to Apps. 2486 * I.e Activities. 2487 */ 2488 private class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> { 2489 2490 void attachStack(TaskStack stack, boolean onTop) { 2491 if (stack.mStackId == HOME_STACK_ID) { 2492 if (mHomeStack != null) { 2493 throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first."); 2494 } 2495 mHomeStack = stack; 2496 } 2497 addChild(stack, onTop); 2498 stack.onDisplayChanged(DisplayContent.this); 2499 } 2500 2501 void moveStack(TaskStack stack, boolean toTop) { 2502 if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) { 2503 // This stack is always-on-top silly... 2504 Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + stack + " to bottom"); 2505 return; 2506 } 2507 2508 if (!mChildren.contains(stack)) { 2509 Slog.wtf(TAG_WM, "moving stack that was not added: " + stack, new Throwable()); 2510 } 2511 removeChild(stack); 2512 addChild(stack, toTop); 2513 } 2514 2515 private void addChild(TaskStack stack, boolean toTop) { 2516 int addIndex = toTop ? mChildren.size() : 0; 2517 2518 if (toTop 2519 && mService.isStackVisibleLocked(PINNED_STACK_ID) 2520 && stack.mStackId != PINNED_STACK_ID) { 2521 // The pinned stack is always the top most stack (always-on-top) when it is visible. 2522 // So, stack is moved just below the pinned stack. 2523 addIndex--; 2524 TaskStack topStack = mChildren.get(addIndex); 2525 if (topStack.mStackId != PINNED_STACK_ID) { 2526 throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren); 2527 } 2528 } 2529 addChild(stack, addIndex); 2530 setLayoutNeeded(); 2531 } 2532 2533 @Override 2534 int getOrientation() { 2535 if (mService.isStackVisibleLocked(DOCKED_STACK_ID) 2536 || mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) { 2537 // Apps and their containers are not allowed to specify an orientation while the 2538 // docked or freeform stack is visible...except for the home stack/task if the 2539 // docked stack is minimized and it actually set something. 2540 if (mHomeStack != null && mHomeStack.isVisible() 2541 && mDividerControllerLocked.isMinimizedDock()) { 2542 final int orientation = mHomeStack.getOrientation(); 2543 if (orientation != SCREEN_ORIENTATION_UNSET) { 2544 return orientation; 2545 } 2546 } 2547 return SCREEN_ORIENTATION_UNSPECIFIED; 2548 } 2549 2550 final int orientation = super.getOrientation(); 2551 if (orientation != SCREEN_ORIENTATION_UNSET 2552 && orientation != SCREEN_ORIENTATION_BEHIND) { 2553 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 2554 "App is requesting an orientation, return " + orientation); 2555 return orientation; 2556 } 2557 2558 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 2559 "No app is requesting an orientation, return " + mService.mLastOrientation); 2560 // The next app has not been requested to be visible, so we keep the current orientation 2561 // to prevent freezing/unfreezing the display too early. 2562 return mService.mLastOrientation; 2563 } 2564 } 2565 2566 /** 2567 * Window container class that contains all containers on this display that are not related to 2568 * Apps. E.g. status bar. 2569 */ 2570 private static class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> { 2571 2572 } 2573} 2574