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