RootWindowContainer.java revision 412754816d2b8e83f0f5f860b13f09f53d2da05f
1/* 2 * Copyright (C) 2016 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 android.app.AppOpsManager; 20import android.content.res.Configuration; 21import android.graphics.Rect; 22import android.hardware.power.V1_0.PowerHint; 23import android.os.Binder; 24import android.os.Debug; 25import android.os.IBinder; 26import android.os.ParcelFileDescriptor; 27import android.os.PowerManager; 28import android.os.RemoteException; 29import android.os.SystemClock; 30import android.os.UserHandle; 31import android.provider.Settings; 32import android.util.EventLog; 33import android.util.Slog; 34import android.util.SparseIntArray; 35import android.view.Display; 36import android.view.DisplayInfo; 37import android.view.InputChannel; 38import android.view.WindowManager; 39import com.android.internal.util.ArrayUtils; 40import com.android.server.EventLogTags; 41import com.android.server.input.InputWindowHandle; 42 43import java.io.FileDescriptor; 44import java.io.PrintWriter; 45import java.util.ArrayList; 46import java.util.HashMap; 47import java.util.LinkedList; 48 49import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; 50import static android.app.ActivityManager.StackId.PINNED_STACK_ID; 51import static android.view.Display.DEFAULT_DISPLAY; 52import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION; 53import static android.view.WindowManager.INPUT_CONSUMER_PIP; 54import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER; 55import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; 56import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 57import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 58import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE; 59import static android.view.WindowManager.LayoutParams.TYPE_DREAM; 60import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; 61import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; 62import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; 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 android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 68import static com.android.server.wm.AppTransition.TRANSIT_UNSET; 69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS; 71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; 72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; 73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON; 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_POWER; 78import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; 79import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT; 80import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 81import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT; 82import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE; 83import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; 84import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC; 85import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; 86import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON; 87import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 88import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 89import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS; 90import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION; 91import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD; 92import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; 93import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES; 94import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; 95import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE; 96import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT; 97import static com.android.server.wm.WindowManagerService.logSurface; 98import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED; 99import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE; 100import static com.android.server.wm.WindowSurfacePlacer.SET_TURN_ON_SCREEN; 101import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION; 102import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING; 103import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE; 104 105/** Root {@link WindowContainer} for the device. */ 106// TODO: Several methods in here are accessing children of this container's children through various 107// references (WindowList I am looking at you :/). See if we can delegate instead. 108class RootWindowContainer extends WindowContainer<DisplayContent> { 109 private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM; 110 111 WindowManagerService mService; 112 113 private boolean mWallpaperForceHidingChanged = false; 114 private Object mLastWindowFreezeSource = null; 115 private Session mHoldScreen = null; 116 private float mScreenBrightness = -1; 117 private float mButtonBrightness = -1; 118 private long mUserActivityTimeout = -1; 119 private boolean mUpdateRotation = false; 120 private boolean mObscured = false; 121 private boolean mSyswin = false; 122 // Set to true when the display contains content to show the user. 123 // When false, the display manager may choose to mirror or blank the display. 124 private boolean mDisplayHasContent = false; 125 private float mPreferredRefreshRate = 0; 126 private int mPreferredModeId = 0; 127 // Following variables are for debugging screen wakelock only. 128 // Last window that requires screen wakelock 129 WindowState mHoldScreenWindow = null; 130 // Last window that obscures all windows below 131 WindowState mObscuringWindow = null; 132 // Only set while traversing the default display based on its content. 133 // Affects the behavior of mirroring on secondary displays. 134 private boolean mObscureApplicationContentOnSecondaryDisplays = false; 135 136 private boolean mSustainedPerformanceModeEnabled = false; 137 private boolean mSustainedPerformanceModeCurrent = false; 138 139 boolean mWallpaperMayChange = false; 140 // During an orientation change, we track whether all windows have rendered 141 // at the new orientation, and this will be false from changing orientation until that occurs. 142 // For seamless rotation cases this always stays true, as the windows complete their orientation 143 // changes 1 by 1 without disturbing global state. 144 boolean mOrientationChangeComplete = true; 145 boolean mWallpaperActionPending = false; 146 147 private final ArrayList<Integer> mChangedStackList = new ArrayList(); 148 149 private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList(); 150 151 private final ArrayList<WindowToken> mTmpTokensList = new ArrayList(); 152 153 // Collection of binder tokens mapped to their window type we are allowed to create window 154 // tokens for but that are not current attached to any display. We need to track this here 155 // because a binder token can be added through {@link WindowManagerService#addWindowToken}, 156 // but we don't know what display windows for the token will be added to until 157 // {@link WindowManagerService#addWindow} is called. 158 private final HashMap<IBinder, Integer> mUnattachedBinderTokens = new HashMap(); 159 160 // State for the RemoteSurfaceTrace system used in testing. If this is enabled SurfaceControl 161 // instances will be replaced with an instance that writes a binary representation of all 162 // commands to mSurfaceTraceFd. 163 boolean mSurfaceTraceEnabled; 164 ParcelFileDescriptor mSurfaceTraceFd; 165 RemoteEventTrace mRemoteEventTrace; 166 167 RootWindowContainer(WindowManagerService service) { 168 mService = service; 169 } 170 171 WindowState computeFocusedWindow() { 172 final int count = mChildren.size(); 173 for (int i = 0; i < count; i++) { 174 final DisplayContent dc = mChildren.get(i); 175 final WindowState win = dc.findFocusedWindow(); 176 if (win != null) { 177 return win; 178 } 179 } 180 return null; 181 } 182 183 /** 184 * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if 185 * there is a Display for the displayId. 186 * 187 * @param displayId The display the caller is interested in. 188 * @return The DisplayContent associated with displayId or null if there is no Display for it. 189 */ 190 DisplayContent getDisplayContentOrCreate(int displayId) { 191 DisplayContent dc = getDisplayContent(displayId); 192 193 if (dc == null) { 194 final Display display = mService.mDisplayManager.getDisplay(displayId); 195 if (display != null) { 196 dc = createDisplayContent(display); 197 } 198 } 199 return dc; 200 } 201 202 DisplayContent getDisplayContent(int displayId) { 203 for (int i = mChildren.size() - 1; i >= 0; --i) { 204 final DisplayContent current = mChildren.get(i); 205 if (current.getDisplayId() == displayId) { 206 return current; 207 } 208 } 209 return null; 210 } 211 212 private DisplayContent createDisplayContent(final Display display) { 213 final DisplayContent dc = new DisplayContent(display, mService); 214 final int displayId = display.getDisplayId(); 215 216 if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display); 217 addChild(dc, null); 218 219 final DisplayInfo displayInfo = dc.getDisplayInfo(); 220 final Rect rect = new Rect(); 221 mService.mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect); 222 displayInfo.overscanLeft = rect.left; 223 displayInfo.overscanTop = rect.top; 224 displayInfo.overscanRight = rect.right; 225 displayInfo.overscanBottom = rect.bottom; 226 if (mService.mDisplayManagerInternal != null) { 227 mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( 228 displayId, displayInfo); 229 mService.configureDisplayPolicyLocked(dc); 230 231 // TODO(multi-display): Create an input channel for each display with touch capability. 232 if (displayId == Display.DEFAULT_DISPLAY) { 233 dc.mTapDetector = new TaskTapPointerEventListener( 234 mService, dc); 235 mService.registerPointerEventListener(dc.mTapDetector); 236 mService.registerPointerEventListener(mService.mMousePositionTracker); 237 } 238 } 239 240 return dc; 241 } 242 243 /** Adds the input stack id to the input display id and returns the bounds of the added stack.*/ 244 Rect addStackToDisplay(int stackId, int displayId, boolean onTop) { 245 final DisplayContent dc = getDisplayContent(displayId); 246 if (dc == null) { 247 Slog.w(TAG_WM, "addStackToDisplay: Trying to add stackId=" + stackId 248 + " to unknown displayId=" + displayId + " callers=" + Debug.getCallers(6)); 249 return null; 250 } 251 252 boolean attachedToDisplay = false; 253 TaskStack stack = mService.mStackIdToStack.get(stackId); 254 if (stack == null) { 255 if (DEBUG_STACK) Slog.d(TAG_WM, "attachStack: stackId=" + stackId); 256 257 stack = dc.getStackById(stackId); 258 if (stack != null) { 259 // It's already attached to the display...clear mDeferRemoval and move stack to 260 // appropriate z-order on display as needed. 261 stack.mDeferRemoval = false; 262 dc.moveStack(stack, onTop); 263 attachedToDisplay = true; 264 } else { 265 stack = new TaskStack(mService, stackId); 266 } 267 268 mService.mStackIdToStack.put(stackId, stack); 269 if (stackId == DOCKED_STACK_ID) { 270 mService.getDefaultDisplayContentLocked().mDividerControllerLocked 271 .notifyDockedStackExistsChanged(true); 272 } 273 } 274 275 if (!attachedToDisplay) { 276 dc.attachStack(stack, onTop); 277 } 278 279 if (stack.getRawFullscreen()) { 280 return null; 281 } 282 final Rect bounds = new Rect(); 283 stack.getRawBounds(bounds); 284 return bounds; 285 } 286 287 boolean isLayoutNeeded() { 288 final int numDisplays = mChildren.size(); 289 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 290 final DisplayContent displayContent = mChildren.get(displayNdx); 291 if (displayContent.isLayoutNeeded()) { 292 return true; 293 } 294 } 295 return false; 296 } 297 298 void getWindows(WindowList output) { 299 final int count = mChildren.size(); 300 for (int i = 0; i < count; ++i) { 301 final DisplayContent dc = mChildren.get(i); 302 output.addAll(dc.getWindowList()); 303 } 304 } 305 306 void getWindows(WindowList output, boolean visibleOnly, boolean appsOnly) { 307 final int numDisplays = mChildren.size(); 308 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 309 final WindowList windowList = mChildren.get(displayNdx).getWindowList(); 310 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 311 final WindowState w = windowList.get(winNdx); 312 if ((!visibleOnly || w.mWinAnimator.getShown()) 313 && (!appsOnly || w.mAppToken != null)) { 314 output.add(w); 315 } 316 } 317 } 318 } 319 320 void getWindowsByName(WindowList output, String name) { 321 int objectId = 0; 322 // See if this is an object ID. 323 try { 324 objectId = Integer.parseInt(name, 16); 325 name = null; 326 } catch (RuntimeException e) { 327 } 328 final int numDisplays = mChildren.size(); 329 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 330 final WindowList windowList = mChildren.get(displayNdx).getWindowList(); 331 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 332 final WindowState w = windowList.get(winNdx); 333 if (name != null) { 334 if (w.mAttrs.getTitle().toString().contains(name)) { 335 output.add(w); 336 } 337 } else if (System.identityHashCode(w) == objectId) { 338 output.add(w); 339 } 340 } 341 } 342 } 343 344 WindowState findWindow(int hashCode) { 345 final int numDisplays = mChildren.size(); 346 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 347 final WindowList windows = mChildren.get(displayNdx).getWindowList(); 348 final int numWindows = windows.size(); 349 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 350 final WindowState w = windows.get(winNdx); 351 if (System.identityHashCode(w) == hashCode) { 352 return w; 353 } 354 } 355 } 356 357 return null; 358 } 359 360 /** Return the window token associated with the input binder token on the input display */ 361 WindowToken getWindowToken(IBinder binder, DisplayContent dc) { 362 final WindowToken token = dc.getWindowToken(binder); 363 if (token != null) { 364 return token; 365 } 366 367 // There is no window token mapped to the binder on the display. Create and map a window 368 // token if it is currently allowed. 369 if (!mUnattachedBinderTokens.containsKey(binder)) { 370 return null; 371 } 372 373 final int type = mUnattachedBinderTokens.get(binder); 374 return new WindowToken(mService, binder, type, true, dc); 375 } 376 377 /** Returns all window tokens mapped to the input binder. */ 378 ArrayList<WindowToken> getWindowTokens(IBinder binder) { 379 mTmpTokensList.clear(); 380 for (int i = mChildren.size() - 1; i >= 0; --i) { 381 final DisplayContent dc = mChildren.get(i); 382 final WindowToken token = dc.getWindowToken(binder); 383 if (token != null) { 384 mTmpTokensList.add(token); 385 } 386 } 387 return mTmpTokensList; 388 } 389 390 /** 391 * Returns the app window token for the input binder if it exist in the system. 392 * NOTE: Only one AppWindowToken is allowed to exist in the system for a binder token, since 393 * AppWindowToken represents an activity which can only exist on one display. 394 */ 395 AppWindowToken getAppWindowToken(IBinder binder) { 396 for (int i = mChildren.size() - 1; i >= 0; --i) { 397 final DisplayContent dc = mChildren.get(i); 398 final AppWindowToken atoken = dc.getAppWindowToken(binder); 399 if (atoken != null) { 400 return atoken; 401 } 402 } 403 return null; 404 } 405 406 /** Returns the display object the input window token is currently mapped on. */ 407 DisplayContent getWindowTokenDisplay(WindowToken token) { 408 if (token == null) { 409 return null; 410 } 411 412 for (int i = mChildren.size() - 1; i >= 0; --i) { 413 final DisplayContent dc = mChildren.get(i); 414 final WindowToken current = dc.getWindowToken(token.token); 415 if (current == token) { 416 return dc; 417 } 418 } 419 420 return null; 421 } 422 423 void addWindowToken(IBinder binder, int type) { 424 if (mUnattachedBinderTokens.containsKey(binder)) { 425 Slog.w(TAG_WM, "addWindowToken: Attempted to add existing binder token: " + binder); 426 return; 427 } 428 429 final ArrayList<WindowToken> tokens = getWindowTokens(binder); 430 431 if (!tokens.isEmpty()) { 432 Slog.w(TAG_WM, "addWindowToken: Attempted to add binder token: " + binder 433 + " for already created window tokens: " + tokens); 434 return; 435 } 436 437 mUnattachedBinderTokens.put(binder, type); 438 439 // TODO(multi-display): By default we add this to the default display, but maybe we 440 // should provide an API for a token to be added to any display? 441 final WindowToken token = new WindowToken(mService, binder, type, true, 442 getDisplayContent(DEFAULT_DISPLAY)); 443 if (type == TYPE_WALLPAPER) { 444 mService.mWallpaperControllerLocked.addWallpaperToken(token); 445 } 446 } 447 448 ArrayList<WindowToken> removeWindowToken(IBinder binder) { 449 mUnattachedBinderTokens.remove(binder); 450 451 mTmpTokensList.clear(); 452 for (int i = mChildren.size() - 1; i >= 0; --i) { 453 final DisplayContent dc = mChildren.get(i); 454 final WindowToken token = dc.removeWindowToken(binder); 455 if (token != null) { 456 mTmpTokensList.add(token); 457 } 458 } 459 return mTmpTokensList; 460 } 461 462 /** 463 * Removed the mapping to the input binder for the system if it no longer as a window token 464 * associated with it on any display. 465 */ 466 void removeWindowTokenIfPossible(IBinder binder) { 467 for (int i = mChildren.size() - 1; i >= 0; --i) { 468 final DisplayContent dc = mChildren.get(i); 469 final WindowToken token = dc.getWindowToken(binder); 470 if (token != null) { 471 return; 472 } 473 } 474 475 mUnattachedBinderTokens.remove(binder); 476 } 477 478 void removeAppToken(IBinder binder) { 479 final ArrayList<WindowToken> removedTokens = removeWindowToken(binder); 480 if (removedTokens == null || removedTokens.isEmpty()) { 481 Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder); 482 return; 483 } 484 485 for (int i = removedTokens.size() - 1; i >= 0; --i) { 486 WindowToken wtoken = removedTokens.get(i); 487 AppWindowToken appToken = wtoken.asAppWindowToken(); 488 489 if (appToken == null) { 490 Slog.w(TAG_WM, 491 "Attempted to remove non-App token: " + binder + " wtoken=" + wtoken); 492 continue; 493 } 494 495 AppWindowToken startingToken = null; 496 497 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + appToken); 498 499 boolean delayed = appToken.setVisibility(null, false, TRANSIT_UNSET, true, 500 appToken.voiceInteraction); 501 502 mService.mOpeningApps.remove(appToken); 503 appToken.waitingToShow = false; 504 if (mService.mClosingApps.contains(appToken)) { 505 delayed = true; 506 } else if (mService.mAppTransition.isTransitionSet()) { 507 mService.mClosingApps.add(appToken); 508 delayed = true; 509 } 510 511 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + appToken 512 + " delayed=" + delayed 513 + " animation=" + appToken.mAppAnimator.animation 514 + " animating=" + appToken.mAppAnimator.animating); 515 516 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: " 517 + appToken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4)); 518 519 final TaskStack stack = appToken.mTask.mStack; 520 if (delayed && !appToken.isEmpty()) { 521 // set the token aside because it has an active animation to be finished 522 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, 523 "removeAppToken make exiting: " + appToken); 524 stack.mExitingAppTokens.add(appToken); 525 appToken.mIsExiting = true; 526 } else { 527 // Make sure there is no animation running on this token, so any windows associated 528 // with it will be removed as soon as their animations are complete 529 appToken.mAppAnimator.clearAnimation(); 530 appToken.mAppAnimator.animating = false; 531 appToken.removeIfPossible(); 532 } 533 534 appToken.removed = true; 535 if (appToken.startingData != null) { 536 startingToken = appToken; 537 } 538 appToken.stopFreezingScreen(true, true); 539 if (mService.mFocusedApp == appToken) { 540 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + appToken); 541 mService.mFocusedApp = null; 542 mService.updateFocusedWindowLocked( 543 UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 544 mService.mInputMonitor.setFocusedAppLw(null); 545 } 546 547 if (!delayed) { 548 appToken.updateReportedVisibilityLocked(); 549 } 550 551 // Will only remove if startingToken non null. 552 mService.scheduleRemoveStartingWindowLocked(startingToken); 553 } 554 } 555 556 // TODO: Users would have their own window containers under the display container? 557 void switchUser() { 558 final int count = mChildren.size(); 559 for (int i = 0; i < count; ++i) { 560 final DisplayContent dc = mChildren.get(i); 561 dc.switchUser(); 562 } 563 } 564 565 /** Set new config and return array of ids of stacks that were changed during update. */ 566 int[] setGlobalConfigurationIfNeeded(Configuration newConfiguration) { 567 final boolean configChanged = getConfiguration().diff(newConfiguration) != 0; 568 if (!configChanged) { 569 return null; 570 } 571 onConfigurationChanged(newConfiguration); 572 return updateStackBoundsAfterConfigChange(); 573 } 574 575 @Override 576 void onConfigurationChanged(Configuration newParentConfig) { 577 prepareFreezingTaskBounds(); 578 super.onConfigurationChanged(newParentConfig); 579 580 mService.mPolicy.onConfigurationChanged(); 581 } 582 583 /** 584 * Callback used to trigger bounds update after configuration change and get ids of stacks whose 585 * bounds were updated. 586 */ 587 private int[] updateStackBoundsAfterConfigChange() { 588 mChangedStackList.clear(); 589 590 final int numDisplays = mChildren.size(); 591 for (int i = 0; i < numDisplays; ++i) { 592 final DisplayContent dc = mChildren.get(i); 593 dc.updateStackBoundsAfterConfigChange(mChangedStackList); 594 } 595 596 return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList); 597 } 598 599 private void prepareFreezingTaskBounds() { 600 for (int i = mChildren.size() - 1; i >= 0; i--) { 601 mChildren.get(i).prepareFreezingTaskBounds(); 602 } 603 } 604 605 void setSecureSurfaceState(int userId, boolean disabled) { 606 for (int i = mChildren.size() - 1; i >= 0; --i) { 607 final WindowList windows = mChildren.get(i).getWindowList(); 608 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 609 final WindowState win = windows.get(winNdx); 610 if (win.mHasSurface && userId == UserHandle.getUserId(win.mOwnerUid)) { 611 win.mWinAnimator.setSecureLocked(disabled); 612 } 613 } 614 } 615 } 616 617 void updateAppOpsState() { 618 final int count = mChildren.size(); 619 for (int i = 0; i < count; ++i) { 620 final WindowList windows = mChildren.get(i).getWindowList(); 621 final int numWindows = windows.size(); 622 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 623 final WindowState win = windows.get(winNdx); 624 if (win.mAppOp == AppOpsManager.OP_NONE) { 625 continue; 626 } 627 final int mode = mService.mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(), 628 win.getOwningPackage()); 629 win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED || 630 mode == AppOpsManager.MODE_DEFAULT); 631 } 632 } 633 } 634 635 boolean canShowStrictModeViolation(int pid) { 636 final int count = mChildren.size(); 637 for (int i = 0; i < count; ++i) { 638 final WindowList windows = mChildren.get(i).getWindowList(); 639 final int numWindows = windows.size(); 640 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 641 final WindowState ws = windows.get(winNdx); 642 if (ws.mSession.mPid == pid && ws.isVisibleLw()) { 643 return true; 644 } 645 } 646 } 647 return false; 648 } 649 650 void closeSystemDialogs(String reason) { 651 final int count = mChildren.size(); 652 for (int i = 0; i < count; ++i) { 653 final WindowList windows = mChildren.get(i).getWindowList(); 654 final int numWindows = windows.size(); 655 for (int j = 0; j < numWindows; ++j) { 656 final WindowState w = windows.get(j); 657 if (w.mHasSurface) { 658 try { 659 w.mClient.closeSystemDialogs(reason); 660 } catch (RemoteException e) { 661 } 662 } 663 } 664 } 665 } 666 667 void removeReplacedWindows() { 668 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION removeReplacedWindows"); 669 mService.openSurfaceTransaction(); 670 try { 671 for (int i = mChildren.size() - 1; i >= 0; i--) { 672 DisplayContent dc = mChildren.get(i); 673 final WindowList windows = dc.getWindowList(); 674 for (int j = windows.size() - 1; j >= 0; j--) { 675 final WindowState win = windows.get(j); 676 final AppWindowToken aToken = win.mAppToken; 677 if (aToken != null) { 678 aToken.removeReplacedWindowIfNeeded(win); 679 } 680 } 681 } 682 } finally { 683 mService.closeSurfaceTransaction(); 684 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION removeReplacedWindows"); 685 } 686 } 687 688 boolean hasPendingLayoutChanges(WindowAnimator animator) { 689 boolean hasChanges = false; 690 691 final int count = mChildren.size(); 692 for (int i = 0; i < count; ++i) { 693 final DisplayContent dc = mChildren.get(i); 694 final int pendingChanges = animator.getPendingLayoutChanges(dc.getDisplayId()); 695 if ((pendingChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) { 696 animator.mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING; 697 } 698 if (pendingChanges != 0) { 699 hasChanges = true; 700 } 701 } 702 703 return hasChanges; 704 } 705 706 void updateInputWindows(InputMonitor inputMonitor, WindowState inputFocus, boolean inDrag) { 707 final InputConsumerImpl navInputConsumer = 708 mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_NAVIGATION); 709 final InputConsumerImpl pipInputConsumer = 710 mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_PIP); 711 final InputConsumerImpl wallpaperInputConsumer = 712 mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_WALLPAPER); 713 boolean addInputConsumerHandle = navInputConsumer != null; 714 boolean addPipInputConsumerHandle = pipInputConsumer != null; 715 boolean addWallpaperInputConsumerHandle = wallpaperInputConsumer != null; 716 final Rect pipTouchableBounds = addPipInputConsumerHandle ? new Rect() : null; 717 final WallpaperController wallpaperController = mService.mWallpaperControllerLocked; 718 boolean disableWallpaperTouchEvents = false; 719 720 final int count = mChildren.size(); 721 for (int i = 0; i < count; ++i) { 722 final DisplayContent dc = mChildren.get(i); 723 final WindowList windows = dc.getWindowList(); 724 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { 725 final WindowState child = windows.get(winNdx); 726 final InputChannel inputChannel = child.mInputChannel; 727 final InputWindowHandle inputWindowHandle = child.mInputWindowHandle; 728 if (inputChannel == null || inputWindowHandle == null || child.mRemoved 729 || child.isAdjustedForMinimizedDock()) { 730 // Skip this window because it cannot possibly receive input. 731 continue; 732 } 733 734 if (addPipInputConsumerHandle 735 && child.getStackId() == PINNED_STACK_ID 736 && inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer) { 737 // Update the bounds of the Pip input consumer to match the Pinned stack 738 child.getStack().getBounds(pipTouchableBounds); 739 pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds); 740 inputMonitor.addInputWindowHandle(pipInputConsumer.mWindowHandle); 741 addPipInputConsumerHandle = false; 742 } 743 744 if (addInputConsumerHandle 745 && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) { 746 inputMonitor.addInputWindowHandle(navInputConsumer.mWindowHandle); 747 addInputConsumerHandle = false; 748 } 749 750 if (addWallpaperInputConsumerHandle) { 751 if (child.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER && 752 child.isVisibleLw()) { 753 // Add the wallpaper input consumer above the first visible wallpaper. 754 inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle); 755 addWallpaperInputConsumerHandle = false; 756 } 757 } 758 759 final int flags = child.mAttrs.flags; 760 final int privateFlags = child.mAttrs.privateFlags; 761 final int type = child.mAttrs.type; 762 763 final boolean hasFocus = child == inputFocus; 764 final boolean isVisible = child.isVisibleLw(); 765 if ((privateFlags 766 & WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) 767 != 0) { 768 disableWallpaperTouchEvents = true; 769 } 770 final boolean hasWallpaper = wallpaperController.isWallpaperTarget(child) 771 && (privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD) == 0 772 && !disableWallpaperTouchEvents; 773 final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY); 774 775 // If there's a drag in progress and 'child' is a potential drop target, 776 // make sure it's been told about the drag 777 if (inDrag && isVisible && onDefaultDisplay) { 778 mService.mDragState.sendDragStartedIfNeededLw(child); 779 } 780 781 inputMonitor.addInputWindowHandle( 782 inputWindowHandle, child, flags, type, isVisible, hasFocus, hasWallpaper); 783 } 784 } 785 786 if (addWallpaperInputConsumerHandle) { 787 // No visible wallpaper found, add the wallpaper input consumer at the end. 788 inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle); 789 } 790 } 791 792 boolean reclaimSomeSurfaceMemory(WindowStateAnimator winAnimator, String operation, 793 boolean secure) { 794 final WindowSurfaceController surfaceController = winAnimator.mSurfaceController; 795 boolean leakedSurface = false; 796 boolean killedApps = false; 797 798 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), 799 winAnimator.mSession.mPid, operation); 800 801 final long callingIdentity = Binder.clearCallingIdentity(); 802 try { 803 // There was some problem... first, do a sanity check of the window list to make sure 804 // we haven't left any dangling surfaces around. 805 806 Slog.i(TAG_WM, "Out of memory for surface! Looking for leaks..."); 807 final int numDisplays = mChildren.size(); 808 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 809 final WindowList windows = mChildren.get(displayNdx).getWindowList(); 810 final int numWindows = windows.size(); 811 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 812 final WindowState ws = windows.get(winNdx); 813 final WindowStateAnimator wsa = ws.mWinAnimator; 814 if (wsa.mSurfaceController == null) { 815 continue; 816 } 817 if (!mService.mSessions.contains(wsa.mSession)) { 818 Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): " 819 + ws + " surface=" + wsa.mSurfaceController 820 + " token=" + ws.mToken 821 + " pid=" + ws.mSession.mPid 822 + " uid=" + ws.mSession.mUid); 823 wsa.destroySurface(); 824 mService.mForceRemoves.add(ws); 825 leakedSurface = true; 826 } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { 827 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): " 828 + ws + " surface=" + wsa.mSurfaceController 829 + " token=" + ws.mAppToken 830 + " saved=" + ws.hasSavedSurface()); 831 if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false); 832 wsa.destroySurface(); 833 leakedSurface = true; 834 } 835 } 836 } 837 838 if (!leakedSurface) { 839 Slog.w(TAG_WM, "No leaked surfaces; killing applications!"); 840 SparseIntArray pidCandidates = new SparseIntArray(); 841 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 842 final WindowList windows = mChildren.get(displayNdx).getWindowList(); 843 final int numWindows = windows.size(); 844 for (int winNdx = 0; winNdx < numWindows; ++winNdx) { 845 final WindowState ws = windows.get(winNdx); 846 if (mService.mForceRemoves.contains(ws)) { 847 continue; 848 } 849 WindowStateAnimator wsa = ws.mWinAnimator; 850 if (wsa.mSurfaceController != null) { 851 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 852 } 853 } 854 if (pidCandidates.size() > 0) { 855 int[] pids = new int[pidCandidates.size()]; 856 for (int i = 0; i < pids.length; i++) { 857 pids[i] = pidCandidates.keyAt(i); 858 } 859 try { 860 if (mService.mActivityManager.killPids(pids, "Free memory", secure)) { 861 killedApps = true; 862 } 863 } catch (RemoteException e) { 864 } 865 } 866 } 867 } 868 869 if (leakedSurface || killedApps) { 870 // We managed to reclaim some memory, so get rid of the trouble surface and ask the 871 // app to request another one. 872 Slog.w(TAG_WM, 873 "Looks like we have reclaimed some memory, clearing surface for retry."); 874 if (surfaceController != null) { 875 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, 876 "RECOVER DESTROY", false); 877 winAnimator.destroySurface(); 878 mService.scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken); 879 } 880 881 try { 882 winAnimator.mWin.mClient.dispatchGetNewSurface(); 883 } catch (RemoteException e) { 884 } 885 } 886 } finally { 887 Binder.restoreCallingIdentity(callingIdentity); 888 } 889 890 return leakedSurface || killedApps; 891 } 892 893 // "Something has changed! Let's make it correct now." 894 // TODO: Super crazy long method that should be broken down... 895 void performSurfacePlacement(boolean recoveringMemory) { 896 if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by " 897 + Debug.getCallers(3)); 898 899 int i; 900 boolean updateInputWindowsNeeded = false; 901 902 if (mService.mFocusMayChange) { 903 mService.mFocusMayChange = false; 904 updateInputWindowsNeeded = mService.updateFocusedWindowLocked( 905 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/); 906 } 907 908 // Initialize state of exiting tokens. 909 final int numDisplays = mChildren.size(); 910 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 911 final DisplayContent displayContent = mChildren.get(displayNdx); 912 for (i = displayContent.mExitingTokens.size() - 1; i >= 0; i--) { 913 displayContent.mExitingTokens.get(i).hasVisible = false; 914 } 915 } 916 917 for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 918 // Initialize state of exiting applications. 919 final AppTokenList exitingAppTokens = 920 mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 921 for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) { 922 exitingAppTokens.get(tokenNdx).hasVisible = false; 923 } 924 } 925 926 mHoldScreen = null; 927 mScreenBrightness = -1; 928 mButtonBrightness = -1; 929 mUserActivityTimeout = -1; 930 mObscureApplicationContentOnSecondaryDisplays = false; 931 mSustainedPerformanceModeCurrent = false; 932 mService.mTransactionSequence++; 933 934 // TODO(multi-display): 935 final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked(); 936 final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); 937 final int defaultDw = defaultInfo.logicalWidth; 938 final int defaultDh = defaultInfo.logicalHeight; 939 940 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 941 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); 942 mService.openSurfaceTransaction(); 943 try { 944 applySurfaceChangesTransaction(recoveringMemory, defaultDw, defaultDh); 945 } catch (RuntimeException e) { 946 Slog.wtf(TAG, "Unhandled exception in Window Manager", e); 947 } finally { 948 mService.closeSurfaceTransaction(); 949 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 950 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); 951 } 952 953 final WindowList defaultWindows = defaultDisplay.getWindowList(); 954 final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked; 955 956 // If we are ready to perform an app transition, check through all of the app tokens to be 957 // shown and see if they are ready to go. 958 if (mService.mAppTransition.isReady()) { 959 defaultDisplay.pendingLayoutChanges |= 960 surfacePlacer.handleAppTransitionReadyLocked(defaultWindows); 961 if (DEBUG_LAYOUT_REPEATS) 962 surfacePlacer.debugLayoutRepeats("after handleAppTransitionReadyLocked", 963 defaultDisplay.pendingLayoutChanges); 964 } 965 966 if (!mService.mAnimator.mAppWindowAnimating && mService.mAppTransition.isRunning()) { 967 // We have finished the animation of an app transition. To do this, we have delayed a 968 // lot of operations like showing and hiding apps, moving apps in Z-order, etc. The app 969 // token list reflects the correct Z-order, but the window list may now be out of sync 970 // with it. So here we will just rebuild the entire app window list. Fun! 971 defaultDisplay.pendingLayoutChanges |= 972 mService.handleAnimatingStoppedAndTransitionLocked(); 973 if (DEBUG_LAYOUT_REPEATS) 974 surfacePlacer.debugLayoutRepeats("after handleAnimStopAndXitionLock", 975 defaultDisplay.pendingLayoutChanges); 976 } 977 978 if (mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 979 && !mService.mAppTransition.isReady()) { 980 // At this point, there was a window with a wallpaper that was force hiding other 981 // windows behind it, but now it is going away. This may be simple -- just animate away 982 // the wallpaper and its window -- or it may be hard -- the wallpaper now needs to be 983 // shown behind something that was hidden. 984 defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT; 985 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats( 986 "after animateAwayWallpaperLocked", defaultDisplay.pendingLayoutChanges); 987 } 988 mWallpaperForceHidingChanged = false; 989 990 if (mWallpaperMayChange) { 991 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting"); 992 defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 993 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("WallpaperMayChange", 994 defaultDisplay.pendingLayoutChanges); 995 } 996 997 if (mService.mFocusMayChange) { 998 mService.mFocusMayChange = false; 999 if (mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 1000 false /*updateInputWindows*/)) { 1001 updateInputWindowsNeeded = true; 1002 defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; 1003 } 1004 } 1005 1006 if (isLayoutNeeded()) { 1007 defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT; 1008 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("mLayoutNeeded", 1009 defaultDisplay.pendingLayoutChanges); 1010 } 1011 1012 for (i = mService.mResizingWindows.size() - 1; i >= 0; i--) { 1013 WindowState win = mService.mResizingWindows.get(i); 1014 if (win.mAppFreezing) { 1015 // Don't remove this window until rotation has completed. 1016 continue; 1017 } 1018 // Discard the saved surface if window size is changed, it can't be reused. 1019 if (win.mAppToken != null) { 1020 win.mAppToken.destroySavedSurfaces(); 1021 } 1022 win.reportResized(); 1023 mService.mResizingWindows.remove(i); 1024 } 1025 1026 if (DEBUG_ORIENTATION && mService.mDisplayFrozen) Slog.v(TAG, 1027 "With display frozen, orientationChangeComplete=" + mOrientationChangeComplete); 1028 if (mOrientationChangeComplete) { 1029 if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) { 1030 mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE; 1031 mService.mLastFinishedFreezeSource = mLastWindowFreezeSource; 1032 mService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT); 1033 } 1034 mService.stopFreezingDisplayLocked(); 1035 } 1036 1037 // Destroy the surface of any windows that are no longer visible. 1038 boolean wallpaperDestroyed = false; 1039 i = mService.mDestroySurface.size(); 1040 if (i > 0) { 1041 do { 1042 i--; 1043 WindowState win = mService.mDestroySurface.get(i); 1044 win.mDestroying = false; 1045 if (mService.mInputMethodWindow == win) { 1046 mService.mInputMethodWindow = null; 1047 } 1048 if (mService.mWallpaperControllerLocked.isWallpaperTarget(win)) { 1049 wallpaperDestroyed = true; 1050 } 1051 win.destroyOrSaveSurface(); 1052 } while (i > 0); 1053 mService.mDestroySurface.clear(); 1054 } 1055 1056 // Time to remove any exiting tokens? 1057 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 1058 final DisplayContent displayContent = mChildren.get(displayNdx); 1059 ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens; 1060 for (i = exitingTokens.size() - 1; i >= 0; i--) { 1061 WindowToken token = exitingTokens.get(i); 1062 if (!token.hasVisible) { 1063 exitingTokens.remove(i); 1064 if (token.windowType == TYPE_WALLPAPER) { 1065 mService.mWallpaperControllerLocked.removeWallpaperToken(token); 1066 } 1067 } 1068 } 1069 } 1070 1071 // Time to remove any exiting applications? 1072 for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) { 1073 // Initialize state of exiting applications. 1074 final AppTokenList exitingAppTokens = 1075 mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens; 1076 for (i = exitingAppTokens.size() - 1; i >= 0; i--) { 1077 final AppWindowToken token = exitingAppTokens.get(i); 1078 if (!token.hasVisible && !mService.mClosingApps.contains(token) && 1079 (!token.mIsExiting || token.isEmpty())) { 1080 // Make sure there is no animation running on this token, so any windows 1081 // associated with it will be removed as soon as their animations are complete 1082 token.mAppAnimator.clearAnimation(); 1083 token.mAppAnimator.animating = false; 1084 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, 1085 "performLayout: App token exiting now removed" + token); 1086 token.removeIfPossible(); 1087 } 1088 } 1089 } 1090 1091 if (wallpaperDestroyed) { 1092 defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 1093 defaultDisplay.setLayoutNeeded(); 1094 } 1095 1096 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 1097 final DisplayContent displayContent = mChildren.get(displayNdx); 1098 if (displayContent.pendingLayoutChanges != 0) { 1099 displayContent.setLayoutNeeded(); 1100 } 1101 } 1102 1103 // Finally update all input windows now that the window changes have stabilized. 1104 mService.mInputMonitor.updateInputWindowsLw(true /*force*/); 1105 1106 mService.setHoldScreenLocked(mHoldScreen); 1107 if (!mService.mDisplayFrozen) { 1108 if (mScreenBrightness < 0 || mScreenBrightness > 1.0f) { 1109 mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1); 1110 } else { 1111 mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager( 1112 toBrightnessOverride(mScreenBrightness)); 1113 } 1114 if (mButtonBrightness < 0 || mButtonBrightness > 1.0f) { 1115 mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1); 1116 } else { 1117 mService.mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager( 1118 toBrightnessOverride(mButtonBrightness)); 1119 } 1120 mService.mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager( 1121 mUserActivityTimeout); 1122 } 1123 1124 if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) { 1125 mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent; 1126 mService.mPowerManagerInternal.powerHint( 1127 PowerHint.SUSTAINED_PERFORMANCE, 1128 (mSustainedPerformanceModeEnabled ? 1 : 0)); 1129 } 1130 1131 if (mService.mTurnOnScreen) { 1132 if (mService.mAllowTheaterModeWakeFromLayout 1133 || Settings.Global.getInt(mService.mContext.getContentResolver(), 1134 Settings.Global.THEATER_MODE_ON, 0) == 0) { 1135 if (DEBUG_VISIBILITY || DEBUG_POWER) { 1136 Slog.v(TAG, "Turning screen on after layout!"); 1137 } 1138 mService.mPowerManager.wakeUp(SystemClock.uptimeMillis(), 1139 "android.server.wm:TURN_ON"); 1140 } 1141 mService.mTurnOnScreen = false; 1142 } 1143 1144 if (mUpdateRotation) { 1145 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); 1146 if (mService.updateRotationUncheckedLocked(false)) { 1147 mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION); 1148 } else { 1149 mUpdateRotation = false; 1150 } 1151 } 1152 1153 if (mService.mWaitingForDrawnCallback != null || 1154 (mOrientationChangeComplete && !defaultDisplay.isLayoutNeeded() 1155 && !mUpdateRotation)) { 1156 mService.checkDrawnWindowsLocked(); 1157 } 1158 1159 final int N = mService.mPendingRemove.size(); 1160 if (N > 0) { 1161 if (mService.mPendingRemoveTmp.length < N) { 1162 mService.mPendingRemoveTmp = new WindowState[N+10]; 1163 } 1164 mService.mPendingRemove.toArray(mService.mPendingRemoveTmp); 1165 mService.mPendingRemove.clear(); 1166 DisplayContentList displayList = new DisplayContentList(); 1167 for (i = 0; i < N; i++) { 1168 final WindowState w = mService.mPendingRemoveTmp[i]; 1169 w.removeImmediately(); 1170 final DisplayContent displayContent = w.getDisplayContent(); 1171 if (displayContent != null && !displayList.contains(displayContent)) { 1172 displayList.add(displayContent); 1173 } 1174 } 1175 1176 for (DisplayContent displayContent : displayList) { 1177 mService.mLayersController.assignLayersLocked(displayContent.getWindowList()); 1178 displayContent.setLayoutNeeded(); 1179 } 1180 } 1181 1182 // Remove all deferred displays stacks, tasks, and activities. 1183 for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) { 1184 mChildren.get(displayNdx).checkCompleteDeferredRemoval(); 1185 } 1186 1187 if (updateInputWindowsNeeded) { 1188 mService.mInputMonitor.updateInputWindowsLw(false /*force*/); 1189 } 1190 mService.setFocusTaskRegionLocked(); 1191 1192 // Check to see if we are now in a state where the screen should 1193 // be enabled, because the window obscured flags have changed. 1194 mService.enableScreenIfNeededLocked(); 1195 1196 mService.scheduleAnimationLocked(); 1197 mService.mWindowPlacerLocked.destroyPendingSurfaces(); 1198 1199 if (DEBUG_WINDOW_TRACE) Slog.e(TAG, 1200 "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating()); 1201 } 1202 1203 // TODO: Super crazy long method that should be broken down... 1204 private void applySurfaceChangesTransaction(boolean recoveringMemory, int defaultDw, int defaultDh) { 1205 mHoldScreenWindow = null; 1206 mObscuringWindow = null; 1207 1208 if (mService.mWatermark != null) { 1209 mService.mWatermark.positionSurface(defaultDw, defaultDh); 1210 } 1211 if (mService.mStrictModeFlash != null) { 1212 mService.mStrictModeFlash.positionSurface(defaultDw, defaultDh); 1213 } 1214 if (mService.mCircularDisplayMask != null) { 1215 mService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mService.mRotation); 1216 } 1217 if (mService.mEmulatorDisplayOverlay != null) { 1218 mService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh, 1219 mService.mRotation); 1220 } 1221 1222 boolean focusDisplayed = false; 1223 1224 final int count = mChildren.size(); 1225 for (int j = 0; j < count; ++j) { 1226 final DisplayContent dc = mChildren.get(j); 1227 WindowList windows = dc.getWindowList(); 1228 DisplayInfo displayInfo = dc.getDisplayInfo(); 1229 final int displayId = dc.getDisplayId(); 1230 final int dw = displayInfo.logicalWidth; 1231 final int dh = displayInfo.logicalHeight; 1232 final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); 1233 final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked; 1234 1235 // Reset for each display. 1236 mDisplayHasContent = false; 1237 mPreferredRefreshRate = 0; 1238 mPreferredModeId = 0; 1239 mTmpUpdateAllDrawn.clear(); 1240 1241 int repeats = 0; 1242 do { 1243 repeats++; 1244 if (repeats > 6) { 1245 Slog.w(TAG, "Animation repeat aborted after too many iterations"); 1246 dc.clearLayoutNeeded(); 1247 break; 1248 } 1249 1250 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats( 1251 "On entry to LockedInner", dc.pendingLayoutChanges); 1252 1253 if ((dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0 1254 && mService.mWallpaperControllerLocked.adjustWallpaperWindows()) { 1255 mService.mLayersController.assignLayersLocked(windows); 1256 dc.setLayoutNeeded(); 1257 } 1258 1259 if (isDefaultDisplay 1260 && (dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) { 1261 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); 1262 if (mService.updateOrientationFromAppTokensLocked(true)) { 1263 dc.setLayoutNeeded(); 1264 mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION); 1265 } 1266 } 1267 1268 if ((dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) { 1269 dc.setLayoutNeeded(); 1270 } 1271 1272 // FIRST LOOP: Perform a layout, if needed. 1273 if (repeats < LAYOUT_REPEAT_THRESHOLD) { 1274 surfacePlacer.performLayoutLockedInner(dc, repeats == 1, 1275 false /* updateInputWindows */); 1276 } else { 1277 Slog.w(TAG, "Layout repeat skipped after too many iterations"); 1278 } 1279 1280 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think 1281 // it is animating. 1282 dc.pendingLayoutChanges = 0; 1283 1284 if (isDefaultDisplay) { 1285 mService.mPolicy.beginPostLayoutPolicyLw(dw, dh); 1286 for (int i = windows.size() - 1; i >= 0; i--) { 1287 WindowState w = windows.get(i); 1288 if (w.mHasSurface) { 1289 mService.mPolicy.applyPostLayoutPolicyLw( 1290 w, w.mAttrs, w.getParentWindow()); 1291 } 1292 } 1293 dc.pendingLayoutChanges |= 1294 mService.mPolicy.finishPostLayoutPolicyLw(); 1295 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats( 1296 "after finishPostLayoutPolicyLw", dc.pendingLayoutChanges); 1297 } 1298 } while (dc.pendingLayoutChanges != 0); 1299 1300 mObscured = false; 1301 mSyswin = false; 1302 dc.resetDimming(); 1303 1304 // Only used if default window 1305 final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty(); 1306 1307 for (int i = windows.size() - 1; i >= 0; i--) { 1308 WindowState w = windows.get(i); 1309 final Task task = w.getTask(); 1310 final boolean obscuredChanged = w.mObscured != mObscured; 1311 1312 // Update effect. 1313 w.mObscured = mObscured; 1314 if (!mObscured) { 1315 handleNotObscuredLocked(w, displayInfo); 1316 } 1317 1318 w.applyDimLayerIfNeeded(); 1319 1320 if (isDefaultDisplay && obscuredChanged && w.isVisibleLw() 1321 && mService.mWallpaperControllerLocked.isWallpaperTarget(w)) { 1322 // This is the wallpaper target and its obscured state changed... make sure the 1323 // current wallpaper's visibility has been updated accordingly. 1324 mService.mWallpaperControllerLocked.updateWallpaperVisibility(); 1325 } 1326 1327 w.handleWindowMovedIfNeeded(); 1328 1329 final WindowStateAnimator winAnimator = w.mWinAnimator; 1330 1331 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); 1332 w.mContentChanged = false; 1333 1334 // Moved from updateWindowsAndWallpaperLocked(). 1335 if (w.mHasSurface) { 1336 // Take care of the window being ready to display. 1337 final boolean committed = winAnimator.commitFinishDrawingLocked(); 1338 if (isDefaultDisplay && committed) { 1339 if (w.mAttrs.type == TYPE_DREAM) { 1340 // HACK: When a dream is shown, it may at that point hide the lock 1341 // screen. So we need to redo the layout to let the phone window manager 1342 // make this happen. 1343 dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT; 1344 if (DEBUG_LAYOUT_REPEATS) { 1345 surfacePlacer.debugLayoutRepeats( 1346 "dream and commitFinishDrawingLocked true", 1347 dc.pendingLayoutChanges); 1348 } 1349 } 1350 if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { 1351 if (DEBUG_WALLPAPER_LIGHT) 1352 Slog.v(TAG, "First draw done in potential wallpaper target " + w); 1353 mWallpaperMayChange = true; 1354 dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 1355 if (DEBUG_LAYOUT_REPEATS) { 1356 surfacePlacer.debugLayoutRepeats( 1357 "wallpaper and commitFinishDrawingLocked true", 1358 dc.pendingLayoutChanges); 1359 } 1360 } 1361 } 1362 if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) { 1363 // Updates the shown frame before we set up the surface. This is needed 1364 // because the resizing could change the top-left position (in addition to 1365 // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to 1366 // position the surface. 1367 // 1368 // If an animation is being started, we can't call this method because the 1369 // animation hasn't processed its initial transformation yet, but in general 1370 // we do want to update the position if the window is animating. 1371 winAnimator.computeShownFrameLocked(); 1372 } 1373 winAnimator.setSurfaceBoundariesLocked(recoveringMemory); 1374 } 1375 1376 final AppWindowToken atoken = w.mAppToken; 1377 if (atoken != null) { 1378 final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w); 1379 if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) { 1380 mTmpUpdateAllDrawn.add(atoken); 1381 } 1382 } 1383 1384 if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus 1385 && w.isDisplayedLw()) { 1386 focusDisplayed = true; 1387 } 1388 1389 w.updateResizingWindowIfNeeded(); 1390 } 1391 1392 mService.mDisplayManagerInternal.setDisplayProperties(displayId, 1393 mDisplayHasContent, 1394 mPreferredRefreshRate, 1395 mPreferredModeId, 1396 true /* inTraversal, must call performTraversalInTrans... below */); 1397 1398 dc.stopDimmingIfNeeded(); 1399 1400 while (!mTmpUpdateAllDrawn.isEmpty()) { 1401 final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast(); 1402 // See if any windows have been drawn, so they (and others associated with them) 1403 // can now be shown. 1404 atoken.updateAllDrawn(dc); 1405 } 1406 } 1407 1408 if (focusDisplayed) { 1409 mService.mH.sendEmptyMessage(REPORT_LOSING_FOCUS); 1410 } 1411 1412 // Give the display manager a chance to adjust properties 1413 // like display rotation if it needs to. 1414 mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); 1415 } 1416 1417 /** 1418 * @param w WindowState this method is applied to. 1419 * @param dispInfo info of the display that the window's obscuring state is checked against. 1420 */ 1421 private void handleNotObscuredLocked(final WindowState w, final DisplayInfo dispInfo) { 1422 final WindowManager.LayoutParams attrs = w.mAttrs; 1423 final int attrFlags = attrs.flags; 1424 final boolean canBeSeen = w.isDisplayedLw(); 1425 final int privateflags = attrs.privateFlags; 1426 1427 if (canBeSeen && w.isObscuringFullscreen(dispInfo)) { 1428 // This window completely covers everything behind it, 1429 // so we want to leave all of them as undimmed (for 1430 // performance reasons). 1431 if (!mObscured) { 1432 mObscuringWindow = w; 1433 } 1434 1435 mObscured = true; 1436 } 1437 1438 if (w.mHasSurface && canBeSeen) { 1439 if ((attrFlags & FLAG_KEEP_SCREEN_ON) != 0) { 1440 mHoldScreen = w.mSession; 1441 mHoldScreenWindow = w; 1442 } else if (DEBUG_KEEP_SCREEN_ON && w == mService.mLastWakeLockHoldingWindow) { 1443 Slog.d(TAG_KEEP_SCREEN_ON, "handleNotObscuredLocked: " + w + " was holding " 1444 + "screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by" 1445 + Debug.getCallers(10)); 1446 } 1447 if (!mSyswin && w.mAttrs.screenBrightness >= 0 && mScreenBrightness < 0) { 1448 mScreenBrightness = w.mAttrs.screenBrightness; 1449 } 1450 if (!mSyswin && w.mAttrs.buttonBrightness >= 0 && mButtonBrightness < 0) { 1451 mButtonBrightness = w.mAttrs.buttonBrightness; 1452 } 1453 if (!mSyswin && w.mAttrs.userActivityTimeout >= 0 && mUserActivityTimeout < 0) { 1454 mUserActivityTimeout = w.mAttrs.userActivityTimeout; 1455 } 1456 1457 final int type = attrs.type; 1458 if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR 1459 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 1460 mSyswin = true; 1461 } 1462 1463 // This function assumes that the contents of the default display are processed first 1464 // before secondary displays. 1465 final DisplayContent displayContent = w.getDisplayContent(); 1466 if (displayContent != null && displayContent.isDefaultDisplay) { 1467 // While a dream or keyguard is showing, obscure ordinary application content on 1468 // secondary displays (by forcibly enabling mirroring unless there is other content 1469 // we want to show) but still allow opaque keyguard dialogs to be shown. 1470 if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 1471 mObscureApplicationContentOnSecondaryDisplays = true; 1472 } 1473 mDisplayHasContent = true; 1474 } else if (displayContent != null && 1475 (!mObscureApplicationContentOnSecondaryDisplays 1476 || (mObscured && type == TYPE_KEYGUARD_DIALOG))) { 1477 // Allow full screen keyguard presentation dialogs to be seen. 1478 mDisplayHasContent = true; 1479 } 1480 if (mPreferredRefreshRate == 0 && w.mAttrs.preferredRefreshRate != 0) { 1481 mPreferredRefreshRate = w.mAttrs.preferredRefreshRate; 1482 } 1483 if (mPreferredModeId == 0 && w.mAttrs.preferredDisplayModeId != 0) { 1484 mPreferredModeId = w.mAttrs.preferredDisplayModeId; 1485 } 1486 if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) { 1487 mSustainedPerformanceModeCurrent = true; 1488 } 1489 } 1490 } 1491 1492 boolean copyAnimToLayoutParams() { 1493 boolean doRequest = false; 1494 1495 final int bulkUpdateParams = mService.mAnimator.mBulkUpdateParams; 1496 if ((bulkUpdateParams & SET_UPDATE_ROTATION) != 0) { 1497 mUpdateRotation = true; 1498 doRequest = true; 1499 } 1500 if ((bulkUpdateParams & SET_WALLPAPER_MAY_CHANGE) != 0) { 1501 mWallpaperMayChange = true; 1502 doRequest = true; 1503 } 1504 if ((bulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0) { 1505 mWallpaperForceHidingChanged = true; 1506 doRequest = true; 1507 } 1508 if ((bulkUpdateParams & SET_ORIENTATION_CHANGE_COMPLETE) == 0) { 1509 mOrientationChangeComplete = false; 1510 } else { 1511 mOrientationChangeComplete = true; 1512 mLastWindowFreezeSource = mService.mAnimator.mLastWindowFreezeSource; 1513 if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) { 1514 doRequest = true; 1515 } 1516 } 1517 if ((bulkUpdateParams & SET_TURN_ON_SCREEN) != 0) { 1518 mService.mTurnOnScreen = true; 1519 } 1520 if ((bulkUpdateParams & SET_WALLPAPER_ACTION_PENDING) != 0) { 1521 mWallpaperActionPending = true; 1522 } 1523 1524 return doRequest; 1525 } 1526 1527 private static int toBrightnessOverride(float value) { 1528 return (int)(value * PowerManager.BRIGHTNESS_ON); 1529 } 1530 1531 void enableSurfaceTrace(ParcelFileDescriptor pfd) { 1532 final FileDescriptor fd = pfd.getFileDescriptor(); 1533 if (mSurfaceTraceEnabled) { 1534 disableSurfaceTrace(); 1535 } 1536 mSurfaceTraceEnabled = true; 1537 mRemoteEventTrace = new RemoteEventTrace(mService, fd); 1538 mSurfaceTraceFd = pfd; 1539 for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) { 1540 final DisplayContent dc = mChildren.get(displayNdx); 1541 dc.enableSurfaceTrace(fd); 1542 } 1543 } 1544 1545 void disableSurfaceTrace() { 1546 mSurfaceTraceEnabled = false; 1547 mRemoteEventTrace = null; 1548 mSurfaceTraceFd = null; 1549 for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) { 1550 final DisplayContent dc = mChildren.get(displayNdx); 1551 dc.disableSurfaceTrace(); 1552 } 1553 } 1554 1555 void dumpDisplayContents(PrintWriter pw) { 1556 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 1557 if (mService.mDisplayReady) { 1558 final int count = mChildren.size(); 1559 for (int i = 0; i < count; ++i) { 1560 final DisplayContent displayContent = mChildren.get(i); 1561 displayContent.dump(" ", pw); 1562 } 1563 } else { 1564 pw.println(" NO DISPLAY"); 1565 } 1566 } 1567 1568 void dumpLayoutNeededDisplayIds(PrintWriter pw) { 1569 if (!isLayoutNeeded()) { 1570 return; 1571 } 1572 pw.print(" mLayoutNeeded on displays="); 1573 final int count = mChildren.size(); 1574 for (int displayNdx = 0; displayNdx < count; ++displayNdx) { 1575 final DisplayContent displayContent = mChildren.get(displayNdx); 1576 if (displayContent.isLayoutNeeded()) { 1577 pw.print(displayContent.getDisplayId()); 1578 } 1579 } 1580 pw.println(); 1581 } 1582 1583 void dumpWindowsNoHeader(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows) { 1584 final int numDisplays = mChildren.size(); 1585 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 1586 final WindowList windowList = mChildren.get(displayNdx).getWindowList(); 1587 for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { 1588 final WindowState w = windowList.get(winNdx); 1589 if (windows == null || windows.contains(w)) { 1590 pw.println(" Window #" + winNdx + " " + w + ":"); 1591 w.dump(pw, " ", dumpAll || windows != null); 1592 } 1593 } 1594 } 1595 } 1596 1597 void dumpTokens(PrintWriter pw, boolean dumpAll) { 1598 pw.println(" All tokens:"); 1599 for (int i = mChildren.size() - 1; i >= 0; --i) { 1600 mChildren.get(i).dumpTokens(pw, dumpAll); 1601 } 1602 } 1603 1604 @Override 1605 String getName() { 1606 return "ROOT"; 1607 } 1608} 1609