DisplayContent.java revision cb291f38f8aa1517ca66c7331765becb47442edd
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.View.GONE; 33import static android.view.WindowManager.DOCKED_BOTTOM; 34import static android.view.WindowManager.DOCKED_INVALID; 35import static android.view.WindowManager.DOCKED_TOP; 36import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION; 37import static android.view.WindowManager.INPUT_CONSUMER_PIP; 38import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER; 39import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 40import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 41import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 42import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 43import static android.view.WindowManager.LayoutParams.FLAG_SECURE; 44import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 45import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE; 46import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET; 47import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS; 48import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 49import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 50import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 51import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 52import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; 53import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; 54import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION; 55import static android.view.WindowManager.LayoutParams.TYPE_DREAM; 56import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 57import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 58import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; 59import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; 60import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; 61import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 62import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 63import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 64import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; 65import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 66import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT; 69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; 70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS; 71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; 72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; 73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS; 74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; 75import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; 76import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; 77import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT; 78import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON; 79import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; 80import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 81import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER; 82import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; 83import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT; 84import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS; 85import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; 86import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 87import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 88import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION; 89import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER; 90import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT; 91import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD; 92import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER; 93import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET; 94import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; 95import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT; 96import static com.android.server.wm.WindowManagerService.dipToPixel; 97import static com.android.server.wm.WindowManagerService.localLOGV; 98import static com.android.server.wm.WindowManagerService.logSurface; 99import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; 100import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; 101import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW; 102import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE; 103 104import android.annotation.NonNull; 105import android.app.ActivityManager.StackId; 106import android.content.res.Configuration; 107import android.graphics.Bitmap; 108import android.graphics.Matrix; 109import android.graphics.Rect; 110import android.graphics.RectF; 111import android.graphics.Region; 112import android.graphics.Region.Op; 113import android.hardware.display.DisplayManagerInternal; 114import android.os.Debug; 115import android.os.Handler; 116import android.os.IBinder; 117import android.os.RemoteException; 118import android.os.SystemClock; 119import android.util.DisplayMetrics; 120import android.util.Slog; 121import android.view.Display; 122import android.view.DisplayInfo; 123import android.view.IWindow; 124import android.view.InputChannel; 125import android.view.Surface; 126import android.view.SurfaceControl; 127import android.view.WindowManagerPolicy; 128 129import com.android.internal.util.FastPrintWriter; 130import com.android.internal.view.IInputMethodClient; 131import com.android.server.input.InputWindowHandle; 132 133import java.io.FileDescriptor; 134import java.io.PrintWriter; 135import java.io.StringWriter; 136import java.util.ArrayList; 137import java.util.Arrays; 138import java.util.Comparator; 139import java.util.HashMap; 140import java.util.Iterator; 141import java.util.LinkedList; 142import java.util.List; 143 144/** 145 * Utility class for keeping track of the WindowStates and other pertinent contents of a 146 * particular Display. 147 * 148 * IMPORTANT: No method from this class should ever be used without holding 149 * WindowManagerService.mWindowMap. 150 */ 151class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> { 152 private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM; 153 154 /** Unique identifier of this stack. */ 155 private final int mDisplayId; 156 157 /** The containers below are the only child containers the display can have. */ 158 // Contains all window containers that are related to apps (Activities) 159 private final TaskStackContainers mTaskStackContainers = new TaskStackContainers(); 160 // Contains all non-app window containers that should be displayed above the app containers 161 // (e.g. Status bar) 162 private final NonAppWindowContainers mAboveAppWindowsContainers = 163 new NonAppWindowContainers("mAboveAppWindowsContainers"); 164 // Contains all non-app window containers that should be displayed below the app containers 165 // (e.g. Wallpaper). 166 private final NonAppWindowContainers mBelowAppWindowsContainers = 167 new NonAppWindowContainers("mBelowAppWindowsContainers"); 168 // Contains all IME window containers. Note that the z-ordering of the IME windows will depend 169 // on the IME target. We mainly have this container grouping so we can keep track of all the IME 170 // window containers together and move them in-sync if/when needed. 171 private final NonAppWindowContainers mImeWindowsContainers = 172 new NonAppWindowContainers("mImeWindowsContainers"); 173 174 // Z-ordered (bottom-most first) list of all Window objects. 175 private final WindowList mWindows = new WindowList(); 176 177 // Mapping from a token IBinder to a WindowToken object on this display. 178 private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap(); 179 180 int mInitialDisplayWidth = 0; 181 int mInitialDisplayHeight = 0; 182 int mInitialDisplayDensity = 0; 183 int mBaseDisplayWidth = 0; 184 int mBaseDisplayHeight = 0; 185 int mBaseDisplayDensity = 0; 186 boolean mDisplayScalingDisabled; 187 private final DisplayInfo mDisplayInfo = new DisplayInfo(); 188 private final Display mDisplay; 189 private final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 190 191 Rect mBaseDisplayRect = new Rect(); 192 private Rect mContentRect = new Rect(); 193 194 // Accessed directly by all users. 195 private boolean mLayoutNeeded; 196 int pendingLayoutChanges; 197 // TODO(multi-display): remove some of the usages. 198 final boolean isDefaultDisplay; 199 200 /** Window tokens that are in the process of exiting, but still on screen for animations. */ 201 final ArrayList<WindowToken> mExitingTokens = new ArrayList<>(); 202 203 /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack 204 * (except a future lockscreen TaskStack) moves to the top. */ 205 private TaskStack mHomeStack = null; 206 207 /** Detect user tapping outside of current focused task bounds .*/ 208 TaskTapPointerEventListener mTapDetector; 209 210 /** Detect user tapping outside of current focused stack bounds .*/ 211 private Region mTouchExcludeRegion = new Region(); 212 213 /** Save allocating when calculating rects */ 214 private final Rect mTmpRect = new Rect(); 215 private final Rect mTmpRect2 = new Rect(); 216 private final RectF mTmpRectF = new RectF(); 217 private final Matrix mTmpMatrix = new Matrix(); 218 private final Region mTmpRegion = new Region(); 219 220 final WindowManagerService mService; 221 222 /** Remove this display when animation on it has completed. */ 223 private boolean mDeferredRemoval; 224 225 final DockedStackDividerController mDividerControllerLocked; 226 final PinnedStackController mPinnedStackControllerLocked; 227 228 final DimLayerController mDimLayerController; 229 230 final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>(); 231 232 /** Used when rebuilding window list to keep track of windows that have been removed. */ 233 private WindowState[] mRebuildTmp = new WindowState[20]; 234 235 /** 236 * Temporary list for comparison. Always clear this after use so we don't end up with 237 * orphaned windows references 238 */ 239 private final ArrayList<WindowState> mTmpWindows = new ArrayList<>(); 240 241 private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList(); 242 243 private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult = 244 new TaskForResizePointSearchResult(); 245 private final GetWindowOnDisplaySearchResult mTmpGetWindowOnDisplaySearchResult = 246 new GetWindowOnDisplaySearchResult(); 247 248 // True if this display is in the process of being removed. Used to determine if the removal of 249 // the display's direct children should be allowed. 250 private boolean mRemovingDisplay = false; 251 252 private final WindowLayersController mLayersController; 253 final WallpaperController mWallpaperController; 254 int mInputMethodAnimLayerAdjustment; 255 256 /** 257 * @param display May not be null. 258 * @param service You know. 259 * @param layersController window layer controller used to assign layer to the windows on this 260 * display. 261 * @param wallpaperController wallpaper windows controller used to adjust the positioning of the 262 * wallpaper windows in the window list. 263 */ 264 DisplayContent(Display display, WindowManagerService service, 265 WindowLayersController layersController, WallpaperController wallpaperController) { 266 mDisplay = display; 267 mDisplayId = display.getDisplayId(); 268 mLayersController = layersController; 269 mWallpaperController = wallpaperController; 270 display.getDisplayInfo(mDisplayInfo); 271 display.getMetrics(mDisplayMetrics); 272 isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY; 273 mService = service; 274 initializeDisplayBaseInfo(); 275 mDividerControllerLocked = new DockedStackDividerController(service, this); 276 mPinnedStackControllerLocked = new PinnedStackController(service, this); 277 mDimLayerController = new DimLayerController(this); 278 279 // These are the only direct children we should ever have and they are permanent. 280 super.addChild(mBelowAppWindowsContainers, null); 281 super.addChild(mTaskStackContainers, null); 282 super.addChild(mAboveAppWindowsContainers, null); 283 super.addChild(mImeWindowsContainers, null); 284 } 285 286 int getDisplayId() { 287 return mDisplayId; 288 } 289 290 WindowToken getWindowToken(IBinder binder) { 291 return mTokenMap.get(binder); 292 } 293 294 AppWindowToken getAppWindowToken(IBinder binder) { 295 final WindowToken token = getWindowToken(binder); 296 if (token == null) { 297 return null; 298 } 299 return token.asAppWindowToken(); 300 } 301 302 void setWindowToken(IBinder binder, WindowToken token) { 303 final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token); 304 if (dc != null) { 305 // We currently don't support adding a window token to the display if the display 306 // already has the binder mapped to another token. If there is a use case for supporting 307 // this moving forward we will either need to merge the WindowTokens some how or have 308 // the binder map to a list of window tokens. 309 throw new IllegalArgumentException("Can't map token=" + token + " to display=" + this 310 + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap); 311 } 312 mTokenMap.put(binder, token); 313 314 if (token.asAppWindowToken() == null) { 315 // Add non-app token to container hierarchy on the display. App tokens are added through 316 // the parent container managing them (e.g. Tasks). 317 switch (token.windowType) { 318 case TYPE_WALLPAPER: 319 mBelowAppWindowsContainers.addChild(token); 320 break; 321 case TYPE_INPUT_METHOD: 322 case TYPE_INPUT_METHOD_DIALOG: 323 mImeWindowsContainers.addChild(token); 324 break; 325 default: 326 mAboveAppWindowsContainers.addChild(token); 327 break; 328 } 329 } 330 } 331 332 WindowToken removeWindowToken(IBinder binder) { 333 final WindowToken token = mTokenMap.remove(binder); 334 if (token != null && token.asAppWindowToken() == null) { 335 switch (token.windowType) { 336 case TYPE_WALLPAPER: 337 mBelowAppWindowsContainers.removeChild(token); 338 break; 339 case TYPE_INPUT_METHOD: 340 case TYPE_INPUT_METHOD_DIALOG: 341 mImeWindowsContainers.removeChild(token); 342 break; 343 default: 344 mAboveAppWindowsContainers.removeChild(token); 345 break; 346 } 347 } 348 return token; 349 } 350 351 void removeAppToken(IBinder binder) { 352 final WindowToken token = removeWindowToken(binder); 353 if (token == null) { 354 Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder); 355 return; 356 } 357 358 final AppWindowToken appToken = token.asAppWindowToken(); 359 360 if (appToken == null) { 361 Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token); 362 return; 363 } 364 365 appToken.onRemovedFromDisplay(); 366 } 367 368 Display getDisplay() { 369 return mDisplay; 370 } 371 372 DisplayInfo getDisplayInfo() { 373 return mDisplayInfo; 374 } 375 376 DisplayMetrics getDisplayMetrics() { 377 return mDisplayMetrics; 378 } 379 380 DockedStackDividerController getDockedDividerController() { 381 return mDividerControllerLocked; 382 } 383 384 PinnedStackController getPinnedStackController() { 385 return mPinnedStackControllerLocked; 386 } 387 388 /** 389 * Returns true if the specified UID has access to this display. 390 */ 391 boolean hasAccess(int uid) { 392 return mDisplay.hasAccess(uid); 393 } 394 395 boolean isPrivate() { 396 return (mDisplay.getFlags() & FLAG_PRIVATE) != 0; 397 } 398 399 TaskStack getHomeStack() { 400 if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) { 401 Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this); 402 } 403 return mHomeStack; 404 } 405 406 TaskStack getStackById(int stackId) { 407 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 408 final TaskStack stack = mTaskStackContainers.get(i); 409 if (stack.mStackId == stackId) { 410 return stack; 411 } 412 } 413 return null; 414 } 415 416 @Override 417 void onConfigurationChanged(Configuration newParentConfig) { 418 super.onConfigurationChanged(newParentConfig); 419 420 // The display size information is heavily dependent on the resources in the current 421 // configuration, so we need to reconfigure it every time the configuration changes. 422 // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh... 423 mService.reconfigureDisplayLocked(this); 424 425 getDockedDividerController().onConfigurationChanged(); 426 getPinnedStackController().onConfigurationChanged(); 427 } 428 429 /** 430 * Callback used to trigger bounds update after configuration change and get ids of stacks whose 431 * bounds were updated. 432 */ 433 void updateStackBoundsAfterConfigChange(@NonNull List<Integer> changedStackList) { 434 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 435 final TaskStack stack = mTaskStackContainers.get(i); 436 if (stack.updateBoundsAfterConfigChange()) { 437 changedStackList.add(stack.mStackId); 438 } 439 } 440 } 441 442 @Override 443 boolean fillsParent() { 444 return true; 445 } 446 447 @Override 448 boolean isVisible() { 449 return true; 450 } 451 452 @Override 453 void onAppTransitionDone() { 454 super.onAppTransitionDone(); 455 rebuildAppWindowList(); 456 } 457 458 @Override 459 int getOrientation() { 460 final WindowManagerPolicy policy = mService.mPolicy; 461 462 // TODO: All the logic before the last return statement in this method should really go in 463 // #NonAppWindowContainer.getOrientation() since it is trying to decide orientation based 464 // on non-app windows. But, we can not do that until the window list is always correct in 465 // terms of z-ordering based on layers. 466 if (mService.mDisplayFrozen) { 467 if (mService.mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) { 468 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 469 "Display is frozen, return " + mService.mLastWindowForcedOrientation); 470 // If the display is frozen, some activities may be in the middle of restarting, and 471 // thus have removed their old window. If the window has the flag to hide the lock 472 // screen, then the lock screen can re-appear and inflict its own orientation on us. 473 // Keep the orientation stable until this all settles down. 474 return mService.mLastWindowForcedOrientation; 475 } else if (policy.isKeyguardLocked()) { 476 // Use the last orientation the while the display is frozen with the keyguard 477 // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED 478 // window. We don't want to check the show when locked window directly though as 479 // things aren't stable while the display is frozen, for example the window could be 480 // momentarily unavailable due to activity relaunch. 481 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, " 482 + "return " + mService.mLastOrientation); 483 return mService.mLastOrientation; 484 } 485 } else { 486 for (int pos = mWindows.size() - 1; pos >= 0; --pos) { 487 final WindowState win = mWindows.get(pos); 488 if (win.mAppToken != null) { 489 // We hit an application window. so the orientation will be determined by the 490 // app window. No point in continuing further. 491 break; 492 } 493 if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) { 494 continue; 495 } 496 int req = win.mAttrs.screenOrientation; 497 if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND) { 498 continue; 499 } 500 501 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req); 502 if (policy.isKeyguardHostWindow(win.mAttrs)) { 503 mService.mLastKeyguardForcedOrientation = req; 504 } 505 return (mService.mLastWindowForcedOrientation = req); 506 } 507 mService.mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 508 509 if (policy.isKeyguardShowingAndNotOccluded()) { 510 return mService.mLastKeyguardForcedOrientation; 511 } 512 } 513 514 // Top system windows are not requesting an orientation. Start searching from apps. 515 return mTaskStackContainers.getOrientation(); 516 } 517 518 void updateDisplayInfo() { 519 mDisplay.getDisplayInfo(mDisplayInfo); 520 mDisplay.getMetrics(mDisplayMetrics); 521 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 522 mTaskStackContainers.get(i).updateDisplayInfo(null); 523 } 524 } 525 526 void initializeDisplayBaseInfo() { 527 final DisplayManagerInternal displayManagerInternal = mService.mDisplayManagerInternal; 528 if (displayManagerInternal != null) { 529 // Bootstrap the default logical display from the display manager. 530 final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId); 531 if (newDisplayInfo != null) { 532 mDisplayInfo.copyFrom(newDisplayInfo); 533 } 534 } 535 536 mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth; 537 mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight; 538 mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi; 539 mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight); 540 } 541 542 void getLogicalDisplayRect(Rect out) { 543 // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked. 544 final int orientation = mDisplayInfo.rotation; 545 boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270); 546 final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; 547 final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; 548 int width = mDisplayInfo.logicalWidth; 549 int left = (physWidth - width) / 2; 550 int height = mDisplayInfo.logicalHeight; 551 int top = (physHeight - height) / 2; 552 out.set(left, top, left + width, top + height); 553 } 554 555 private void getLogicalDisplayRect(Rect out, int orientation) { 556 getLogicalDisplayRect(out); 557 558 // Rotate the Rect if needed. 559 final int currentRotation = mDisplayInfo.rotation; 560 final int rotationDelta = deltaRotation(currentRotation, orientation); 561 if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) { 562 createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix); 563 mTmpRectF.set(out); 564 mTmpMatrix.mapRect(mTmpRectF); 565 mTmpRectF.round(out); 566 } 567 } 568 569 void getContentRect(Rect out) { 570 out.set(mContentRect); 571 } 572 573 /** 574 * Adds the stack to this display. 575 * @see WindowManagerService#addStackToDisplay(int, int, boolean) 576 */ 577 Rect addStackToDisplay(int stackId, boolean onTop) { 578 boolean attachedToDisplay = false; 579 TaskStack stack = mService.mStackIdToStack.get(stackId); 580 if (stack == null) { 581 if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId=" 582 + mDisplayId); 583 584 stack = getStackById(stackId); 585 if (stack != null) { 586 // It's already attached to the display...clear mDeferRemoval and move stack to 587 // appropriate z-order on display as needed. 588 stack.mDeferRemoval = false; 589 moveStack(stack, onTop); 590 attachedToDisplay = true; 591 } else { 592 stack = new TaskStack(mService, stackId); 593 } 594 595 mService.mStackIdToStack.put(stackId, stack); 596 if (stackId == DOCKED_STACK_ID) { 597 mDividerControllerLocked.notifyDockedStackExistsChanged(true); 598 } 599 } else { 600 final DisplayContent currentDC = stack.getDisplayContent(); 601 if (currentDC != null) { 602 throw new IllegalStateException("Trying to add stackId=" + stackId 603 + "to displayId=" + mDisplayId + ", but it's already attached to displayId=" 604 + currentDC.getDisplayId()); 605 } 606 } 607 608 if (!attachedToDisplay) { 609 mTaskStackContainers.addStackToDisplay(stack, onTop); 610 } 611 612 if (stack.getRawFullscreen()) { 613 return null; 614 } 615 final Rect bounds = new Rect(); 616 stack.getRawBounds(bounds); 617 return bounds; 618 } 619 620 /** Removes the stack from the display and prepares for changing the parent. */ 621 private void removeStackFromDisplay(TaskStack stack) { 622 mTaskStackContainers.removeStackFromDisplay(stack); 623 } 624 625 /** Moves the stack to this display and returns the updated bounds. */ 626 Rect moveStackToDisplay(TaskStack stack) { 627 final DisplayContent currentDisplayContent = stack.getDisplayContent(); 628 if (currentDisplayContent == null) { 629 throw new IllegalStateException("Trying to move stackId=" + stack.mStackId 630 + " which is not currently attached to any display"); 631 } 632 if (stack.getDisplayContent().getDisplayId() == mDisplayId) { 633 throw new IllegalArgumentException("Trying to move stackId=" + stack.mStackId 634 + " to its current displayId=" + mDisplayId); 635 } 636 637 currentDisplayContent.removeStackFromDisplay(stack); 638 return addStackToDisplay(stack.mStackId, true /* onTop */); 639 } 640 641 void moveStack(TaskStack stack, boolean toTop) { 642 mTaskStackContainers.moveStack(stack, toTop); 643 } 644 645 @Override 646 protected void addChild(DisplayChildWindowContainer child, 647 Comparator<DisplayChildWindowContainer> comparator) { 648 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 649 } 650 651 @Override 652 protected void addChild(DisplayChildWindowContainer child, int index) { 653 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 654 } 655 656 @Override 657 protected void removeChild(DisplayChildWindowContainer child) { 658 // Only allow removal of direct children from this display if the display is in the process 659 // of been removed. 660 if (mRemovingDisplay) { 661 super.removeChild(child); 662 return; 663 } 664 throw new UnsupportedOperationException("See DisplayChildWindowContainer"); 665 } 666 667 int taskIdFromPoint(int x, int y) { 668 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 669 final TaskStack stack = mTaskStackContainers.get(stackNdx); 670 final int taskId = stack.taskIdFromPoint(x, y); 671 if (taskId != -1) { 672 return taskId; 673 } 674 } 675 return -1; 676 } 677 678 /** 679 * Find the task whose outside touch area (for resizing) (x, y) falls within. 680 * Returns null if the touch doesn't fall into a resizing area. 681 */ 682 Task findTaskForResizePoint(int x, int y) { 683 final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics); 684 mTmpTaskForResizePointSearchResult.reset(); 685 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 686 final TaskStack stack = mTaskStackContainers.get(stackNdx); 687 if (!StackId.isTaskResizeAllowed(stack.mStackId)) { 688 return null; 689 } 690 691 stack.findTaskForResizePoint(x, y, delta, mTmpTaskForResizePointSearchResult); 692 if (mTmpTaskForResizePointSearchResult.searchDone) { 693 return mTmpTaskForResizePointSearchResult.taskForResize; 694 } 695 } 696 return null; 697 } 698 699 void setTouchExcludeRegion(Task focusedTask) { 700 mTouchExcludeRegion.set(mBaseDisplayRect); 701 final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics); 702 mTmpRect2.setEmpty(); 703 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 704 final TaskStack stack = mTaskStackContainers.get(stackNdx); 705 stack.setTouchExcludeRegion( 706 focusedTask, delta, mTouchExcludeRegion, mContentRect, mTmpRect2); 707 } 708 // If we removed the focused task above, add it back and only leave its 709 // outside touch area in the exclusion. TapDectector is not interested in 710 // any touch inside the focused task itself. 711 if (!mTmpRect2.isEmpty()) { 712 mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION); 713 } 714 final WindowState inputMethod = mService.mInputMethodWindow; 715 if (inputMethod != null && inputMethod.isVisibleLw()) { 716 // If the input method is visible and the user is typing, we don't want these touch 717 // events to be intercepted and used to change focus. This would likely cause a 718 // disappearance of the input method. 719 inputMethod.getTouchableRegion(mTmpRegion); 720 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION); 721 } 722 for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) { 723 WindowState win = mTapExcludedWindows.get(i); 724 win.getTouchableRegion(mTmpRegion); 725 mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION); 726 } 727 if (getDockedStackLocked() != null) { 728 mDividerControllerLocked.getTouchRegion(mTmpRect); 729 mTmpRegion.set(mTmpRect); 730 mTouchExcludeRegion.op(mTmpRegion, Op.UNION); 731 } 732 if (mTapDetector != null) { 733 mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion); 734 } 735 } 736 737 void switchUser() { 738 final int count = mWindows.size(); 739 for (int i = 0; i < count; i++) { 740 final WindowState win = mWindows.get(i); 741 if (win.isHiddenFromUserLocked()) { 742 if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + win 743 + ", attrs=" + win.mAttrs.type + ", belonging to " + win.mOwnerUid); 744 win.hideLw(false); 745 } 746 } 747 748 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 749 mTaskStackContainers.get(stackNdx).switchUser(); 750 } 751 752 rebuildAppWindowList(); 753 } 754 755 private void resetAnimationBackgroundAnimator() { 756 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 757 mTaskStackContainers.get(stackNdx).resetAnimationBackgroundAnimator(); 758 } 759 } 760 761 boolean animateDimLayers() { 762 return mDimLayerController.animateDimLayers(); 763 } 764 765 private void resetDimming() { 766 mDimLayerController.resetDimming(); 767 } 768 769 boolean isDimming() { 770 return mDimLayerController.isDimming(); 771 } 772 773 private void stopDimmingIfNeeded() { 774 mDimLayerController.stopDimmingIfNeeded(); 775 } 776 777 @Override 778 void removeIfPossible() { 779 if (isAnimating()) { 780 mDeferredRemoval = true; 781 return; 782 } 783 removeImmediately(); 784 } 785 786 @Override 787 void removeImmediately() { 788 mRemovingDisplay = true; 789 try { 790 super.removeImmediately(); 791 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this); 792 mDimLayerController.close(); 793 if (mDisplayId == DEFAULT_DISPLAY) { 794 mService.unregisterPointerEventListener(mTapDetector); 795 mService.unregisterPointerEventListener(mService.mMousePositionTracker); 796 } 797 } finally { 798 mRemovingDisplay = false; 799 } 800 } 801 802 /** Returns true if a removal action is still being deferred. */ 803 @Override 804 boolean checkCompleteDeferredRemoval() { 805 final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval(); 806 807 if (!stillDeferringRemoval && mDeferredRemoval) { 808 removeImmediately(); 809 mService.onDisplayRemoved(mDisplayId); 810 return false; 811 } 812 return true; 813 } 814 815 boolean animateForIme(float interpolatedValue, float animationTarget, 816 float dividerAnimationTarget) { 817 boolean updated = false; 818 819 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 820 final TaskStack stack = mTaskStackContainers.get(i); 821 if (stack == null || !stack.isAdjustedForIme()) { 822 continue; 823 } 824 825 if (interpolatedValue >= 1f && animationTarget == 0f && dividerAnimationTarget == 0f) { 826 stack.resetAdjustedForIme(true /* adjustBoundsNow */); 827 updated = true; 828 } else { 829 mDividerControllerLocked.mLastAnimationProgress = 830 mDividerControllerLocked.getInterpolatedAnimationValue(interpolatedValue); 831 mDividerControllerLocked.mLastDividerProgress = 832 mDividerControllerLocked.getInterpolatedDividerValue(interpolatedValue); 833 updated |= stack.updateAdjustForIme( 834 mDividerControllerLocked.mLastAnimationProgress, 835 mDividerControllerLocked.mLastDividerProgress, 836 false /* force */); 837 } 838 if (interpolatedValue >= 1f) { 839 stack.endImeAdjustAnimation(); 840 } 841 } 842 843 return updated; 844 } 845 846 boolean clearImeAdjustAnimation() { 847 boolean changed = false; 848 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 849 final TaskStack stack = mTaskStackContainers.get(i); 850 if (stack != null && stack.isAdjustedForIme()) { 851 stack.resetAdjustedForIme(true /* adjustBoundsNow */); 852 changed = true; 853 } 854 } 855 return changed; 856 } 857 858 void beginImeAdjustAnimation() { 859 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 860 final TaskStack stack = mTaskStackContainers.get(i); 861 if (stack.isVisible() && stack.isAdjustedForIme()) { 862 stack.beginImeAdjustAnimation(); 863 } 864 } 865 } 866 867 void adjustForImeIfNeeded() { 868 final WindowState imeWin = mService.mInputMethodWindow; 869 final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw() 870 && !mDividerControllerLocked.isImeHideRequested(); 871 final boolean dockVisible = mService.isStackVisibleLocked(DOCKED_STACK_ID); 872 final TaskStack imeTargetStack = mService.getImeFocusStackLocked(); 873 final int imeDockSide = (dockVisible && imeTargetStack != null) ? 874 imeTargetStack.getDockSide() : DOCKED_INVALID; 875 final boolean imeOnTop = (imeDockSide == DOCKED_TOP); 876 final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM); 877 final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock(); 878 final int imeHeight = mService.mPolicy.getInputMethodWindowVisibleHeightLw(); 879 final boolean imeHeightChanged = imeVisible && 880 imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor(); 881 882 // The divider could be adjusted for IME position, or be thinner than usual, 883 // or both. There are three possible cases: 884 // - If IME is visible, and focus is on top, divider is not moved for IME but thinner. 885 // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner. 886 // - If IME is not visible, divider is not moved and is normal width. 887 888 if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) { 889 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 890 final TaskStack stack = mTaskStackContainers.get(i); 891 final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM; 892 if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)) { 893 stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged); 894 } else { 895 stack.resetAdjustedForIme(false); 896 } 897 } 898 mDividerControllerLocked.setAdjustedForIme( 899 imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight); 900 } else { 901 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 902 final TaskStack stack = mTaskStackContainers.get(i); 903 stack.resetAdjustedForIme(!dockVisible); 904 } 905 mDividerControllerLocked.setAdjustedForIme( 906 false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight); 907 } 908 mPinnedStackControllerLocked.setAdjustedForIme(imeVisible, imeHeight); 909 } 910 911 void setInputMethodAnimLayerAdjustment(int adj) { 912 if (DEBUG_LAYERS) Slog.v(TAG_WM, "Setting im layer adj to " + adj); 913 mInputMethodAnimLayerAdjustment = adj; 914 final WindowState imw = mService.mInputMethodWindow; 915 if (imw != null) { 916 imw.adjustAnimLayer(adj); 917 } 918 for (int i = mService.mInputMethodDialogs.size() - 1; i >= 0; i--) { 919 final WindowState dialog = mService.mInputMethodDialogs.get(i); 920 // TODO: This and other places setting mAnimLayer can probably use WS.adjustAnimLayer, 921 // but need to make sure we are not setting things twice for child windows that are 922 // already in the list. 923 dialog.mWinAnimator.mAnimLayer = dialog.mLayer + adj; 924 if (DEBUG_LAYERS) Slog.v(TAG_WM, "IM win " + imw 925 + " anim layer: " + dialog.mWinAnimator.mAnimLayer); 926 } 927 } 928 929 /** 930 * If a window that has an animation specifying a colored background and the current wallpaper 931 * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to 932 * suddenly disappear. 933 */ 934 int getLayerForAnimationBackground(WindowStateAnimator winAnimator) { 935 for (int i = mWindows.size() - 1; i >= 0; --i) { 936 final WindowState win = mWindows.get(i); 937 if (win.mIsWallpaper && win.isVisibleNow()) { 938 return win.mWinAnimator.mAnimLayer; 939 } 940 } 941 return winAnimator.mAnimLayer; 942 } 943 944 void prepareFreezingTaskBounds() { 945 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 946 final TaskStack stack = mTaskStackContainers.get(stackNdx); 947 stack.prepareFreezingTaskBounds(); 948 } 949 } 950 951 void rotateBounds(int oldRotation, int newRotation, Rect bounds) { 952 getLogicalDisplayRect(mTmpRect, newRotation); 953 954 // Compute a transform matrix to undo the coordinate space transformation, 955 // and present the window at the same physical position it previously occupied. 956 final int deltaRotation = deltaRotation(newRotation, oldRotation); 957 createRotationMatrix(deltaRotation, mTmpRect.width(), mTmpRect.height(), mTmpMatrix); 958 959 mTmpRectF.set(bounds); 960 mTmpMatrix.mapRect(mTmpRectF); 961 mTmpRectF.round(bounds); 962 } 963 964 static int deltaRotation(int oldRotation, int newRotation) { 965 int delta = newRotation - oldRotation; 966 if (delta < 0) delta += 4; 967 return delta; 968 } 969 970 private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight, 971 Matrix outMatrix) { 972 // For rotations without Z-ordering we don't need the target rectangle's position. 973 createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth, 974 displayHeight, outMatrix); 975 } 976 977 static void createRotationMatrix(int rotation, float rectLeft, float rectTop, 978 float displayWidth, float displayHeight, Matrix outMatrix) { 979 switch (rotation) { 980 case ROTATION_0: 981 outMatrix.reset(); 982 break; 983 case ROTATION_270: 984 outMatrix.setRotate(270, 0, 0); 985 outMatrix.postTranslate(0, displayHeight); 986 outMatrix.postTranslate(rectTop, 0); 987 break; 988 case ROTATION_180: 989 outMatrix.reset(); 990 break; 991 case ROTATION_90: 992 outMatrix.setRotate(90, 0, 0); 993 outMatrix.postTranslate(displayWidth, 0); 994 outMatrix.postTranslate(-rectTop, rectLeft); 995 break; 996 } 997 } 998 999 public void dump(String prefix, PrintWriter pw) { 1000 pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId); 1001 final String subPrefix = " " + prefix; 1002 pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x"); 1003 pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity); 1004 pw.print("dpi"); 1005 if (mInitialDisplayWidth != mBaseDisplayWidth 1006 || mInitialDisplayHeight != mBaseDisplayHeight 1007 || mInitialDisplayDensity != mBaseDisplayDensity) { 1008 pw.print(" base="); 1009 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); 1010 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi"); 1011 } 1012 if (mDisplayScalingDisabled) { 1013 pw.println(" noscale"); 1014 } 1015 pw.print(" cur="); 1016 pw.print(mDisplayInfo.logicalWidth); 1017 pw.print("x"); pw.print(mDisplayInfo.logicalHeight); 1018 pw.print(" app="); 1019 pw.print(mDisplayInfo.appWidth); 1020 pw.print("x"); pw.print(mDisplayInfo.appHeight); 1021 pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth); 1022 pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight); 1023 pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth); 1024 pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight); 1025 pw.println(subPrefix + "deferred=" + mDeferredRemoval 1026 + " mLayoutNeeded=" + mLayoutNeeded); 1027 1028 pw.println(); 1029 pw.println(prefix + "Application tokens in top down Z order:"); 1030 for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { 1031 final TaskStack stack = mTaskStackContainers.get(stackNdx); 1032 stack.dump(prefix + " ", pw); 1033 } 1034 1035 pw.println(); 1036 if (!mExitingTokens.isEmpty()) { 1037 pw.println(); 1038 pw.println(" Exiting tokens:"); 1039 for (int i = mExitingTokens.size() - 1; i >= 0; i--) { 1040 final WindowToken token = mExitingTokens.get(i); 1041 pw.print(" Exiting #"); pw.print(i); 1042 pw.print(' '); pw.print(token); 1043 pw.println(':'); 1044 token.dump(pw, " "); 1045 } 1046 } 1047 pw.println(); 1048 mDimLayerController.dump(prefix, pw); 1049 pw.println(); 1050 mDividerControllerLocked.dump(prefix, pw); 1051 pw.println(); 1052 mPinnedStackControllerLocked.dump(prefix, pw); 1053 1054 if (mInputMethodAnimLayerAdjustment != 0) { 1055 pw.println(subPrefix 1056 + "mInputMethodAnimLayerAdjustment=" + mInputMethodAnimLayerAdjustment); 1057 } 1058 } 1059 1060 @Override 1061 public String toString() { 1062 return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren; 1063 } 1064 1065 String getName() { 1066 return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\""; 1067 } 1068 1069 /** 1070 * @return The docked stack, but only if it is visible, and {@code null} otherwise. 1071 */ 1072 TaskStack getDockedStackLocked() { 1073 final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID); 1074 return (stack != null && stack.isVisible()) ? stack : null; 1075 } 1076 1077 /** 1078 * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not 1079 * visible. 1080 */ 1081 TaskStack getDockedStackIgnoringVisibility() { 1082 return mService.mStackIdToStack.get(DOCKED_STACK_ID); 1083 } 1084 1085 /** Find the visible, touch-deliverable window under the given point */ 1086 WindowState getTouchableWinAtPointLocked(float xf, float yf) { 1087 WindowState touchedWin = null; 1088 final int x = (int) xf; 1089 final int y = (int) yf; 1090 1091 for (int i = mWindows.size() - 1; i >= 0; i--) { 1092 WindowState window = mWindows.get(i); 1093 final int flags = window.mAttrs.flags; 1094 if (!window.isVisibleLw()) { 1095 continue; 1096 } 1097 if ((flags & FLAG_NOT_TOUCHABLE) != 0) { 1098 continue; 1099 } 1100 1101 window.getVisibleBounds(mTmpRect); 1102 if (!mTmpRect.contains(x, y)) { 1103 continue; 1104 } 1105 1106 window.getTouchableRegion(mTmpRegion); 1107 1108 final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL); 1109 if (mTmpRegion.contains(x, y) || touchFlags == 0) { 1110 touchedWin = window; 1111 break; 1112 } 1113 } 1114 1115 return touchedWin; 1116 } 1117 1118 boolean canAddToastWindowForUid(int uid) { 1119 // We allow one toast window per UID being shown at a time. 1120 final int windowCount = mWindows.size(); 1121 for (int i = 0; i < windowCount; i++) { 1122 final WindowState window = mWindows.get(i); 1123 if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == uid 1124 && !window.mPermanentlyHidden && !window.mAnimatingExit 1125 && !window.mRemoveOnExit) { 1126 return false; 1127 } 1128 } 1129 return true; 1130 } 1131 1132 void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) { 1133 if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) { 1134 return; 1135 } 1136 final int lostFocusUid = oldFocus.mOwnerUid; 1137 final int windowCount = mWindows.size(); 1138 final Handler handler = mService.mH; 1139 for (int i = 0; i < windowCount; i++) { 1140 final WindowState window = mWindows.get(i); 1141 if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == lostFocusUid) { 1142 if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, window)) { 1143 handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, window), 1144 window.mAttrs.hideTimeoutMilliseconds); 1145 } 1146 } 1147 } 1148 } 1149 1150 WindowState findFocusedWindow() { 1151 final AppWindowToken focusedApp = mService.mFocusedApp; 1152 1153 for (int i = mWindows.size() - 1; i >= 0; i--) { 1154 final WindowState win = mWindows.get(i); 1155 1156 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + i + " = " + win 1157 + ", flags=" + win.mAttrs.flags + ", canReceive=" + win.canReceiveKeys()); 1158 1159 if (!win.canReceiveKeys()) { 1160 continue; 1161 } 1162 1163 final AppWindowToken wtoken = win.mAppToken; 1164 1165 // If this window's application has been removed, just skip it. 1166 if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) { 1167 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because " 1168 + (wtoken.removed ? "removed" : "sendingToBottom")); 1169 continue; 1170 } 1171 1172 if (focusedApp == null) { 1173 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null" 1174 + " using new focus @ " + i + " = " + win); 1175 return win; 1176 } 1177 1178 if (!focusedApp.windowsAreFocusable()) { 1179 // Current focused app windows aren't focusable... 1180 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not" 1181 + " focusable using new focus @ " + i + " = " + win); 1182 return win; 1183 } 1184 1185 // Descend through all of the app tokens and find the first that either matches 1186 // win.mAppToken (return win) or mFocusedApp (return null). 1187 if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING) { 1188 if (focusedApp.compareTo(wtoken) > 0) { 1189 // App stack below focused app stack. No focus for you!!! 1190 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, 1191 "findFocusedWindow: Reached focused app=" + focusedApp); 1192 return null; 1193 } 1194 } 1195 1196 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " 1197 + i + " = " + win); 1198 return win; 1199 } 1200 1201 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows."); 1202 return null; 1203 } 1204 1205 void addAppWindowToWindowList(final WindowState win) { 1206 final IWindow client = win.mClient; 1207 1208 WindowList tokenWindowList = getTokenWindowsOnDisplay(win.mToken); 1209 if (!tokenWindowList.isEmpty()) { 1210 addAppWindowExisting(win, tokenWindowList); 1211 return; 1212 } 1213 1214 // No windows from this token on this display 1215 if (localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window " 1216 + client.asBinder() + " (token=" + this + ")"); 1217 1218 final WindowToken wToken = win.mToken; 1219 1220 // Figure out where the window should go, based on the order of applications. 1221 mTmpGetWindowOnDisplaySearchResult.reset(); 1222 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1223 final TaskStack stack = mTaskStackContainers.get(i); 1224 stack.getWindowOnDisplayBeforeToken(this, wToken, mTmpGetWindowOnDisplaySearchResult); 1225 if (mTmpGetWindowOnDisplaySearchResult.reachedToken) { 1226 // We have reach the token we are interested in. End search. 1227 break; 1228 } 1229 } 1230 1231 WindowState pos = mTmpGetWindowOnDisplaySearchResult.foundWindow; 1232 1233 // We now know the index into the apps. If we found an app window above, that gives us the 1234 // position; else we need to look some more. 1235 if (pos != null) { 1236 // Move behind any windows attached to this one. 1237 final WindowToken atoken = getWindowToken(pos.mClient.asBinder()); 1238 if (atoken != null) { 1239 tokenWindowList = getTokenWindowsOnDisplay(atoken); 1240 final int NC = tokenWindowList.size(); 1241 if (NC > 0) { 1242 WindowState bottom = tokenWindowList.get(0); 1243 if (bottom.mSubLayer < 0) { 1244 pos = bottom; 1245 } 1246 } 1247 } 1248 addWindowToListBefore(win, pos); 1249 return; 1250 } 1251 1252 // Continue looking down until we find the first token that has windows on this display. 1253 mTmpGetWindowOnDisplaySearchResult.reset(); 1254 for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { 1255 final TaskStack stack = mTaskStackContainers.get(i); 1256 stack.getWindowOnDisplayAfterToken(this, wToken, mTmpGetWindowOnDisplaySearchResult); 1257 if (mTmpGetWindowOnDisplaySearchResult.foundWindow != null) { 1258 // We have found a window after the token. End search. 1259 break; 1260 } 1261 } 1262 1263 pos = mTmpGetWindowOnDisplaySearchResult.foundWindow; 1264 1265 if (pos != null) { 1266 // Move in front of any windows attached to this one. 1267 final WindowToken atoken = getWindowToken(pos.mClient.asBinder()); 1268 if (atoken != null) { 1269 final WindowState top = atoken.getTopWindow(); 1270 if (top != null && top.mSubLayer >= 0) { 1271 pos = top; 1272 } 1273 } 1274 addWindowToListAfter(win, pos); 1275 return; 1276 } 1277 1278 // Just search for the start of this layer. 1279 final int myLayer = win.mBaseLayer; 1280 int i; 1281 for (i = mWindows.size() - 1; i >= 0; --i) { 1282 final WindowState w = mWindows.get(i); 1283 // Dock divider shares the base layer with application windows, but we want to always 1284 // keep it above the application windows. The sharing of the base layer is intended 1285 // for window animations, which need to be above the dock divider for the duration 1286 // of the animation. 1287 if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) { 1288 break; 1289 } 1290 } 1291 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1292 "Based on layer: Adding window " + win + " at " + (i + 1) + " of " 1293 + mWindows.size()); 1294 mWindows.add(i + 1, win); 1295 mService.mWindowsChanged = true; 1296 } 1297 1298 /** Adds this non-app window to the window list. */ 1299 void addNonAppWindowToWindowList(WindowState win) { 1300 // Figure out where window should go, based on layer. 1301 int i; 1302 for (i = mWindows.size() - 1; i >= 0; i--) { 1303 final WindowState otherWin = mWindows.get(i); 1304 if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= win.mBaseLayer) { 1305 // Wallpaper wanders through the window list, for example to position itself 1306 // directly behind keyguard. Because of this it will break the ordering based on 1307 // WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and 1308 // we don't want the new window to appear above them. An example of this is adding 1309 // of the docked stack divider. Consider a scenario with the following ordering (top 1310 // to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider 1311 // to land below the assist preview, so the dock divider must ignore the wallpaper, 1312 // with which it shares the base layer. 1313 break; 1314 } 1315 } 1316 1317 i++; 1318 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 1319 "Free window: Adding window " + this + " at " + i + " of " + mWindows.size()); 1320 mWindows.add(i, win); 1321 mService.mWindowsChanged = true; 1322 } 1323 1324 void addToWindowList(WindowState win, int index) { 1325 mService.mWindowsChanged = true; 1326 mWindows.add(index, win); 1327 } 1328 1329 boolean removeFromWindowList(WindowState win) { 1330 mService.mWindowsChanged = true; 1331 return mWindows.remove(win); 1332 } 1333 1334 private int removeWindowAndChildrenFromWindowList(WindowState win, int interestingPos) { 1335 int wpos = mWindows.indexOf(win); 1336 if (wpos < 0) { 1337 return interestingPos; 1338 } 1339 1340 if (wpos < interestingPos) interestingPos--; 1341 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing at " + wpos + ": " + this); 1342 mWindows.remove(wpos); 1343 mService.mWindowsChanged = true; 1344 int childWinCount = win.mChildren.size(); 1345 while (childWinCount > 0) { 1346 childWinCount--; 1347 final WindowState cw = win.mChildren.get(childWinCount); 1348 int cpos = mWindows.indexOf(cw); 1349 if (cpos >= 0) { 1350 if (cpos < interestingPos) interestingPos--; 1351 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, 1352 "Temp removing child at " + cpos + ": " + cw); 1353 mWindows.remove(cpos); 1354 } 1355 } 1356 return interestingPos; 1357 } 1358 1359 void addChildWindowToWindowList(WindowState win) { 1360 final WindowState parentWindow = win.getParentWindow(); 1361 1362 WindowList windowsOnSameDisplay = getTokenWindowsOnDisplay(win.mToken); 1363 1364 // Figure out this window's ordering relative to the parent window. 1365 final int wCount = windowsOnSameDisplay.size(); 1366 final int sublayer = win.mSubLayer; 1367 int largestSublayer = Integer.MIN_VALUE; 1368 WindowState windowWithLargestSublayer = null; 1369 int i; 1370 for (i = 0; i < wCount; i++) { 1371 WindowState w = windowsOnSameDisplay.get(i); 1372 final int wSublayer = w.mSubLayer; 1373 if (wSublayer >= largestSublayer) { 1374 largestSublayer = wSublayer; 1375 windowWithLargestSublayer = w; 1376 } 1377 if (sublayer < 0) { 1378 // For negative sublayers, we go below all windows in the same sublayer. 1379 if (wSublayer >= sublayer) { 1380 addWindowToListBefore(win, wSublayer >= 0 ? parentWindow : w); 1381 break; 1382 } 1383 } else { 1384 // For positive sublayers, we go above all windows in the same sublayer. 1385 if (wSublayer > sublayer) { 1386 addWindowToListBefore(win, w); 1387 break; 1388 } 1389 } 1390 } 1391 if (i >= wCount) { 1392 if (sublayer < 0) { 1393 addWindowToListBefore(win, parentWindow); 1394 } else { 1395 addWindowToListAfter(win, 1396 largestSublayer >= 0 ? windowWithLargestSublayer : parentWindow); 1397 } 1398 } 1399 } 1400 1401 /** Updates the layer assignment of windows on this display. */ 1402 void assignWindowLayers(boolean setLayoutNeeded) { 1403 mLayersController.assignWindowLayers(mWindows.getReadOnly()); 1404 if (setLayoutNeeded) { 1405 setLayoutNeeded(); 1406 } 1407 } 1408 1409 void adjustWallpaperWindows() { 1410 if (mWallpaperController.adjustWallpaperWindows(mWindows.getReadOnly())) { 1411 assignWindowLayers(true /*setLayoutNeeded*/); 1412 } 1413 } 1414 1415 /** 1416 * Z-orders the display window list so that: 1417 * <ul> 1418 * <li>Any windows that are currently below the wallpaper window stay below the wallpaper 1419 * window. 1420 * <li>Exiting application windows are at the bottom, but above the wallpaper window. 1421 * <li>All other application windows are above the exiting application windows and ordered based 1422 * on the ordering of their stacks and tasks on the display. 1423 * <li>Non-application windows are at the very top. 1424 * </ul> 1425 * <p> 1426 * NOTE: This isn't a complete picture of what the user see. Further manipulation of the window 1427 * surface layering is done in {@link WindowLayersController}. 1428 */ 1429 void rebuildAppWindowList() { 1430 int count = mWindows.size(); 1431 int i; 1432 int lastBelow = -1; 1433 int numRemoved = 0; 1434 1435 if (mRebuildTmp.length < count) { 1436 mRebuildTmp = new WindowState[count + 10]; 1437 } 1438 1439 // First remove all existing app windows. 1440 i = 0; 1441 while (i < count) { 1442 final WindowState w = mWindows.get(i); 1443 if (w.mAppToken != null) { 1444 final WindowState win = mWindows.remove(i); 1445 win.mRebuilding = true; 1446 mRebuildTmp[numRemoved] = win; 1447 mService.mWindowsChanged = true; 1448 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win); 1449 count--; 1450 numRemoved++; 1451 continue; 1452 } else if (lastBelow == i-1) { 1453 if (w.mAttrs.type == TYPE_WALLPAPER) { 1454 lastBelow = i; 1455 } 1456 } 1457 i++; 1458 } 1459 1460 // Keep whatever windows were below the app windows still below, by skipping them. 1461 lastBelow++; 1462 i = lastBelow; 1463 1464 // First add all of the exiting app tokens... these are no longer in the main app list, 1465 // but still have windows shown. We put them in the back because now that the animation is 1466 // over we no longer will care about them. 1467 final int numStacks = mTaskStackContainers.size(); 1468 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 1469 AppTokenList exitingAppTokens = mTaskStackContainers.get(stackNdx).mExitingAppTokens; 1470 int NT = exitingAppTokens.size(); 1471 for (int j = 0; j < NT; j++) { 1472 i = exitingAppTokens.get(j).rebuildWindowListUnchecked(i); 1473 } 1474 } 1475 1476 // And add in the still active app tokens in Z order. 1477 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 1478 i = mTaskStackContainers.get(stackNdx).rebuildWindowList(i); 1479 } 1480 1481 i -= lastBelow; 1482 if (i != numRemoved) { 1483 setLayoutNeeded(); 1484 Slog.w(TAG_WM, "On display=" + mDisplayId + " Rebuild removed " + numRemoved 1485 + " windows but added " + i + " rebuildAppWindowListLocked() " 1486 + " callers=" + Debug.getCallers(10)); 1487 for (i = 0; i < numRemoved; i++) { 1488 WindowState ws = mRebuildTmp[i]; 1489 if (ws.mRebuilding) { 1490 StringWriter sw = new StringWriter(); 1491 PrintWriter pw = new FastPrintWriter(sw, false, 1024); 1492 ws.dump(pw, "", true); 1493 pw.flush(); 1494 Slog.w(TAG_WM, "This window was lost: " + ws); 1495 Slog.w(TAG_WM, sw.toString()); 1496 ws.mWinAnimator.destroySurfaceLocked(); 1497 } 1498 } 1499 Slog.w(TAG_WM, "Current window hierarchy:"); 1500 dumpChildrenNames(); 1501 Slog.w(TAG_WM, "Final window list:"); 1502 dumpWindows(); 1503 } 1504 Arrays.fill(mRebuildTmp, null); 1505 } 1506 1507 /** Rebuilds the display's window list and does a relayout if something changed. */ 1508 void rebuildAppWindowsAndLayoutIfNeeded() { 1509 mTmpWindows.clear(); 1510 mTmpWindows.addAll(mWindows); 1511 1512 rebuildAppWindowList(); 1513 1514 // Set displayContent.mLayoutNeeded if window order changed. 1515 final int tmpSize = mTmpWindows.size(); 1516 final int winSize = mWindows.size(); 1517 int tmpNdx = 0, winNdx = 0; 1518 while (tmpNdx < tmpSize && winNdx < winSize) { 1519 // Skip over all exiting windows, they've been moved out of order. 1520 WindowState tmp; 1521 do { 1522 tmp = mTmpWindows.get(tmpNdx++); 1523 } while (tmpNdx < tmpSize && tmp.mAppToken != null && tmp.mAppToken.mIsExiting); 1524 1525 WindowState win; 1526 do { 1527 win = mWindows.get(winNdx++); 1528 } while (winNdx < winSize && win.mAppToken != null && win.mAppToken.mIsExiting); 1529 1530 if (tmp != win) { 1531 // Window order changed. 1532 setLayoutNeeded(); 1533 break; 1534 } 1535 } 1536 if (tmpNdx != winNdx) { 1537 // One list was different from the other. 1538 setLayoutNeeded(); 1539 } 1540 mTmpWindows.clear(); 1541 1542 if (!mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 1543 false /*updateInputWindows*/)) { 1544 assignWindowLayers(false /* setLayoutNeeded */); 1545 } 1546 1547 mService.mInputMonitor.setUpdateInputWindowsNeededLw(); 1548 mService.mWindowPlacerLocked.performSurfacePlacement(); 1549 mService.mInputMonitor.updateInputWindowsLw(false /*force*/); 1550 } 1551 1552 void updateInputWindows(InputMonitor inputMonitor, WindowState inputFocus, boolean inDrag) { 1553 final InputConsumerImpl navInputConsumer = 1554 mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_NAVIGATION, mDisplayId); 1555 final InputConsumerImpl pipInputConsumer = 1556 mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_PIP, mDisplayId); 1557 final InputConsumerImpl wallpaperInputConsumer = 1558 mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_WALLPAPER, mDisplayId); 1559 boolean addInputConsumerHandle = navInputConsumer != null; 1560 boolean addPipInputConsumerHandle = pipInputConsumer != null; 1561 boolean addWallpaperInputConsumerHandle = wallpaperInputConsumer != null; 1562 final Rect pipTouchableBounds = addPipInputConsumerHandle ? new Rect() : null; 1563 boolean disableWallpaperTouchEvents = false; 1564 1565 for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) { 1566 final WindowState child = mWindows.get(winNdx); 1567 final InputChannel inputChannel = child.mInputChannel; 1568 final InputWindowHandle inputWindowHandle = child.mInputWindowHandle; 1569 if (inputChannel == null || inputWindowHandle == null || child.mRemoved 1570 || child.isAdjustedForMinimizedDock()) { 1571 // Skip this window because it cannot possibly receive input. 1572 continue; 1573 } 1574 1575 if (addPipInputConsumerHandle 1576 && child.getStackId() == PINNED_STACK_ID 1577 && inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer) { 1578 // Update the bounds of the Pip input consumer to match the Pinned stack 1579 child.getStack().getBounds(pipTouchableBounds); 1580 pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds); 1581 inputMonitor.addInputWindowHandle(pipInputConsumer.mWindowHandle); 1582 addPipInputConsumerHandle = false; 1583 } 1584 1585 if (addInputConsumerHandle 1586 && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) { 1587 inputMonitor.addInputWindowHandle(navInputConsumer.mWindowHandle); 1588 addInputConsumerHandle = false; 1589 } 1590 1591 if (addWallpaperInputConsumerHandle) { 1592 if (child.mAttrs.type == TYPE_WALLPAPER && child.isVisibleLw()) { 1593 // Add the wallpaper input consumer above the first visible wallpaper. 1594 inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle); 1595 addWallpaperInputConsumerHandle = false; 1596 } 1597 } 1598 1599 final int flags = child.mAttrs.flags; 1600 final int privateFlags = child.mAttrs.privateFlags; 1601 final int type = child.mAttrs.type; 1602 1603 final boolean hasFocus = child == inputFocus; 1604 final boolean isVisible = child.isVisibleLw(); 1605 if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) { 1606 disableWallpaperTouchEvents = true; 1607 } 1608 final boolean hasWallpaper = mWallpaperController.isWallpaperTarget(child) 1609 && (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0 1610 && !disableWallpaperTouchEvents; 1611 1612 // If there's a drag in progress and 'child' is a potential drop target, 1613 // make sure it's been told about the drag 1614 if (inDrag && isVisible && isDefaultDisplay) { 1615 mService.mDragState.sendDragStartedIfNeededLw(child); 1616 } 1617 1618 inputMonitor.addInputWindowHandle( 1619 inputWindowHandle, child, flags, type, isVisible, hasFocus, hasWallpaper); 1620 } 1621 1622 if (addWallpaperInputConsumerHandle) { 1623 // No visible wallpaper found, add the wallpaper input consumer at the end. 1624 inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle); 1625 } 1626 } 1627 1628 /** Returns true if a leaked surface was destroyed */ 1629 boolean destroyLeakedSurfaces() { 1630 boolean leakedSurface = false; 1631 final int numWindows = mWindows.size(); 1632 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 1633 final WindowState ws = mWindows.get(winNdx); 1634 final WindowStateAnimator wsa = ws.mWinAnimator; 1635 if (wsa.mSurfaceController == null) { 1636 continue; 1637 } 1638 if (!mService.mSessions.contains(wsa.mSession)) { 1639 Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): " 1640 + ws + " surface=" + wsa.mSurfaceController 1641 + " token=" + ws.mToken 1642 + " pid=" + ws.mSession.mPid 1643 + " uid=" + ws.mSession.mUid); 1644 wsa.destroySurface(); 1645 mService.mForceRemoves.add(ws); 1646 leakedSurface = true; 1647 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 1648 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): " 1649 + ws + " surface=" + wsa.mSurfaceController 1650 + " token=" + ws.mAppToken 1651 + " saved=" + ws.hasSavedSurface()); 1652 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false); 1653 wsa.destroySurface(); 1654 leakedSurface = true; 1655 } 1656 } 1657 1658 return leakedSurface; 1659 } 1660 1661 /** Return the list of Windows on this display associated with the input token. */ 1662 WindowList getTokenWindowsOnDisplay(WindowToken token) { 1663 final WindowList windowList = new WindowList(); 1664 final int count = mWindows.size(); 1665 for (int i = 0; i < count; i++) { 1666 final WindowState win = mWindows.get(i); 1667 if (win.mToken == token) { 1668 windowList.add(win); 1669 } 1670 } 1671 return windowList; 1672 } 1673 1674 private void reAddToWindowList(WindowState win) { 1675 win.mToken.addWindow(win); 1676 // This is a hack to get all of the child windows added as well at the right position. Child 1677 // windows should be rare and this case should be rare, so it shouldn't be that big a deal. 1678 int wpos = mWindows.indexOf(win); 1679 if (wpos >= 0) { 1680 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "ReAdd removing from " + wpos + ": " + win); 1681 mWindows.remove(wpos); 1682 mService.mWindowsChanged = true; 1683 win.reAddWindow(wpos); 1684 } 1685 } 1686 1687 void moveInputMethodDialogs(int pos) { 1688 ArrayList<WindowState> dialogs = mService.mInputMethodDialogs; 1689 1690 final int N = dialogs.size(); 1691 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Removing " + N + " dialogs w/pos=" + pos); 1692 for (int i = 0; i < N; i++) { 1693 pos = removeWindowAndChildrenFromWindowList(dialogs.get(i), pos); 1694 } 1695 if (DEBUG_INPUT_METHOD) { 1696 Slog.v(TAG_WM, "Window list w/pos=" + pos); 1697 logWindowList(mWindows, " "); 1698 } 1699 1700 WindowState ime = mService.mInputMethodWindow; 1701 if (pos >= 0) { 1702 // Skip windows owned by the input method. 1703 if (ime != null) { 1704 while (pos < mWindows.size()) { 1705 WindowState wp = mWindows.get(pos); 1706 if (wp == ime || wp.getParentWindow() == ime) { 1707 pos++; 1708 continue; 1709 } 1710 break; 1711 } 1712 } 1713 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Adding " + N + " dialogs at pos=" + pos); 1714 for (int i=0; i<N; i++) { 1715 WindowState win = dialogs.get(i); 1716 pos = win.reAddWindow(pos); 1717 } 1718 if (DEBUG_INPUT_METHOD) { 1719 Slog.v(TAG_WM, "Final window list:"); 1720 logWindowList(mWindows, " "); 1721 } 1722 return; 1723 } 1724 for (int i=0; i<N; i++) { 1725 WindowState win = dialogs.get(i); 1726 reAddToWindowList(win); 1727 if (DEBUG_INPUT_METHOD) { 1728 Slog.v(TAG_WM, "No IM target, final list:"); 1729 logWindowList(mWindows, " "); 1730 } 1731 } 1732 } 1733 1734 boolean moveInputMethodWindowsIfNeeded(boolean needAssignLayers) { 1735 final WindowState imWin = mService.mInputMethodWindow; 1736 final int DN = mService.mInputMethodDialogs.size(); 1737 if (imWin == null && DN == 0) { 1738 return false; 1739 } 1740 1741 // TODO(multidisplay): IMEs are only supported on the default display. 1742 int imPos = findDesiredInputMethodWindowIndex(true); 1743 if (imPos >= 0) { 1744 // In this case, the input method windows are to be placed 1745 // immediately above the window they are targeting. 1746 1747 // First check to see if the input method windows are already 1748 // located here, and contiguous. 1749 final int N = mWindows.size(); 1750 final WindowState firstImWin = imPos < N ? mWindows.get(imPos) : null; 1751 1752 // Figure out the actual input method window that should be 1753 // at the bottom of their stack. 1754 WindowState baseImWin = imWin != null ? imWin : mService.mInputMethodDialogs.get(0); 1755 final WindowState cw = baseImWin.getBottomChild(); 1756 if (cw != null && cw.mSubLayer < 0) { 1757 baseImWin = cw; 1758 } 1759 1760 if (firstImWin == baseImWin) { 1761 // The windows haven't moved... but are they still contiguous? 1762 // First find the top IM window. 1763 int pos = imPos+1; 1764 while (pos < N) { 1765 if (!(mWindows.get(pos)).mIsImWindow) { 1766 break; 1767 } 1768 pos++; 1769 } 1770 pos++; 1771 // Now there should be no more input method windows above. 1772 while (pos < N) { 1773 if ((mWindows.get(pos)).mIsImWindow) { 1774 break; 1775 } 1776 pos++; 1777 } 1778 if (pos >= N) { 1779 return false; 1780 } 1781 } 1782 1783 if (imWin != null) { 1784 if (DEBUG_INPUT_METHOD) { 1785 Slog.v(TAG_WM, "Moving IM from " + imPos); 1786 logWindowList(mWindows, " "); 1787 } 1788 imPos = removeWindowAndChildrenFromWindowList(imWin, imPos); 1789 if (DEBUG_INPUT_METHOD) { 1790 Slog.v(TAG_WM, "List after removing with new pos " + imPos + ":"); 1791 logWindowList(mWindows, " "); 1792 } 1793 imWin.reAddWindow(imPos); 1794 if (DEBUG_INPUT_METHOD) { 1795 Slog.v(TAG_WM, "List after moving IM to " + imPos + ":"); 1796 logWindowList(mWindows, " "); 1797 } 1798 if (DN > 0) moveInputMethodDialogs(imPos+1); 1799 } else { 1800 moveInputMethodDialogs(imPos); 1801 } 1802 1803 } else { 1804 // In this case, the input method windows go in a fixed layer, 1805 // because they aren't currently associated with a focus window. 1806 1807 if (imWin != null) { 1808 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Moving IM from " + imPos); 1809 removeWindowAndChildrenFromWindowList(imWin, 0); 1810 reAddToWindowList(imWin); 1811 if (DEBUG_INPUT_METHOD) { 1812 Slog.v(TAG_WM, "List with no IM target:"); 1813 logWindowList(mWindows, " "); 1814 } 1815 if (DN > 0) moveInputMethodDialogs(-1); 1816 } else { 1817 moveInputMethodDialogs(-1); 1818 } 1819 1820 } 1821 1822 if (needAssignLayers) { 1823 assignWindowLayers(false /* setLayoutNeeded */); 1824 } 1825 1826 return true; 1827 } 1828 1829 /** 1830 * Dig through the WindowStates and find the one that the Input Method will target. 1831 * @param willMove 1832 * @return The index+1 in mWindows of the discovered target. 1833 */ 1834 int findDesiredInputMethodWindowIndex(boolean willMove) { 1835 // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the 1836 // same display. Or even when the current IME/target are not on the same screen as the next 1837 // IME/target. For now only look for input windows on the main screen. 1838 WindowState w = null; 1839 int i; 1840 for (i = mWindows.size() - 1; i >= 0; --i) { 1841 final WindowState win = mWindows.get(i); 1842 1843 if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG_WM, "Checking window @" + i 1844 + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags)); 1845 if (canBeImeTarget(win)) { 1846 w = win; 1847 //Slog.i(TAG_WM, "Putting input method here!"); 1848 1849 // Yet more tricksyness! If this window is a "starting" window, we do actually want 1850 // to be on top of it, but it is not -really- where input will go. So if the caller 1851 // is not actually looking to move the IME, look down below for a real window to 1852 // target... 1853 if (!willMove && w.mAttrs.type == TYPE_APPLICATION_STARTING && i > 0) { 1854 final WindowState wb = mWindows.get(i-1); 1855 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) { 1856 i--; 1857 w = wb; 1858 } 1859 } 1860 break; 1861 } 1862 } 1863 1864 // Now w is either mWindows[0] or an IME (or null if mWindows is empty). 1865 1866 if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG_WM, "Proposed new IME target: " + w); 1867 1868 // Now, a special case -- if the last target's window is in the process of exiting, and is 1869 // above the new target, keep on the last target to avoid flicker. Consider for example a 1870 // Dialog with the IME shown: when the Dialog is dismissed, we want to keep the IME above it 1871 // until it is completely gone so it doesn't drop behind the dialog or its full-screen 1872 // scrim. 1873 final WindowState curTarget = mService.mInputMethodTarget; 1874 if (curTarget != null 1875 && curTarget.isDisplayedLw() 1876 && curTarget.isClosing() 1877 && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) { 1878 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing"); 1879 return mWindows.indexOf(curTarget) + 1; 1880 } 1881 1882 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" 1883 + w + " willMove=" + willMove); 1884 1885 if (willMove && w != null) { 1886 AppWindowToken token = curTarget == null ? null : curTarget.mAppToken; 1887 if (token != null) { 1888 1889 // Now some fun for dealing with window animations that modify the Z order. We need 1890 // to look at all windows below the current target that are in this app, finding the 1891 // highest visible one in layering. 1892 WindowState highestTarget = null; 1893 int highestPos = 0; 1894 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) { 1895 WindowList curWindows = token.getDisplayContent().mWindows; 1896 int pos = curWindows.indexOf(curTarget); 1897 while (pos >= 0) { 1898 WindowState win = curWindows.get(pos); 1899 if (win.mAppToken != token) { 1900 break; 1901 } 1902 if (!win.mRemoved) { 1903 if (highestTarget == null || win.mWinAnimator.mAnimLayer > 1904 highestTarget.mWinAnimator.mAnimLayer) { 1905 highestTarget = win; 1906 highestPos = pos; 1907 } 1908 } 1909 pos--; 1910 } 1911 } 1912 1913 if (highestTarget != null) { 1914 final AppTransition appTransition = mService.mAppTransition; 1915 if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, appTransition + " " + highestTarget 1916 + " animating=" + highestTarget.mWinAnimator.isAnimationSet() 1917 + " layer=" + highestTarget.mWinAnimator.mAnimLayer 1918 + " new layer=" + w.mWinAnimator.mAnimLayer); 1919 1920 if (appTransition.isTransitionSet()) { 1921 // If we are currently setting up for an animation, hold everything until we 1922 // can find out what will happen. 1923 mService.mInputMethodTargetWaitingAnim = true; 1924 mService.mInputMethodTarget = highestTarget; 1925 return highestPos + 1; 1926 } else if (highestTarget.mWinAnimator.isAnimationSet() && 1927 highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) { 1928 // If the window we are currently targeting is involved with an animation, 1929 // and it is on top of the next target we will be over, then hold off on 1930 // moving until that is done. 1931 mService.mInputMethodTargetWaitingAnim = true; 1932 mService.mInputMethodTarget = highestTarget; 1933 return highestPos + 1; 1934 } 1935 } 1936 } 1937 } 1938 1939 //Slog.i(TAG_WM, "Placing input method @" + (i+1)); 1940 if (w != null) { 1941 if (willMove) { 1942 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to " 1943 + w + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : "")); 1944 mService.mInputMethodTarget = w; 1945 mService.mInputMethodTargetWaitingAnim = false; 1946 if (w.mAppToken != null) { 1947 setInputMethodAnimLayerAdjustment( 1948 w.mAppToken.mAppAnimator.animLayerAdjustment); 1949 } else { 1950 setInputMethodAnimLayerAdjustment(0); 1951 } 1952 } 1953 1954 // If the docked divider is visible, we still need to go through this whole excercise to 1955 // find the appropriate input method target (used for animations and dialog 1956 // adjustments), but for purposes of Z ordering we simply wish to place it above the 1957 // docked divider. Unless it is already above the divider. 1958 final WindowState dockedDivider = mDividerControllerLocked.getWindow(); 1959 if (dockedDivider != null && dockedDivider.isVisibleLw()) { 1960 int dividerIndex = mWindows.indexOf(dockedDivider); 1961 if (dividerIndex > 0 && dividerIndex > i) { 1962 return dividerIndex + 1; 1963 } 1964 } 1965 return i+1; 1966 } 1967 if (willMove) { 1968 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget 1969 + " to null." + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : "")); 1970 mService.mInputMethodTarget = null; 1971 setInputMethodAnimLayerAdjustment(0); 1972 } 1973 return -1; 1974 } 1975 1976 private static boolean canBeImeTarget(WindowState w) { 1977 final int fl = w.mAttrs.flags & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); 1978 final int type = w.mAttrs.type; 1979 1980 if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM) 1981 && type != TYPE_APPLICATION_STARTING) { 1982 return false; 1983 } 1984 1985 if (DEBUG_INPUT_METHOD) { 1986 Slog.i(TAG_WM, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding()); 1987 if (!w.isVisibleOrAdding()) { 1988 Slog.i(TAG_WM, " mSurfaceController=" + w.mWinAnimator.mSurfaceController 1989 + " relayoutCalled=" + w.mRelayoutCalled 1990 + " viewVis=" + w.mViewVisibility 1991 + " policyVis=" + w.mPolicyVisibility 1992 + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim 1993 + " parentHidden=" + w.isParentWindowHidden() 1994 + " exiting=" + w.mAnimatingExit + " destroying=" + w.mDestroying); 1995 if (w.mAppToken != null) { 1996 Slog.i(TAG_WM, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested); 1997 } 1998 } 1999 } 2000 return w.isVisibleOrAdding(); 2001 } 2002 2003 private void logWindowList(final WindowList windows, String prefix) { 2004 int N = windows.size(); 2005 while (N > 0) { 2006 N--; 2007 Slog.v(TAG_WM, prefix + "#" + N + ": " + windows.get(N)); 2008 } 2009 } 2010 2011 boolean getNeedsMenu(WindowState win, WindowManagerPolicy.WindowState bottom) { 2012 int index = -1; 2013 while (true) { 2014 if (win.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) { 2015 return win.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE; 2016 } 2017 // If we reached the bottom of the range of windows we are considering, 2018 // assume no menu is needed. 2019 if (win == bottom) { 2020 return false; 2021 } 2022 // The current window hasn't specified whether menu key is needed; look behind it. 2023 // First, we may need to determine the starting position. 2024 if (index < 0) { 2025 index = mWindows.indexOf(win); 2026 } 2027 index--; 2028 if (index < 0) { 2029 return false; 2030 } 2031 win = mWindows.get(index); 2032 } 2033 } 2034 2035 void setLayoutNeeded() { 2036 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3)); 2037 mLayoutNeeded = true; 2038 } 2039 2040 private void clearLayoutNeeded() { 2041 if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3)); 2042 mLayoutNeeded = false; 2043 } 2044 2045 boolean isLayoutNeeded() { 2046 return mLayoutNeeded; 2047 } 2048 2049 private void addAppWindowExisting(WindowState win, WindowList tokenWindowList) { 2050 2051 // If this application has existing windows, we simply place the new window on top of 2052 // them... but keep the starting window on top. 2053 if (win.mAttrs.type == TYPE_BASE_APPLICATION) { 2054 // Base windows go behind everything else. 2055 final WindowState lowestWindow = tokenWindowList.get(0); 2056 addWindowToListBefore(win, lowestWindow); 2057 } else { 2058 final AppWindowToken atoken = win.mAppToken; 2059 final int windowListPos = tokenWindowList.size(); 2060 final WindowState lastWindow = tokenWindowList.get(windowListPos - 1); 2061 if (atoken != null && lastWindow == atoken.startingWindow) { 2062 addWindowToListBefore(win, lastWindow); 2063 } else { 2064 int newIdx = findIdxBasedOnAppTokens(win); 2065 // There is a window above this one associated with the same apptoken note that the 2066 // window could be a floating window that was created later or a window at the top 2067 // of the list of windows associated with this token. 2068 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 2069 "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " 2070 + mWindows.size()); 2071 mWindows.add(newIdx + 1, win); 2072 mService.mWindowsChanged = true; 2073 } 2074 } 2075 } 2076 2077 /** Places the first input window after the second input window in the window list. */ 2078 private void addWindowToListAfter(WindowState first, WindowState second) { 2079 final int i = mWindows.indexOf(second); 2080 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 2081 "Adding window " + this + " at " + (i + 1) + " of " + mWindows.size() 2082 + " (after " + second + ")"); 2083 mWindows.add(i + 1, first); 2084 mService.mWindowsChanged = true; 2085 } 2086 2087 /** Places the first input window before the second input window in the window list. */ 2088 private void addWindowToListBefore(WindowState first, WindowState second) { 2089 int i = mWindows.indexOf(second); 2090 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, 2091 "Adding window " + this + " at " + i + " of " + mWindows.size() 2092 + " (before " + second + ")"); 2093 if (i < 0) { 2094 Slog.w(TAG_WM, "addWindowToListBefore: Unable to find " + second + " in " + mWindows); 2095 i = 0; 2096 } 2097 mWindows.add(i, first); 2098 mService.mWindowsChanged = true; 2099 } 2100 2101 /** 2102 * This method finds out the index of a window that has the same app token as win. used for z 2103 * ordering the windows in mWindows 2104 */ 2105 private int findIdxBasedOnAppTokens(WindowState win) { 2106 for(int j = mWindows.size() - 1; j >= 0; j--) { 2107 final WindowState wentry = mWindows.get(j); 2108 if(wentry.mAppToken == win.mAppToken) { 2109 return j; 2110 } 2111 } 2112 return -1; 2113 } 2114 2115 private void dumpChildrenNames() { 2116 StringBuilder output = new StringBuilder(); 2117 dumpChildrenNames(output, " "); 2118 Slog.v(TAG_WM, output.toString()); 2119 } 2120 2121 private void dumpWindows() { 2122 Slog.v(TAG_WM, " Display #" + mDisplayId); 2123 for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) { 2124 Slog.v(TAG_WM, " #" + winNdx + ": " + mWindows.get(winNdx)); 2125 } 2126 } 2127 2128 void dumpTokens(PrintWriter pw, boolean dumpAll) { 2129 if (mTokenMap.isEmpty()) { 2130 return; 2131 } 2132 pw.println(" Display #" + mDisplayId); 2133 final Iterator<WindowToken> it = mTokenMap.values().iterator(); 2134 while (it.hasNext()) { 2135 final WindowToken token = it.next(); 2136 pw.print(" "); 2137 pw.print(token); 2138 if (dumpAll) { 2139 pw.println(':'); 2140 token.dump(pw, " "); 2141 } else { 2142 pw.println(); 2143 } 2144 } 2145 } 2146 2147 void dumpWindowAnimators(PrintWriter pw, String subPrefix) { 2148 final int count = mWindows.size(); 2149 for (int j = 0; j < count; j++) { 2150 final WindowStateAnimator wAnim = mWindows.get(j).mWinAnimator; 2151 pw.println(subPrefix + "Window #" + j + ": " + wAnim); 2152 } 2153 } 2154 2155 void enableSurfaceTrace(FileDescriptor fd) { 2156 for (int i = mWindows.size() - 1; i >= 0; i--) { 2157 final WindowState win = mWindows.get(i); 2158 win.mWinAnimator.enableSurfaceTrace(fd); 2159 } 2160 } 2161 2162 void disableSurfaceTrace() { 2163 for (int i = mWindows.size() - 1; i >= 0; i--) { 2164 final WindowState win = mWindows.get(i); 2165 win.mWinAnimator.disableSurfaceTrace(); 2166 } 2167 } 2168 2169 /** 2170 * Starts the Keyguard exit animation on all windows that don't belong to an app token. 2171 */ 2172 void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade) { 2173 final WindowManagerPolicy policy = mService.mPolicy; 2174 for (int i = mWindows.size() - 1; i >= 0; i--) { 2175 final WindowState window = mWindows.get(i); 2176 if (window.mAppToken == null && policy.canBeHiddenByKeyguardLw(window)) { 2177 window.mWinAnimator.setAnimation( 2178 policy.createHiddenByKeyguardExit(onWallpaper, goingToShade)); 2179 } 2180 } 2181 } 2182 2183 boolean checkWaitingForWindows() { 2184 2185 boolean haveBootMsg = false; 2186 boolean haveApp = false; 2187 // if the wallpaper service is disabled on the device, we're never going to have 2188 // wallpaper, don't bother waiting for it 2189 boolean haveWallpaper = false; 2190 boolean wallpaperEnabled = mService.mContext.getResources().getBoolean( 2191 com.android.internal.R.bool.config_enableWallpaperService) 2192 && !mService.mOnlyCore; 2193 boolean haveKeyguard = true; 2194 final int count = mWindows.size(); 2195 for (int i = 0; i < count; i++) { 2196 final WindowState w = mWindows.get(i); 2197 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { 2198 return true; 2199 } 2200 if (w.isDrawnLw()) { 2201 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { 2202 haveBootMsg = true; 2203 } else if (w.mAttrs.type == TYPE_APPLICATION 2204 || w.mAttrs.type == TYPE_DRAWN_APPLICATION) { 2205 haveApp = true; 2206 } else if (w.mAttrs.type == TYPE_WALLPAPER) { 2207 haveWallpaper = true; 2208 } else if (w.mAttrs.type == TYPE_STATUS_BAR) { 2209 haveKeyguard = mService.mPolicy.isKeyguardDrawnLw(); 2210 } 2211 } 2212 } 2213 2214 if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, 2215 "******** booted=" + mService.mSystemBooted 2216 + " msg=" + mService.mShowingBootMessages 2217 + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp 2218 + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled 2219 + " haveKeyguard=" + haveKeyguard); 2220 2221 // If we are turning on the screen to show the boot message, don't do it until the boot 2222 // message is actually displayed. 2223 if (!mService.mSystemBooted && !haveBootMsg) { 2224 return true; 2225 } 2226 2227 // If we are turning on the screen after the boot is completed normally, don't do so until 2228 // we have the application and wallpaper. 2229 if (mService.mSystemBooted && ((!haveApp && !haveKeyguard) || 2230 (wallpaperEnabled && !haveWallpaper))) { 2231 return true; 2232 } 2233 2234 return false; 2235 } 2236 2237 void updateWindowsForAnimator(WindowAnimator animator) { 2238 final WallpaperController wallpaperController = mWallpaperController; 2239 for (int i = mWindows.size() - 1; i >= 0; i--) { 2240 WindowState win = mWindows.get(i); 2241 WindowStateAnimator winAnimator = win.mWinAnimator; 2242 if (winAnimator.hasSurface()) { 2243 final boolean wasAnimating = winAnimator.mWasAnimating; 2244 final boolean nowAnimating = winAnimator.stepAnimationLocked(animator.mCurrentTime); 2245 winAnimator.mWasAnimating = nowAnimating; 2246 animator.orAnimating(nowAnimating); 2247 2248 if (DEBUG_WALLPAPER) Slog.v(TAG, 2249 win + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating); 2250 2251 if (wasAnimating && !winAnimator.mAnimating 2252 && wallpaperController.isWallpaperTarget(win)) { 2253 animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 2254 pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2255 if (DEBUG_LAYOUT_REPEATS) { 2256 mService.mWindowPlacerLocked.debugLayoutRepeats( 2257 "updateWindowsAndWallpaperLocked 2", pendingLayoutChanges); 2258 } 2259 } 2260 } 2261 2262 final AppWindowToken atoken = win.mAppToken; 2263 if (winAnimator.mDrawState == READY_TO_SHOW) { 2264 if (atoken == null || atoken.allDrawn) { 2265 if (win.performShowLocked()) { 2266 pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 2267 if (DEBUG_LAYOUT_REPEATS) { 2268 mService.mWindowPlacerLocked.debugLayoutRepeats( 2269 "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges); 2270 } 2271 } 2272 } 2273 } 2274 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator; 2275 if (appAnimator != null && appAnimator.thumbnail != null) { 2276 if (appAnimator.thumbnailTransactionSeq != animator.mAnimTransactionSequence) { 2277 appAnimator.thumbnailTransactionSeq = animator.mAnimTransactionSequence; 2278 appAnimator.thumbnailLayer = 0; 2279 } 2280 if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) { 2281 appAnimator.thumbnailLayer = winAnimator.mAnimLayer; 2282 } 2283 } 2284 } // end forall windows 2285 } 2286 2287 void updateWallpaperForAnimator(WindowAnimator animator) { 2288 resetAnimationBackgroundAnimator(); 2289 2290 final WindowList windows = mWindows; 2291 WindowState detachedWallpaper = null; 2292 2293 for (int i = windows.size() - 1; i >= 0; i--) { 2294 final WindowState win = windows.get(i); 2295 final WindowStateAnimator winAnimator = win.mWinAnimator; 2296 if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) { 2297 continue; 2298 } 2299 2300 final int flags = win.mAttrs.flags; 2301 2302 // If this window is animating, make a note that we have an animating window and take 2303 // care of a request to run a detached wallpaper animation. 2304 if (winAnimator.mAnimating) { 2305 if (winAnimator.mAnimation != null) { 2306 if ((flags & FLAG_SHOW_WALLPAPER) != 0 2307 && winAnimator.mAnimation.getDetachWallpaper()) { 2308 detachedWallpaper = win; 2309 } 2310 final int color = winAnimator.mAnimation.getBackgroundColor(); 2311 if (color != 0) { 2312 final TaskStack stack = win.getStack(); 2313 if (stack != null) { 2314 stack.setAnimationBackground(winAnimator, color); 2315 } 2316 } 2317 } 2318 animator.setAnimating(true); 2319 } 2320 2321 // If this window's app token is running a detached wallpaper animation, make a note so 2322 // we can ensure the wallpaper is displayed behind it. 2323 final AppWindowAnimator appAnimator = winAnimator.mAppAnimator; 2324 if (appAnimator != null && appAnimator.animation != null 2325 && appAnimator.animating) { 2326 if ((flags & FLAG_SHOW_WALLPAPER) != 0 2327 && appAnimator.animation.getDetachWallpaper()) { 2328 detachedWallpaper = win; 2329 } 2330 2331 final int color = appAnimator.animation.getBackgroundColor(); 2332 if (color != 0) { 2333 final TaskStack stack = win.getStack(); 2334 if (stack != null) { 2335 stack.setAnimationBackground(winAnimator, color); 2336 } 2337 } 2338 } 2339 } // end forall windows 2340 2341 if (animator.mWindowDetachedWallpaper != detachedWallpaper) { 2342 if (DEBUG_WALLPAPER) Slog.v(TAG, "Detached wallpaper changed from " 2343 + animator.mWindowDetachedWallpaper + " to " + detachedWallpaper); 2344 animator.mWindowDetachedWallpaper = detachedWallpaper; 2345 animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; 2346 } 2347 } 2348 2349 void prepareWindowSurfaces() { 2350 final int count = mWindows.size(); 2351 for (int j = 0; j < count; j++) { 2352 mWindows.get(j).mWinAnimator.prepareSurfaceLocked(true); 2353 } 2354 } 2355 2356 boolean inputMethodClientHasFocus(IInputMethodClient client) { 2357 // The focus for the client is the window immediately below where we would place the input 2358 // method window. 2359 int idx = findDesiredInputMethodWindowIndex(false); 2360 if (idx <= 0) { 2361 return false; 2362 } 2363 2364 WindowState imFocus = mWindows.get(idx - 1); 2365 if (DEBUG_INPUT_METHOD) { 2366 Slog.i(TAG_WM, "Desired input method target: " + imFocus); 2367 Slog.i(TAG_WM, "Current focus: " + mService.mCurrentFocus); 2368 Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus); 2369 } 2370 2371 if (imFocus == null) { 2372 return false; 2373 } 2374 2375 // This may be a starting window, in which case we still want to count it as okay. 2376 if (imFocus.mAttrs.type == TYPE_APPLICATION_STARTING && imFocus.mAppToken != null) { 2377 // The client has definitely started, so it really should have a window in this app 2378 // token. Let's look for it. 2379 final WindowState w = imFocus.mAppToken.getFirstNonStartingWindow(); 2380 if (w != null) { 2381 if (DEBUG_INPUT_METHOD) Slog.i(TAG_WM, "Switching to real app window: " + w); 2382 imFocus = w; 2383 } 2384 } 2385 2386 final IInputMethodClient imeClient = imFocus.mSession.mClient; 2387 2388 if (DEBUG_INPUT_METHOD) { 2389 Slog.i(TAG_WM, "IM target client: " + imeClient); 2390 if (imeClient != null) { 2391 Slog.i(TAG_WM, "IM target client binder: " + imeClient.asBinder()); 2392 Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder()); 2393 } 2394 } 2395 2396 return imeClient != null && imeClient.asBinder() == client.asBinder(); 2397 } 2398 2399 boolean hasSecureWindowOnScreen() { 2400 for (int i = mWindows.size() - 1; i >= 0; --i) { 2401 final WindowState ws = mWindows.get(i); 2402 if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) { 2403 return true; 2404 } 2405 } 2406 return false; 2407 } 2408 2409 void updateSystemUiVisibility(int visibility, int globalDiff) { 2410 for (int i = mWindows.size() - 1; i >= 0; --i) { 2411 final WindowState ws = mWindows.get(i); 2412 try { 2413 int curValue = ws.mSystemUiVisibility; 2414 int diff = (curValue ^ visibility) & globalDiff; 2415 int newValue = (curValue & ~diff) | (visibility & diff); 2416 if (newValue != curValue) { 2417 ws.mSeq++; 2418 ws.mSystemUiVisibility = newValue; 2419 } 2420 if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) { 2421 ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq, 2422 visibility, newValue, diff); 2423 } 2424 } catch (RemoteException e) { 2425 // so sorry 2426 } 2427 } 2428 } 2429 2430 void onWindowFreezeTimeout() { 2431 Slog.w(TAG_WM, "Window freeze timeout expired."); 2432 mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT; 2433 for (int i = mWindows.size() - 1; i >= 0; --i) { 2434 final WindowState w = mWindows.get(i); 2435 if (!w.mOrientationChanging) { 2436 continue; 2437 } 2438 w.mOrientationChanging = false; 2439 w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime() 2440 - mService.mDisplayFreezeTime); 2441 Slog.w(TAG_WM, "Force clearing orientation change: " + w); 2442 } 2443 mService.mWindowPlacerLocked.performSurfacePlacement(); 2444 } 2445 2446 void waitForAllWindowsDrawn() { 2447 final WindowManagerPolicy policy = mService.mPolicy; 2448 for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) { 2449 final WindowState win = mWindows.get(winNdx); 2450 final boolean keyguard = policy.isKeyguardHostWindow(win.mAttrs); 2451 if (win.isVisibleLw() && (win.mAppToken != null || keyguard)) { 2452 win.mWinAnimator.mDrawState = DRAW_PENDING; 2453 // Force add to mResizingWindows. 2454 win.mLastContentInsets.set(-1, -1, -1, -1); 2455 mService.mWaitingForDrawn.add(win); 2456 } 2457 } 2458 } 2459 2460 ReadOnlyWindowList getReadOnlyWindowList() { 2461 return mWindows.getReadOnly(); 2462 } 2463 2464 void getWindows(WindowList output) { 2465 output.addAll(mWindows); 2466 } 2467 2468 // TODO: Super crazy long method that should be broken down... 2469 boolean applySurfaceChangesTransaction(boolean recoveringMemory) { 2470 2471 boolean focusDisplayed = false; 2472 boolean displayHasContent = false; 2473 float preferredRefreshRate = 0; 2474 int preferredModeId = 0; 2475 2476 2477 final int dw = mDisplayInfo.logicalWidth; 2478 final int dh = mDisplayInfo.logicalHeight; 2479 final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked; 2480 2481 mTmpUpdateAllDrawn.clear(); 2482 2483 int repeats = 0; 2484 do { 2485 repeats++; 2486 if (repeats > 6) { 2487 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 2488 clearLayoutNeeded(); 2489 break; 2490 } 2491 2492 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner", 2493 pendingLayoutChanges); 2494 2495 // TODO(multi-display): For now adjusting wallpaper only on primary display to avoid 2496 // the wallpaper window jumping across displays. 2497 // Remove check for default display when there will be support for multiple wallpaper 2498 // targets (on different displays). 2499 if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) { 2500 adjustWallpaperWindows(); 2501 } 2502 2503 if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) { 2504 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 2505 if (mService.updateOrientationFromAppTokensLocked(true, mDisplayId)) { 2506 setLayoutNeeded(); 2507 mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget(); 2508 } 2509 } 2510 2511 if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) { 2512 setLayoutNeeded(); 2513 } 2514 2515 // FIRST LOOP: Perform a layout, if needed. 2516 if (repeats < LAYOUT_REPEAT_THRESHOLD) { 2517 performLayout(repeats == 1, false /* updateInputWindows */); 2518 } else { 2519 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 2520 } 2521 2522 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating. 2523 pendingLayoutChanges = 0; 2524 2525 if (isDefaultDisplay) { 2526 mService.mPolicy.beginPostLayoutPolicyLw(dw, dh); 2527 for (int i = mWindows.size() - 1; i >= 0; i--) { 2528 final WindowState w = mWindows.get(i); 2529 mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(), 2530 mService.mInputMethodTarget); 2531 } 2532 pendingLayoutChanges |= mService.mPolicy.finishPostLayoutPolicyLw(); 2533 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats( 2534 "after finishPostLayoutPolicyLw", pendingLayoutChanges); 2535 } 2536 } while (pendingLayoutChanges != 0); 2537 2538 RootWindowContainer root = mService.mRoot; 2539 boolean obscured = false; 2540 boolean syswin = false; 2541 resetDimming(); 2542 2543 // Only used if default window 2544 final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty(); 2545 2546 for (int i = mWindows.size() - 1; i >= 0; i--) { 2547 final WindowState w = mWindows.get(i); 2548 final Task task = w.getTask(); 2549 final boolean obscuredChanged = w.mObscured != obscured; 2550 2551 // Update effect. 2552 w.mObscured = obscured; 2553 if (!obscured) { 2554 final boolean isDisplayed = w.isDisplayedLw(); 2555 2556 if (isDisplayed && w.isObscuringFullscreen(mDisplayInfo)) { 2557 // This window completely covers everything behind it, so we want to leave all 2558 // of them as undimmed (for performance reasons). 2559 root.mObscuringWindow = w; 2560 obscured = true; 2561 } 2562 2563 displayHasContent |= root.handleNotObscuredLocked(w, obscured, syswin); 2564 2565 if (w.mHasSurface && isDisplayed) { 2566 final int type = w.mAttrs.type; 2567 if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR 2568 || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 2569 syswin = true; 2570 } 2571 if (preferredRefreshRate == 0 && w.mAttrs.preferredRefreshRate != 0) { 2572 preferredRefreshRate = w.mAttrs.preferredRefreshRate; 2573 } 2574 if (preferredModeId == 0 && w.mAttrs.preferredDisplayModeId != 0) { 2575 preferredModeId = w.mAttrs.preferredDisplayModeId; 2576 } 2577 } 2578 } 2579 2580 w.applyDimLayerIfNeeded(); 2581 2582 if (isDefaultDisplay && obscuredChanged && w.isVisibleLw() 2583 && mWallpaperController.isWallpaperTarget(w)) { 2584 // This is the wallpaper target and its obscured state changed... make sure the 2585 // current wallpaper's visibility has been updated accordingly. 2586 mWallpaperController.updateWallpaperVisibility(); 2587 } 2588 2589 w.handleWindowMovedIfNeeded(); 2590 2591 final WindowStateAnimator winAnimator = w.mWinAnimator; 2592 2593 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 2594 w.mContentChanged = false; 2595 2596 // Moved from updateWindowsAndWallpaperLocked(). 2597 if (w.mHasSurface) { 2598 // Take care of the window being ready to display. 2599 final boolean committed = winAnimator.commitFinishDrawingLocked(); 2600 if (isDefaultDisplay && committed) { 2601 if (w.mAttrs.type == TYPE_DREAM) { 2602 // HACK: When a dream is shown, it may at that point hide the lock screen. 2603 // So we need to redo the layout to let the phone window manager make this 2604 // happen. 2605 pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT; 2606 if (DEBUG_LAYOUT_REPEATS) { 2607 surfacePlacer.debugLayoutRepeats( 2608 "dream and commitFinishDrawingLocked true", 2609 pendingLayoutChanges); 2610 } 2611 } 2612 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 2613 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, 2614 "First draw done in potential wallpaper target " + w); 2615 root.mWallpaperMayChange = true; 2616 pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2617 if (DEBUG_LAYOUT_REPEATS) { 2618 surfacePlacer.debugLayoutRepeats( 2619 "wallpaper and commitFinishDrawingLocked true", 2620 pendingLayoutChanges); 2621 } 2622 } 2623 } 2624 if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) { 2625 // Updates the shown frame before we set up the surface. This is needed 2626 // because the resizing could change the top-left position (in addition to 2627 // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to 2628 // position the surface. 2629 // 2630 // If an animation is being started, we can't call this method because the 2631 // animation hasn't processed its initial transformation yet, but in general 2632 // we do want to update the position if the window is animating. 2633 winAnimator.computeShownFrameLocked(); 2634 } 2635 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 2636 } 2637 2638 final AppWindowToken atoken = w.mAppToken; 2639 if (atoken != null) { 2640 final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w); 2641 if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) { 2642 mTmpUpdateAllDrawn.add(atoken); 2643 } 2644 } 2645 2646 if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus 2647 && w.isDisplayedLw()) { 2648 focusDisplayed = true; 2649 } 2650 2651 w.updateResizingWindowIfNeeded(); 2652 } 2653 2654 mService.mDisplayManagerInternal.setDisplayProperties(mDisplayId, 2655 displayHasContent, 2656 preferredRefreshRate, 2657 preferredModeId, 2658 true /* inTraversal, must call performTraversalInTrans... below */); 2659 2660 stopDimmingIfNeeded(); 2661 2662 while (!mTmpUpdateAllDrawn.isEmpty()) { 2663 final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast(); 2664 // See if any windows have been drawn, so they (and others associated with them) 2665 // can now be shown. 2666 atoken.updateAllDrawn(this); 2667 } 2668 2669 return focusDisplayed; 2670 } 2671 2672 void performLayout(boolean initial, boolean updateInputWindows) { 2673 if (!isLayoutNeeded()) { 2674 return; 2675 } 2676 clearLayoutNeeded(); 2677 2678 final int dw = mDisplayInfo.logicalWidth; 2679 final int dh = mDisplayInfo.logicalHeight; 2680 2681 int i; 2682 2683 if (DEBUG_LAYOUT) { 2684 Slog.v(TAG, "-------------------------------------"); 2685 Slog.v(TAG, "performLayout: needed=" + isLayoutNeeded() + " dw=" + dw + " dh=" + dh); 2686 } 2687 2688 mService.mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mService.mRotation, 2689 getConfiguration().uiMode); 2690 if (isDefaultDisplay) { 2691 // Not needed on non-default displays. 2692 mService.mSystemDecorLayer = mService.mPolicy.getSystemDecorLayerLw(); 2693 mService.mScreenRect.set(0, 0, dw, dh); 2694 } 2695 2696 mService.mPolicy.getContentRectLw(mContentRect); 2697 2698 int seq = mService.mLayoutSeq + 1; 2699 if (seq < 0) seq = 0; 2700 mService.mLayoutSeq = seq; 2701 2702 boolean behindDream = false; 2703 2704 // First perform layout of any root windows (not attached to another window). 2705 int topAttached = -1; 2706 for (i = mWindows.size() - 1; i >= 0; i--) { 2707 final WindowState win = mWindows.get(i); 2708 2709 // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid 2710 // wasting time and funky changes while a window is animating away. 2711 final boolean gone = (behindDream && mService.mPolicy.canBeHiddenByKeyguardLw(win)) 2712 || win.isGoneForLayoutLw(); 2713 2714 if (DEBUG_LAYOUT && !win.mLayoutAttached) { 2715 Slog.v(TAG, "1ST PASS " + win + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame 2716 + " mLayoutAttached=" + win.mLayoutAttached 2717 + " screen changed=" + win.isConfigChanged()); 2718 final AppWindowToken atoken = win.mAppToken; 2719 if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + win.mViewVisibility 2720 + " mRelayoutCalled=" + win.mRelayoutCalled + " hidden=" + win.mToken.hidden 2721 + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested) 2722 + " parentHidden=" + win.isParentWindowHidden()); 2723 else Slog.v(TAG, " VIS: mViewVisibility=" + win.mViewVisibility 2724 + " mRelayoutCalled=" + win.mRelayoutCalled + " hidden=" + win.mToken.hidden 2725 + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested) 2726 + " parentHidden=" + win.isParentWindowHidden()); 2727 } 2728 2729 // If this view is GONE, then skip it -- keep the current frame, and let the caller know 2730 // so they can ignore it if they want. (We do the normal layout for INVISIBLE windows, 2731 // since that means "perform layout as normal, just don't display"). 2732 if (!gone || !win.mHaveFrame || win.mLayoutNeeded 2733 || ((win.isConfigChanged() || win.setReportResizeHints()) 2734 && !win.isGoneForLayoutLw() && 2735 ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || 2736 (win.mHasSurface && win.mAppToken != null && 2737 win.mAppToken.layoutConfigChanges)))) { 2738 if (!win.mLayoutAttached) { 2739 if (initial) { 2740 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 2741 win.mContentChanged = false; 2742 } 2743 if (win.mAttrs.type == TYPE_DREAM) { 2744 // Don't layout windows behind a dream, so that if it does stuff like hide 2745 // the status bar we won't get a bad transition when it goes away. 2746 behindDream = true; 2747 } 2748 win.mLayoutNeeded = false; 2749 win.prelayout(); 2750 mService.mPolicy.layoutWindowLw(win, null); 2751 win.mLayoutSeq = seq; 2752 2753 // Window frames may have changed. Update dim layer with the new bounds. 2754 final Task task = win.getTask(); 2755 if (task != null) { 2756 mDimLayerController.updateDimLayer(task); 2757 } 2758 2759 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + win.mFrame 2760 + " mContainingFrame=" + win.mContainingFrame 2761 + " mDisplayFrame=" + win.mDisplayFrame); 2762 } else { 2763 if (topAttached < 0) topAttached = i; 2764 } 2765 } 2766 } 2767 2768 boolean attachedBehindDream = false; 2769 2770 // Now perform layout of attached windows, which usually depend on the position of the 2771 // window they are attached to. XXX does not deal with windows that are attached to windows 2772 // that are themselves attached. 2773 for (i = topAttached; i >= 0; i--) { 2774 final WindowState win = mWindows.get(i); 2775 2776 if (win.mLayoutAttached) { 2777 if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win + " mHaveFrame=" + win.mHaveFrame 2778 + " mViewVisibility=" + win.mViewVisibility 2779 + " mRelayoutCalled=" + win.mRelayoutCalled); 2780 // If this view is GONE, then skip it -- keep the current frame, and let the caller 2781 // know so they can ignore it if they want. (We do the normal layout for INVISIBLE 2782 // windows, since that means "perform layout as normal, just don't display"). 2783 if (attachedBehindDream && mService.mPolicy.canBeHiddenByKeyguardLw(win)) { 2784 continue; 2785 } 2786 if ((win.mViewVisibility != GONE && win.mRelayoutCalled) || !win.mHaveFrame 2787 || win.mLayoutNeeded) { 2788 if (initial) { 2789 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); 2790 win.mContentChanged = false; 2791 } 2792 win.mLayoutNeeded = false; 2793 win.prelayout(); 2794 mService.mPolicy.layoutWindowLw(win, win.getParentWindow()); 2795 win.mLayoutSeq = seq; 2796 if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + win.mFrame 2797 + " mContainingFrame=" + win.mContainingFrame 2798 + " mDisplayFrame=" + win.mDisplayFrame); 2799 } 2800 } else if (win.mAttrs.type == TYPE_DREAM) { 2801 // Don't layout windows behind a dream, so that if it does stuff like hide the 2802 // status bar we won't get a bad transition when it goes away. 2803 attachedBehindDream = behindDream; 2804 } 2805 } 2806 2807 // Window frames may have changed. Tell the input dispatcher about it. 2808 mService.mInputMonitor.layoutInputConsumers(dw, dh); 2809 mService.mInputMonitor.setUpdateInputWindowsNeededLw(); 2810 if (updateInputWindows) { 2811 mService.mInputMonitor.updateInputWindowsLw(false /*force*/); 2812 } 2813 2814 mService.mPolicy.finishLayoutLw(); 2815 mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER); 2816 } 2817 2818 /** 2819 * Takes a snapshot of the display. In landscape mode this grabs the whole screen. 2820 * In portrait mode, it grabs the full screenshot. 2821 * 2822 * @param width the width of the target bitmap 2823 * @param height the height of the target bitmap 2824 * @param includeFullDisplay true if the screen should not be cropped before capture 2825 * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1 2826 * @param config of the output bitmap 2827 * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot 2828 */ 2829 Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height, 2830 boolean includeFullDisplay, float frameScale, Bitmap.Config config, 2831 boolean wallpaperOnly) { 2832 int dw = mDisplayInfo.logicalWidth; 2833 int dh = mDisplayInfo.logicalHeight; 2834 if (dw == 0 || dh == 0) { 2835 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken 2836 + ": returning null. logical widthxheight=" + dw + "x" + dh); 2837 return null; 2838 } 2839 2840 Bitmap bm = null; 2841 2842 int maxLayer = 0; 2843 final Rect frame = new Rect(); 2844 final Rect stackBounds = new Rect(); 2845 2846 boolean screenshotReady; 2847 int minLayer; 2848 if (appToken == null && !wallpaperOnly) { 2849 screenshotReady = true; 2850 minLayer = 0; 2851 } else { 2852 screenshotReady = false; 2853 minLayer = Integer.MAX_VALUE; 2854 } 2855 2856 WindowState appWin = null; 2857 2858 boolean includeImeInScreenshot; 2859 synchronized(mService.mWindowMap) { 2860 final AppWindowToken imeTargetAppToken = mService.mInputMethodTarget != null 2861 ? mService.mInputMethodTarget.mAppToken : null; 2862 // We only include the Ime in the screenshot if the app we are screenshoting is the IME 2863 // target and isn't in multi-window mode. We don't screenshot the IME in multi-window 2864 // mode because the frame of the IME might not overlap with that of the app. 2865 // E.g. IME target app at the top in split-screen mode and the IME at the bottom 2866 // overlapping with the bottom app. 2867 includeImeInScreenshot = imeTargetAppToken != null 2868 && imeTargetAppToken.appToken != null 2869 && imeTargetAppToken.appToken.asBinder() == appToken 2870 && !mService.mInputMethodTarget.isInMultiWindowMode(); 2871 } 2872 2873 final int aboveAppLayer = (mService.mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1) 2874 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; 2875 2876 synchronized(mService.mWindowMap) { 2877 // Figure out the part of the screen that is actually the app. 2878 appWin = null; 2879 for (int i = mWindows.size() - 1; i >= 0; i--) { 2880 final WindowState ws = mWindows.get(i); 2881 if (!ws.mHasSurface) { 2882 continue; 2883 } 2884 if (ws.mLayer >= aboveAppLayer) { 2885 continue; 2886 } 2887 if (wallpaperOnly && !ws.mIsWallpaper) { 2888 continue; 2889 } 2890 if (ws.mIsImWindow) { 2891 if (!includeImeInScreenshot) { 2892 continue; 2893 } 2894 } else if (ws.mIsWallpaper) { 2895 // If this is the wallpaper layer and we're only looking for the wallpaper layer 2896 // then the target window state is this one. 2897 if (wallpaperOnly) { 2898 appWin = ws; 2899 } 2900 2901 if (appWin == null) { 2902 // We have not ran across the target window yet, so it is probably behind 2903 // the wallpaper. This can happen when the keyguard is up and all windows 2904 // are moved behind the wallpaper. We don't want to include the wallpaper 2905 // layer in the screenshot as it will cover-up the layer of the target 2906 // window. 2907 continue; 2908 } 2909 // Fall through. The target window is in front of the wallpaper. For this 2910 // case we want to include the wallpaper layer in the screenshot because 2911 // the target window might have some transparent areas. 2912 } else if (appToken != null) { 2913 if (ws.mAppToken == null || ws.mAppToken.token != appToken) { 2914 // This app window is of no interest if it is not associated with the 2915 // screenshot app. 2916 continue; 2917 } 2918 appWin = ws; 2919 } 2920 2921 // Include this window. 2922 2923 final WindowStateAnimator winAnim = ws.mWinAnimator; 2924 int layer = winAnim.mSurfaceController.getLayer(); 2925 if (maxLayer < layer) { 2926 maxLayer = layer; 2927 } 2928 if (minLayer > layer) { 2929 minLayer = layer; 2930 } 2931 2932 // Don't include wallpaper in bounds calculation 2933 if (!includeFullDisplay && !ws.mIsWallpaper) { 2934 final Rect wf = ws.mFrame; 2935 final Rect cr = ws.mContentInsets; 2936 int left = wf.left + cr.left; 2937 int top = wf.top + cr.top; 2938 int right = wf.right - cr.right; 2939 int bottom = wf.bottom - cr.bottom; 2940 frame.union(left, top, right, bottom); 2941 ws.getVisibleBounds(stackBounds); 2942 if (!Rect.intersects(frame, stackBounds)) { 2943 // Set frame empty if there's no intersection. 2944 frame.setEmpty(); 2945 } 2946 } 2947 2948 final boolean foundTargetWs = 2949 (ws.mAppToken != null && ws.mAppToken.token == appToken) 2950 || (appWin != null && wallpaperOnly); 2951 if (foundTargetWs && ws.isDisplayedLw() && winAnim.getShown()) { 2952 screenshotReady = true; 2953 } 2954 2955 if (ws.isObscuringFullscreen(mDisplayInfo)){ 2956 break; 2957 } 2958 } 2959 2960 if (appToken != null && appWin == null) { 2961 // Can't find a window to snapshot. 2962 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, 2963 "Screenshot: Couldn't find a surface matching " + appToken); 2964 return null; 2965 } 2966 2967 if (!screenshotReady) { 2968 Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken + 2969 " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" + 2970 appWin.mWinAnimator.mDrawState))); 2971 return null; 2972 } 2973 2974 // Screenshot is ready to be taken. Everything from here below will continue 2975 // through the bottom of the loop and return a value. We only stay in the loop 2976 // because we don't want to release the mWindowMap lock until the screenshot is 2977 // taken. 2978 2979 if (maxLayer == 0) { 2980 if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken 2981 + ": returning null maxLayer=" + maxLayer); 2982 return null; 2983 } 2984 2985 if (!includeFullDisplay) { 2986 // Constrain frame to the screen size. 2987 if (!frame.intersect(0, 0, dw, dh)) { 2988 frame.setEmpty(); 2989 } 2990 } else { 2991 // Caller just wants entire display. 2992 frame.set(0, 0, dw, dh); 2993 } 2994 if (frame.isEmpty()) { 2995 return null; 2996 } 2997 2998 if (width < 0) { 2999 width = (int) (frame.width() * frameScale); 3000 } 3001 if (height < 0) { 3002 height = (int) (frame.height() * frameScale); 3003 } 3004 3005 // Tell surface flinger what part of the image to crop. Take the top 3006 // right part of the application, and crop the larger dimension to fit. 3007 Rect crop = new Rect(frame); 3008 if (width / (float) frame.width() < height / (float) frame.height()) { 3009 int cropWidth = (int)((float)width / (float)height * frame.height()); 3010 crop.right = crop.left + cropWidth; 3011 } else { 3012 int cropHeight = (int)((float)height / (float)width * frame.width()); 3013 crop.bottom = crop.top + cropHeight; 3014 } 3015 3016 // The screenshot API does not apply the current screen rotation. 3017 int rot = mDisplay.getRotation(); 3018 3019 if (rot == ROTATION_90 || rot == ROTATION_270) { 3020 rot = (rot == ROTATION_90) ? ROTATION_270 : ROTATION_90; 3021 } 3022 3023 // Surfaceflinger is not aware of orientation, so convert our logical 3024 // crop to surfaceflinger's portrait orientation. 3025 convertCropForSurfaceFlinger(crop, rot, dw, dh); 3026 3027 if (DEBUG_SCREENSHOT) { 3028 Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " 3029 + maxLayer + " appToken=" + appToken); 3030 for (int i = 0; i < mWindows.size(); i++) { 3031 final WindowState win = mWindows.get(i); 3032 final WindowSurfaceController controller = win.mWinAnimator.mSurfaceController; 3033 Slog.i(TAG_WM, win + ": " + win.mLayer 3034 + " animLayer=" + win.mWinAnimator.mAnimLayer 3035 + " surfaceLayer=" + ((controller == null) 3036 ? "null" : controller.getLayer())); 3037 } 3038 } 3039 3040 final ScreenRotationAnimation screenRotationAnimation = 3041 mService.mAnimator.getScreenRotationAnimationLocked(DEFAULT_DISPLAY); 3042 final boolean inRotation = screenRotationAnimation != null && 3043 screenRotationAnimation.isAnimating(); 3044 if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM, 3045 "Taking screenshot while rotating"); 3046 3047 // We force pending transactions to flush before taking 3048 // the screenshot by pushing an empty synchronous transaction. 3049 SurfaceControl.openTransaction(); 3050 SurfaceControl.closeTransactionSync(); 3051 3052 bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer, 3053 inRotation, rot); 3054 if (bm == null) { 3055 Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh 3056 + ") to layer " + maxLayer); 3057 return null; 3058 } 3059 } 3060 3061 if (DEBUG_SCREENSHOT) { 3062 // TEST IF IT's ALL BLACK 3063 int[] buffer = new int[bm.getWidth() * bm.getHeight()]; 3064 bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); 3065 boolean allBlack = true; 3066 final int firstColor = buffer[0]; 3067 for (int i = 0; i < buffer.length; i++) { 3068 if (buffer[i] != firstColor) { 3069 allBlack = false; 3070 break; 3071 } 3072 } 3073 if (allBlack) { 3074 Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" + 3075 Integer.toHexString(firstColor) + ")! mSurfaceLayer=" + 3076 (appWin != null ? 3077 appWin.mWinAnimator.mSurfaceController.getLayer() : "null") + 3078 " minLayer=" + minLayer + " maxLayer=" + maxLayer); 3079 } 3080 } 3081 3082 // Create a copy of the screenshot that is immutable and backed in ashmem. 3083 // This greatly reduces the overhead of passing the bitmap between processes. 3084 Bitmap ret = bm.createAshmemBitmap(config); 3085 bm.recycle(); 3086 return ret; 3087 } 3088 3089 // TODO: Can this use createRotationMatrix()? 3090 private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) { 3091 if (rot == Surface.ROTATION_90) { 3092 final int tmp = crop.top; 3093 crop.top = dw - crop.right; 3094 crop.right = crop.bottom; 3095 crop.bottom = dw - crop.left; 3096 crop.left = tmp; 3097 } else if (rot == Surface.ROTATION_180) { 3098 int tmp = crop.top; 3099 crop.top = dh - crop.bottom; 3100 crop.bottom = dh - tmp; 3101 tmp = crop.right; 3102 crop.right = dw - crop.left; 3103 crop.left = dw - tmp; 3104 } else if (rot == Surface.ROTATION_270) { 3105 final int tmp = crop.top; 3106 crop.top = crop.left; 3107 crop.left = dh - crop.bottom; 3108 crop.bottom = crop.right; 3109 crop.right = dh - tmp; 3110 } 3111 } 3112 3113 void onSeamlessRotationTimeout() { 3114 boolean layoutNeeded = false; 3115 for (int i = mWindows.size() - 1; i >= 0; i--) { 3116 final WindowState w = mWindows.get(i); 3117 if (!w.mSeamlesslyRotated) { 3118 continue; 3119 } 3120 layoutNeeded = true; 3121 w.setDisplayLayoutNeeded(); 3122 mService.markForSeamlessRotation(w, false); 3123 } 3124 3125 if (layoutNeeded) { 3126 mService.mWindowPlacerLocked.performSurfacePlacement(); 3127 } 3128 } 3129 3130 static final class GetWindowOnDisplaySearchResult { 3131 boolean reachedToken; 3132 WindowState foundWindow; 3133 3134 void reset() { 3135 reachedToken = false; 3136 foundWindow = null; 3137 } 3138 } 3139 3140 static final class TaskForResizePointSearchResult { 3141 boolean searchDone; 3142 Task taskForResize; 3143 3144 void reset() { 3145 searchDone = false; 3146 taskForResize = null; 3147 } 3148 } 3149 3150 /** 3151 * Base class for any direct child window container of {@link #DisplayContent} need to inherit 3152 * from. This is mainly a pass through class that allows {@link #DisplayContent} to have 3153 * homogeneous children type which is currently required by sub-classes of 3154 * {@link WindowContainer} class. 3155 */ 3156 static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> { 3157 3158 int size() { 3159 return mChildren.size(); 3160 } 3161 3162 E get(int index) { 3163 return mChildren.get(index); 3164 } 3165 3166 @Override 3167 boolean fillsParent() { 3168 return true; 3169 } 3170 3171 @Override 3172 boolean isVisible() { 3173 return true; 3174 } 3175 } 3176 3177 /** 3178 * Window container class that contains all containers on this display relating to Apps. 3179 * I.e Activities. 3180 */ 3181 private final class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> { 3182 3183 /** 3184 * Adds the stack to this container. 3185 * @see WindowManagerService#addStackToDisplay(int, int, boolean) 3186 */ 3187 void addStackToDisplay(TaskStack stack, boolean onTop) { 3188 if (stack.mStackId == HOME_STACK_ID) { 3189 if (mHomeStack != null) { 3190 throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first."); 3191 } 3192 mHomeStack = stack; 3193 } 3194 addChild(stack, onTop); 3195 stack.onDisplayChanged(DisplayContent.this); 3196 } 3197 3198 /** Removes the stack from its container and prepare for changing the parent. */ 3199 void removeStackFromDisplay(TaskStack stack) { 3200 removeChild(stack); 3201 stack.onRemovedFromDisplay(); 3202 // TODO: remove when window list will be gone. 3203 // Manually remove records from window list and tap excluded windows list. 3204 for (int i = mWindows.size() - 1; i >= 0; --i) { 3205 final WindowState windowState = mWindows.get(i); 3206 if (stack == windowState.getStack()) { 3207 mWindows.remove(i); 3208 mTapExcludedWindows.remove(windowState); 3209 } 3210 } 3211 } 3212 3213 void moveStack(TaskStack stack, boolean toTop) { 3214 if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) { 3215 // This stack is always-on-top silly... 3216 Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + stack + " to bottom"); 3217 return; 3218 } 3219 3220 if (!mChildren.contains(stack)) { 3221 Slog.wtf(TAG_WM, "moving stack that was not added: " + stack, new Throwable()); 3222 } 3223 removeChild(stack); 3224 addChild(stack, toTop); 3225 } 3226 3227 private void addChild(TaskStack stack, boolean toTop) { 3228 int addIndex = toTop ? mChildren.size() : 0; 3229 3230 if (toTop 3231 && mService.isStackVisibleLocked(PINNED_STACK_ID) 3232 && stack.mStackId != PINNED_STACK_ID) { 3233 // The pinned stack is always the top most stack (always-on-top) when it is visible. 3234 // So, stack is moved just below the pinned stack. 3235 addIndex--; 3236 TaskStack topStack = mChildren.get(addIndex); 3237 if (topStack.mStackId != PINNED_STACK_ID) { 3238 throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren); 3239 } 3240 } 3241 addChild(stack, addIndex); 3242 setLayoutNeeded(); 3243 } 3244 3245 @Override 3246 int getOrientation() { 3247 if (mService.isStackVisibleLocked(DOCKED_STACK_ID) 3248 || mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) { 3249 // Apps and their containers are not allowed to specify an orientation while the 3250 // docked or freeform stack is visible...except for the home stack/task if the 3251 // docked stack is minimized and it actually set something. 3252 if (mHomeStack != null && mHomeStack.isVisible() 3253 && mDividerControllerLocked.isMinimizedDock()) { 3254 final int orientation = mHomeStack.getOrientation(); 3255 if (orientation != SCREEN_ORIENTATION_UNSET) { 3256 return orientation; 3257 } 3258 } 3259 return SCREEN_ORIENTATION_UNSPECIFIED; 3260 } 3261 3262 final int orientation = super.getOrientation(); 3263 if (orientation != SCREEN_ORIENTATION_UNSET 3264 && orientation != SCREEN_ORIENTATION_BEHIND) { 3265 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 3266 "App is requesting an orientation, return " + orientation); 3267 return orientation; 3268 } 3269 3270 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, 3271 "No app is requesting an orientation, return " + mService.mLastOrientation); 3272 // The next app has not been requested to be visible, so we keep the current orientation 3273 // to prevent freezing/unfreezing the display too early. 3274 return mService.mLastOrientation; 3275 } 3276 } 3277 3278 /** 3279 * Window container class that contains all containers on this display that are not related to 3280 * Apps. E.g. status bar. 3281 */ 3282 private final class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> { 3283 /** 3284 * Compares two child window tokens returns -1 if the first is lesser than the second in 3285 * terms of z-order and 1 otherwise. 3286 */ 3287 final Comparator<WindowToken> mWindowComparator = (token1, token2) -> 3288 // Tokens with higher base layer are z-ordered on-top. 3289 mService.mPolicy.windowTypeToLayerLw(token1.windowType) 3290 < mService.mPolicy.windowTypeToLayerLw(token2.windowType) ? -1 : 1; 3291 3292 private final String mName; 3293 NonAppWindowContainers(String name) { 3294 mName = name; 3295 } 3296 3297 void addChild(WindowToken token) { 3298 addChild(token, mWindowComparator); 3299 } 3300 3301 @Override 3302 String getName() { 3303 return mName; 3304 } 3305 } 3306} 3307