1 /* 2 * Copyright (C) 2011 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 17 package com.android.server.wm; 18 19 import static android.app.ActivityManager.StackId; 20 import static android.app.ActivityManager.StackId.PINNED_STACK_ID; 21 import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION; 22 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE; 23 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; 24 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; 25 import static android.view.Display.DEFAULT_DISPLAY; 26 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; 27 import static android.view.WindowManager.LayoutParams.FLAG_SECURE; 28 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; 29 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 30 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 31 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 32 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 33 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 34 import static com.android.server.wm.AppTransition.TRANSIT_UNSET; 35 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 36 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 37 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS; 38 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; 39 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; 40 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; 41 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW; 42 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE; 43 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT; 44 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 45 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT; 46 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 47 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 48 import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN; 49 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; 50 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; 51 import static com.android.server.wm.WindowManagerService.logWithStack; 52 53 import android.annotation.NonNull; 54 import android.app.Activity; 55 import android.content.res.Configuration; 56 import android.graphics.Rect; 57 import android.os.Binder; 58 import android.os.Debug; 59 import android.os.IBinder; 60 import android.os.SystemClock; 61 import android.util.Slog; 62 import android.view.IApplicationToken; 63 import android.view.SurfaceControl; 64 import android.view.WindowManager; 65 import android.view.WindowManager.LayoutParams; 66 import android.view.WindowManagerPolicy.StartingSurface; 67 68 import com.android.internal.util.ToBooleanFunction; 69 import com.android.server.input.InputApplicationHandle; 70 import com.android.server.wm.WindowManagerService.H; 71 72 import java.io.PrintWriter; 73 import java.util.ArrayDeque; 74 import java.util.ArrayList; 75 76 class AppTokenList extends ArrayList<AppWindowToken> { 77 } 78 79 /** 80 * Version of WindowToken that is specifically for a particular application (or 81 * really activity) that is displaying windows. 82 */ 83 class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener { 84 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM; 85 86 // Non-null only for application tokens. 87 final IApplicationToken appToken; 88 89 @NonNull final AppWindowAnimator mAppAnimator; 90 91 final boolean mVoiceInteraction; 92 93 /** @see WindowContainer#fillsParent() */ 94 private boolean mFillsParent; 95 boolean layoutConfigChanges; 96 boolean mShowForAllUsers; 97 int mTargetSdk; 98 99 // Flag set while reparenting to prevent actions normally triggered by an individual parent 100 // change. 101 private boolean mReparenting; 102 103 // True if we are current in the process of removing this app token from the display 104 private boolean mRemovingFromDisplay = false; 105 106 // The input dispatching timeout for this application token in nanoseconds. 107 long mInputDispatchingTimeoutNanos; 108 109 // These are used for determining when all windows associated with 110 // an activity have been drawn, so they can be made visible together 111 // at the same time. 112 // initialize so that it doesn't match mTransactionSequence which is an int. 113 private long mLastTransactionSequence = Long.MIN_VALUE; 114 private int mNumInterestingWindows; 115 private int mNumDrawnWindows; 116 boolean inPendingTransaction; 117 boolean allDrawn; 118 // Set to true when this app creates a surface while in the middle of an animation. In that 119 // case do not clear allDrawn until the animation completes. 120 boolean deferClearAllDrawn; 121 122 /** 123 * These are to track the app's real drawing status if there were no saved surfaces. 124 * @see #updateDrawnWindowStates 125 */ 126 boolean allDrawnExcludingSaved; 127 private int mNumInterestingWindowsExcludingSaved; 128 private int mNumDrawnWindowsExcludingSaved; 129 130 // Is this window's surface needed? This is almost like hidden, except 131 // it will sometimes be true a little earlier: when the token has 132 // been shown, but is still waiting for its app transition to execute 133 // before making its windows shown. 134 boolean hiddenRequested; 135 136 // Have we told the window clients to hide themselves? 137 private boolean mClientHidden; 138 139 // If true we will defer setting mClientHidden to true and reporting to the client that it is 140 // hidden. 141 boolean mDeferHidingClient; 142 143 // Last visibility state we reported to the app token. 144 boolean reportedVisible; 145 146 // Last drawn state we reported to the app token. 147 private boolean reportedDrawn; 148 149 // Set to true when the token has been removed from the window mgr. 150 boolean removed; 151 152 // Information about an application starting window if displayed. 153 StartingData startingData; 154 WindowState startingWindow; 155 StartingSurface startingSurface; 156 boolean startingDisplayed; 157 boolean startingMoved; 158 // True if the hidden state of this token was forced to false due to a transferred starting 159 // window. 160 private boolean mHiddenSetFromTransferredStartingWindow; 161 boolean firstWindowDrawn; 162 private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults = 163 new WindowState.UpdateReportedVisibilityResults(); 164 165 // Input application handle used by the input dispatcher. 166 final InputApplicationHandle mInputApplicationHandle; 167 168 // TODO: Have a WindowContainer state for tracking exiting/deferred removal. 169 boolean mIsExiting; 170 171 boolean mLaunchTaskBehind; 172 boolean mEnteringAnimation; 173 174 private boolean mAlwaysFocusable; 175 176 boolean mAppStopped; 177 int mRotationAnimationHint; 178 private int mPendingRelaunchCount; 179 180 private boolean mLastContainsShowWhenLockedWindow; 181 private boolean mLastContainsDismissKeyguardWindow; 182 183 // The bounds of this activity. Mainly used for aspect-ratio compatibility. 184 // TODO(b/36505427): Every level on WindowContainer now has bounds information, which directly 185 // affects the configuration. We should probably move this into that class. 186 private final Rect mBounds = new Rect(); 187 188 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>(); 189 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>(); 190 191 private boolean mDisablePreviewScreenshots; 192 193 Task mLastParent; 194 195 /** 196 * See {@link #canTurnScreenOn()} 197 */ 198 private boolean mCanTurnScreenOn = true; 199 AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint, int configChanges, boolean launchTaskBehind, boolean alwaysFocusable, AppWindowContainerController controller, Configuration overrideConfig, Rect bounds)200 AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction, 201 DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen, 202 boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint, 203 int configChanges, boolean launchTaskBehind, boolean alwaysFocusable, 204 AppWindowContainerController controller, Configuration overrideConfig, Rect bounds) { 205 this(service, token, voiceInteraction, dc, fullscreen, overrideConfig, bounds); 206 setController(controller); 207 mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos; 208 mShowForAllUsers = showForAllUsers; 209 mTargetSdk = targetSdk; 210 mOrientation = orientation; 211 layoutConfigChanges = (configChanges & (CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION)) != 0; 212 mLaunchTaskBehind = launchTaskBehind; 213 mAlwaysFocusable = alwaysFocusable; 214 mRotationAnimationHint = rotationAnimationHint; 215 216 // Application tokens start out hidden. 217 hidden = true; 218 hiddenRequested = true; 219 } 220 AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction, DisplayContent dc, boolean fillsParent, Configuration overrideConfig, Rect bounds)221 AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction, 222 DisplayContent dc, boolean fillsParent, Configuration overrideConfig, Rect bounds) { 223 super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc, 224 false /* ownerCanManageAppTokens */); 225 appToken = token; 226 mVoiceInteraction = voiceInteraction; 227 mFillsParent = fillsParent; 228 mInputApplicationHandle = new InputApplicationHandle(this); 229 mAppAnimator = new AppWindowAnimator(this, service); 230 if (overrideConfig != null) { 231 onOverrideConfigurationChanged(overrideConfig); 232 } 233 if (bounds != null) { 234 mBounds.set(bounds); 235 } 236 } 237 onOverrideConfigurationChanged(Configuration overrideConfiguration, Rect bounds)238 void onOverrideConfigurationChanged(Configuration overrideConfiguration, Rect bounds) { 239 onOverrideConfigurationChanged(overrideConfiguration); 240 if (mBounds.equals(bounds)) { 241 return; 242 } 243 // TODO(b/36505427): If bounds is in WC, then we can automatically call onResize() when set. 244 mBounds.set(bounds); 245 onResize(); 246 } 247 getBounds(Rect outBounds)248 void getBounds(Rect outBounds) { 249 outBounds.set(mBounds); 250 } 251 hasBounds()252 boolean hasBounds() { 253 return !mBounds.isEmpty(); 254 } 255 onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator)256 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) { 257 firstWindowDrawn = true; 258 259 // We now have a good window to show, remove dead placeholders 260 removeDeadWindows(); 261 262 if (startingWindow != null) { 263 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting " 264 + win.mToken + ": first real window is shown, no animation"); 265 // If this initial window is animating, stop it -- we will do an animation to reveal 266 // it from behind the starting window, so there is no need for it to also be doing its 267 // own stuff. 268 winAnimator.clearAnimation(); 269 if (getController() != null) { 270 getController().removeStartingWindow(); 271 } 272 } 273 updateReportedVisibilityLocked(); 274 } 275 updateReportedVisibilityLocked()276 void updateReportedVisibilityLocked() { 277 if (appToken == null) { 278 return; 279 } 280 281 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this); 282 final int count = mChildren.size(); 283 284 mReportedVisibilityResults.reset(); 285 286 for (int i = 0; i < count; i++) { 287 final WindowState win = mChildren.get(i); 288 win.updateReportedVisibility(mReportedVisibilityResults); 289 } 290 291 int numInteresting = mReportedVisibilityResults.numInteresting; 292 int numVisible = mReportedVisibilityResults.numVisible; 293 int numDrawn = mReportedVisibilityResults.numDrawn; 294 boolean nowGone = mReportedVisibilityResults.nowGone; 295 296 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting; 297 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !hidden; 298 if (!nowGone) { 299 // If the app is not yet gone, then it can only become visible/drawn. 300 if (!nowDrawn) { 301 nowDrawn = reportedDrawn; 302 } 303 if (!nowVisible) { 304 nowVisible = reportedVisible; 305 } 306 } 307 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting=" 308 + numInteresting + " visible=" + numVisible); 309 final AppWindowContainerController controller = getController(); 310 if (nowDrawn != reportedDrawn) { 311 if (nowDrawn) { 312 if (controller != null) { 313 controller.reportWindowsDrawn(); 314 } 315 } 316 reportedDrawn = nowDrawn; 317 } 318 if (nowVisible != reportedVisible) { 319 if (DEBUG_VISIBILITY) Slog.v(TAG, 320 "Visibility changed in " + this + ": vis=" + nowVisible); 321 reportedVisible = nowVisible; 322 if (controller != null) { 323 if (nowVisible) { 324 controller.reportWindowsVisible(); 325 } else { 326 controller.reportWindowsGone(); 327 } 328 } 329 } 330 } 331 isClientHidden()332 boolean isClientHidden() { 333 return mClientHidden; 334 } 335 setClientHidden(boolean hideClient)336 void setClientHidden(boolean hideClient) { 337 if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) { 338 return; 339 } 340 mClientHidden = hideClient; 341 sendAppVisibilityToClients(); 342 } 343 setVisibility(WindowManager.LayoutParams lp, boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction)344 boolean setVisibility(WindowManager.LayoutParams lp, 345 boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) { 346 347 boolean delayed = false; 348 inPendingTransaction = false; 349 // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually 350 // been set by the app now. 351 mHiddenSetFromTransferredStartingWindow = false; 352 setClientHidden(!visible); 353 354 // Allow for state changes and animation to be applied if: 355 // * token is transitioning visibility state 356 // * or the token was marked as hidden and is exiting before we had a chance to play the 357 // transition animation 358 // * or this is an opening app and windows are being replaced. 359 boolean visibilityChanged = false; 360 if (hidden == visible || (hidden && mIsExiting) || (visible && waitingForReplacement())) { 361 final AccessibilityController accessibilityController = mService.mAccessibilityController; 362 boolean changed = false; 363 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, 364 "Changing app " + this + " hidden=" + hidden + " performLayout=" + performLayout); 365 366 boolean runningAppAnimation = false; 367 368 if (mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { 369 mAppAnimator.setNullAnimation(); 370 } 371 if (transit != AppTransition.TRANSIT_UNSET) { 372 if (mService.applyAnimationLocked(this, lp, transit, visible, isVoiceInteraction)) { 373 delayed = runningAppAnimation = true; 374 } 375 final WindowState window = findMainWindow(); 376 //TODO (multidisplay): Magnification is supported only for the default display. 377 if (window != null && accessibilityController != null 378 && getDisplayContent().getDisplayId() == DEFAULT_DISPLAY) { 379 accessibilityController.onAppWindowTransitionLocked(window, transit); 380 } 381 changed = true; 382 } 383 384 final int windowsCount = mChildren.size(); 385 for (int i = 0; i < windowsCount; i++) { 386 final WindowState win = mChildren.get(i); 387 changed |= win.onAppVisibilityChanged(visible, runningAppAnimation); 388 } 389 390 hidden = hiddenRequested = !visible; 391 visibilityChanged = true; 392 if (!visible) { 393 stopFreezingScreen(true, true); 394 } else { 395 // If we are being set visible, and the starting window is not yet displayed, 396 // then make sure it doesn't get displayed. 397 if (startingWindow != null && !startingWindow.isDrawnLw()) { 398 startingWindow.mPolicyVisibility = false; 399 startingWindow.mPolicyVisibilityAfterAnim = false; 400 } 401 402 // We are becoming visible, so better freeze the screen with the windows that are 403 // getting visible so we also wait for them. 404 forAllWindows(mService::makeWindowFreezingScreenIfNeededLocked, true); 405 } 406 407 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setVisibility: " + this 408 + ": hidden=" + hidden + " hiddenRequested=" + hiddenRequested); 409 410 if (changed) { 411 mService.mInputMonitor.setUpdateInputWindowsNeededLw(); 412 if (performLayout) { 413 mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, 414 false /*updateInputWindows*/); 415 mService.mWindowPlacerLocked.performSurfacePlacement(); 416 } 417 mService.mInputMonitor.updateInputWindowsLw(false /*force*/); 418 } 419 } 420 421 if (mAppAnimator.animation != null) { 422 delayed = true; 423 } 424 425 for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) { 426 if ((mChildren.get(i)).isWindowAnimationSet()) { 427 delayed = true; 428 } 429 } 430 431 if (visibilityChanged) { 432 if (visible && !delayed) { 433 // The token was made immediately visible, there will be no entrance animation. 434 // We need to inform the client the enter animation was finished. 435 mEnteringAnimation = true; 436 mService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(token); 437 } 438 439 // If we are hidden but there is no delay needed we immediately 440 // apply the Surface transaction so that the ActivityManager 441 // can have some guarantee on the Surface state following 442 // setting the visibility. This captures cases like dismissing 443 // the docked or pinned stack where there is no app transition. 444 // 445 // In the case of a "Null" animation, there will be 446 // no animation but there will still be a transition set. 447 // We still need to delay hiding the surface such that it 448 // can be synchronized with showing the next surface in the transition. 449 if (hidden && !delayed && !mService.mAppTransition.isTransitionSet()) { 450 SurfaceControl.openTransaction(); 451 for (int i = mChildren.size() - 1; i >= 0; i--) { 452 mChildren.get(i).mWinAnimator.hide("immediately hidden"); 453 } 454 SurfaceControl.closeTransaction(); 455 } 456 457 if (!mService.mClosingApps.contains(this) && !mService.mOpeningApps.contains(this)) { 458 // The token is not closing nor opening, so even if there is an animation set, that 459 // doesn't mean that it goes through the normal app transition cycle so we have 460 // to inform the docked controller about visibility change. 461 // TODO(multi-display): notify docked divider on all displays where visibility was 462 // affected. 463 mService.getDefaultDisplayContentLocked().getDockedDividerController() 464 .notifyAppVisibilityChanged(); 465 mService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible); 466 } 467 } 468 469 return delayed; 470 } 471 472 /** 473 * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns 474 * true. 475 */ getTopFullscreenWindow()476 WindowState getTopFullscreenWindow() { 477 for (int i = mChildren.size() - 1; i >= 0; i--) { 478 final WindowState win = mChildren.get(i); 479 if (win != null && win.mAttrs.isFullscreen()) { 480 return win; 481 } 482 } 483 return null; 484 } 485 findMainWindow()486 WindowState findMainWindow() { 487 WindowState candidate = null; 488 int j = mChildren.size(); 489 while (j > 0) { 490 j--; 491 final WindowState win = mChildren.get(j); 492 final int type = win.mAttrs.type; 493 // No need to loop through child window as base application and starting types can't be 494 // child windows. 495 if (type == TYPE_BASE_APPLICATION || type == TYPE_APPLICATION_STARTING) { 496 // In cases where there are multiple windows, we prefer the non-exiting window. This 497 // happens for example when replacing windows during an activity relaunch. When 498 // constructing the animation, we want the new window, not the exiting one. 499 if (win.mAnimatingExit) { 500 candidate = win; 501 } else { 502 return win; 503 } 504 } 505 } 506 return candidate; 507 } 508 windowsAreFocusable()509 boolean windowsAreFocusable() { 510 return StackId.canReceiveKeys(getTask().mStack.mStackId) || mAlwaysFocusable; 511 } 512 getController()513 AppWindowContainerController getController() { 514 final WindowContainerController controller = super.getController(); 515 return controller != null ? (AppWindowContainerController) controller : null; 516 } 517 518 @Override isVisible()519 boolean isVisible() { 520 // If the app token isn't hidden then it is considered visible and there is no need to check 521 // its children windows to see if they are visible. 522 return !hidden; 523 } 524 525 @Override removeImmediately()526 void removeImmediately() { 527 onRemovedFromDisplay(); 528 super.removeImmediately(); 529 } 530 531 @Override removeIfPossible()532 void removeIfPossible() { 533 mIsExiting = false; 534 removeAllWindowsIfPossible(); 535 removeImmediately(); 536 } 537 538 @Override checkCompleteDeferredRemoval()539 boolean checkCompleteDeferredRemoval() { 540 if (mIsExiting) { 541 removeIfPossible(); 542 } 543 return super.checkCompleteDeferredRemoval(); 544 } 545 onRemovedFromDisplay()546 void onRemovedFromDisplay() { 547 if (mRemovingFromDisplay) { 548 return; 549 } 550 mRemovingFromDisplay = true; 551 552 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this); 553 554 boolean delayed = setVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction); 555 556 mService.mOpeningApps.remove(this); 557 mService.mUnknownAppVisibilityController.appRemovedOrHidden(this); 558 mService.mTaskSnapshotController.onAppRemoved(this); 559 waitingToShow = false; 560 if (mService.mClosingApps.contains(this)) { 561 delayed = true; 562 } else if (mService.mAppTransition.isTransitionSet()) { 563 mService.mClosingApps.add(this); 564 delayed = true; 565 } 566 567 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed 568 + " animation=" + mAppAnimator.animation + " animating=" + mAppAnimator.animating); 569 570 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: " 571 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4)); 572 573 if (startingData != null && getController() != null) { 574 getController().removeStartingWindow(); 575 } 576 577 // If this window was animating, then we need to ensure that the app transition notifies 578 // that animations have completed in WMS.handleAnimatingStoppedAndTransitionLocked(), so 579 // add to that list now 580 if (mAppAnimator.animating) { 581 mService.mNoAnimationNotifyOnTransitionFinished.add(token); 582 } 583 584 final TaskStack stack = getStack(); 585 if (delayed && !isEmpty()) { 586 // set the token aside because it has an active animation to be finished 587 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, 588 "removeAppToken make exiting: " + this); 589 if (stack != null) { 590 stack.mExitingAppTokens.add(this); 591 } 592 mIsExiting = true; 593 } else { 594 // Make sure there is no animation running on this token, so any windows associated 595 // with it will be removed as soon as their animations are complete 596 mAppAnimator.clearAnimation(); 597 mAppAnimator.animating = false; 598 if (stack != null) { 599 stack.mExitingAppTokens.remove(this); 600 } 601 removeIfPossible(); 602 } 603 604 removed = true; 605 stopFreezingScreen(true, true); 606 607 if (mService.mFocusedApp == this) { 608 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this); 609 mService.mFocusedApp = null; 610 mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); 611 mService.mInputMonitor.setFocusedAppLw(null); 612 } 613 614 if (!delayed) { 615 updateReportedVisibilityLocked(); 616 } 617 618 mRemovingFromDisplay = false; 619 } 620 clearAnimatingFlags()621 void clearAnimatingFlags() { 622 boolean wallpaperMightChange = false; 623 for (int i = mChildren.size() - 1; i >= 0; i--) { 624 final WindowState win = mChildren.get(i); 625 wallpaperMightChange |= win.clearAnimatingFlags(); 626 } 627 if (wallpaperMightChange) { 628 requestUpdateWallpaperIfNeeded(); 629 } 630 } 631 destroySurfaces()632 void destroySurfaces() { 633 destroySurfaces(false /*cleanupOnResume*/); 634 } 635 636 /** 637 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure 638 * the client has finished with them. 639 * 640 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If 641 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the 642 * others so that they are ready to be reused. If set to false (common case), destroy all 643 * surfaces that's eligible, if the app is already stopped. 644 */ destroySurfaces(boolean cleanupOnResume)645 private void destroySurfaces(boolean cleanupOnResume) { 646 boolean destroyedSomething = false; 647 for (int i = mChildren.size() - 1; i >= 0; i--) { 648 final WindowState win = mChildren.get(i); 649 destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped); 650 } 651 if (destroyedSomething) { 652 final DisplayContent dc = getDisplayContent(); 653 dc.assignWindowLayers(true /*setLayoutNeeded*/); 654 } 655 } 656 657 /** 658 * Notify that the app is now resumed, and it was not stopped before, perform a clean 659 * up of the surfaces 660 */ notifyAppResumed(boolean wasStopped)661 void notifyAppResumed(boolean wasStopped) { 662 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped 663 + " " + this); 664 mAppStopped = false; 665 // Allow the window to turn the screen on once the app is resumed again. 666 setCanTurnScreenOn(true); 667 if (!wasStopped) { 668 destroySurfaces(true /*cleanupOnResume*/); 669 } 670 } 671 672 /** 673 * Notify that the app has stopped, and it is okay to destroy any surfaces which were 674 * keeping alive in case they were still being used. 675 */ notifyAppStopped()676 void notifyAppStopped() { 677 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this); 678 mAppStopped = true; 679 destroySurfaces(); 680 // Remove any starting window that was added for this app if they are still around. 681 if (getController() != null) { 682 getController().removeStartingWindow(); 683 } 684 } 685 686 /** 687 * Checks whether we should save surfaces for this app. 688 * 689 * @return true if the surfaces should be saved, false otherwise. 690 */ shouldSaveSurface()691 boolean shouldSaveSurface() { 692 // We want to save surface if the app's windows are "allDrawn". 693 // (If we started entering animation early with saved surfaces, allDrawn 694 // should have been restored to true. So we'll save again in that case 695 // even if app didn't actually finish drawing.) 696 return allDrawn; 697 } 698 canRestoreSurfaces()699 private boolean canRestoreSurfaces() { 700 for (int i = mChildren.size() -1; i >= 0; i--) { 701 final WindowState w = mChildren.get(i); 702 if (w.canRestoreSurface()) { 703 return true; 704 } 705 } 706 return false; 707 } 708 clearWasVisibleBeforeClientHidden()709 private void clearWasVisibleBeforeClientHidden() { 710 for (int i = mChildren.size() - 1; i >= 0; i--) { 711 final WindowState w = mChildren.get(i); 712 w.clearWasVisibleBeforeClientHidden(); 713 } 714 } 715 716 /** 717 * Whether the app has some window that is invisible in layout, but 718 * animating with saved surface. 719 */ isAnimatingInvisibleWithSavedSurface()720 boolean isAnimatingInvisibleWithSavedSurface() { 721 for (int i = mChildren.size() - 1; i >= 0; i--) { 722 final WindowState w = mChildren.get(i); 723 if (w.isAnimatingInvisibleWithSavedSurface()) { 724 return true; 725 } 726 } 727 return false; 728 } 729 730 /** 731 * Hide all window surfaces that's still invisible in layout but animating 732 * with a saved surface, and mark them destroying. 733 */ stopUsingSavedSurfaceLocked()734 void stopUsingSavedSurfaceLocked() { 735 for (int i = mChildren.size() - 1; i >= 0; i--) { 736 final WindowState w = mChildren.get(i); 737 w.stopUsingSavedSurface(); 738 } 739 destroySurfaces(); 740 } 741 markSavedSurfaceExiting()742 void markSavedSurfaceExiting() { 743 for (int i = mChildren.size() - 1; i >= 0; i--) { 744 final WindowState w = mChildren.get(i); 745 w.markSavedSurfaceExiting(); 746 } 747 } 748 restoreSavedSurfaceForInterestingWindows()749 void restoreSavedSurfaceForInterestingWindows() { 750 if (!canRestoreSurfaces()) { 751 clearWasVisibleBeforeClientHidden(); 752 return; 753 } 754 755 // Check if all interesting windows are drawn and we can mark allDrawn=true. 756 int interestingNotDrawn = -1; 757 758 for (int i = mChildren.size() - 1; i >= 0; i--) { 759 final WindowState w = mChildren.get(i); 760 interestingNotDrawn = w.restoreSavedSurfaceForInterestingWindow(); 761 } 762 763 if (!allDrawn) { 764 allDrawn = (interestingNotDrawn == 0); 765 if (allDrawn) { 766 mService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget(); 767 } 768 } 769 clearWasVisibleBeforeClientHidden(); 770 771 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.d(TAG, 772 "restoreSavedSurfaceForInterestingWindows: " + this + " allDrawn=" + allDrawn 773 + " interestingNotDrawn=" + interestingNotDrawn); 774 } 775 destroySavedSurfaces()776 void destroySavedSurfaces() { 777 for (int i = mChildren.size() - 1; i >= 0; i--) { 778 final WindowState win = mChildren.get(i); 779 win.destroySavedSurface(); 780 } 781 } 782 clearAllDrawn()783 void clearAllDrawn() { 784 allDrawn = false; 785 deferClearAllDrawn = false; 786 allDrawnExcludingSaved = false; 787 } 788 getTask()789 Task getTask() { 790 return (Task) getParent(); 791 } 792 getStack()793 TaskStack getStack() { 794 final Task task = getTask(); 795 if (task != null) { 796 return task.mStack; 797 } else { 798 return null; 799 } 800 } 801 802 @Override onParentSet()803 void onParentSet() { 804 super.onParentSet(); 805 806 final Task task = getTask(); 807 808 // When the associated task is {@code null}, the {@link AppWindowToken} can no longer 809 // access visual elements like the {@link DisplayContent}. We must remove any associations 810 // such as animations. 811 if (!mReparenting) { 812 if (task == null) { 813 // It is possible we have been marked as a closing app earlier. We must remove ourselves 814 // from this list so we do not participate in any future animations. 815 mService.mClosingApps.remove(this); 816 } else if (mLastParent != null && mLastParent.mStack != null) { 817 task.mStack.mExitingAppTokens.remove(this); 818 } 819 } 820 mLastParent = task; 821 } 822 postWindowRemoveStartingWindowCleanup(WindowState win)823 void postWindowRemoveStartingWindowCleanup(WindowState win) { 824 // TODO: Something smells about the code below...Is there a better way? 825 if (startingWindow == win) { 826 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win); 827 if (getController() != null) { 828 getController().removeStartingWindow(); 829 } 830 } else if (mChildren.size() == 0) { 831 // If this is the last window and we had requested a starting transition window, 832 // well there is no point now. 833 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData"); 834 startingData = null; 835 if (mHiddenSetFromTransferredStartingWindow) { 836 // We set the hidden state to false for the token from a transferred starting window. 837 // We now reset it back to true since the starting window was the last window in the 838 // token. 839 hidden = true; 840 } 841 } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) { 842 // If this is the last window except for a starting transition window, 843 // we need to get rid of the starting transition. 844 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window " 845 + win); 846 if (getController() != null) { 847 getController().removeStartingWindow(); 848 } 849 } 850 } 851 removeDeadWindows()852 void removeDeadWindows() { 853 for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) { 854 WindowState win = mChildren.get(winNdx); 855 if (win.mAppDied) { 856 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG, 857 "removeDeadWindows: " + win); 858 // Set mDestroying, we don't want any animation or delayed removal here. 859 win.mDestroying = true; 860 // Also removes child windows. 861 win.removeIfPossible(); 862 } 863 } 864 } 865 hasWindowsAlive()866 boolean hasWindowsAlive() { 867 for (int i = mChildren.size() - 1; i >= 0; i--) { 868 // No need to loop through child windows as the answer should be the same as that of the 869 // parent window. 870 if (!(mChildren.get(i)).mAppDied) { 871 return true; 872 } 873 } 874 return false; 875 } 876 setWillReplaceWindows(boolean animate)877 void setWillReplaceWindows(boolean animate) { 878 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, 879 "Marking app token " + this + " with replacing windows."); 880 881 for (int i = mChildren.size() - 1; i >= 0; i--) { 882 final WindowState w = mChildren.get(i); 883 w.setWillReplaceWindow(animate); 884 } 885 if (animate) { 886 // Set-up dummy animation so we can start treating windows associated with this 887 // token like they are in transition before the new app window is ready for us to 888 // run the real transition animation. 889 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, 890 "setWillReplaceWindow() Setting dummy animation on: " + this); 891 mAppAnimator.setDummyAnimation(); 892 } 893 } 894 setWillReplaceChildWindows()895 void setWillReplaceChildWindows() { 896 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this 897 + " with replacing child windows."); 898 for (int i = mChildren.size() - 1; i >= 0; i--) { 899 final WindowState w = mChildren.get(i); 900 w.setWillReplaceChildWindows(); 901 } 902 } 903 clearWillReplaceWindows()904 void clearWillReplaceWindows() { 905 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, 906 "Resetting app token " + this + " of replacing window marks."); 907 908 for (int i = mChildren.size() - 1; i >= 0; i--) { 909 final WindowState w = mChildren.get(i); 910 w.clearWillReplaceWindow(); 911 } 912 } 913 requestUpdateWallpaperIfNeeded()914 void requestUpdateWallpaperIfNeeded() { 915 for (int i = mChildren.size() - 1; i >= 0; i--) { 916 final WindowState w = mChildren.get(i); 917 w.requestUpdateWallpaperIfNeeded(); 918 } 919 } 920 isRelaunching()921 boolean isRelaunching() { 922 return mPendingRelaunchCount > 0; 923 } 924 shouldFreezeBounds()925 boolean shouldFreezeBounds() { 926 final Task task = getTask(); 927 928 // For freeform windows, we can't freeze the bounds at the moment because this would make 929 // the resizing unresponsive. 930 if (task == null || task.inFreeformWorkspace()) { 931 return false; 932 } 933 934 // We freeze the bounds while drag resizing to deal with the time between 935 // the divider/drag handle being released, and the handling it's new 936 // configuration. If we are relaunched outside of the drag resizing state, 937 // we need to be careful not to do this. 938 return getTask().isDragResizing(); 939 } 940 startRelaunching()941 void startRelaunching() { 942 if (shouldFreezeBounds()) { 943 freezeBounds(); 944 } 945 946 // In the process of tearing down before relaunching, the app will 947 // try and clean up it's child surfaces. We need to prevent this from 948 // happening, so we sever the children, transfering their ownership 949 // from the client it-self to the parent surface (owned by us). 950 for (int i = mChildren.size() - 1; i >= 0; i--) { 951 final WindowState w = mChildren.get(i); 952 w.mWinAnimator.detachChildren(); 953 } 954 955 mPendingRelaunchCount++; 956 } 957 finishRelaunching()958 void finishRelaunching() { 959 unfreezeBounds(); 960 961 if (mPendingRelaunchCount > 0) { 962 mPendingRelaunchCount--; 963 } else { 964 // Update keyguard flags upon finishing relaunch. 965 checkKeyguardFlagsChanged(); 966 } 967 } 968 clearRelaunching()969 void clearRelaunching() { 970 if (mPendingRelaunchCount == 0) { 971 return; 972 } 973 unfreezeBounds(); 974 mPendingRelaunchCount = 0; 975 } 976 977 /** 978 * Returns true if the new child window we are adding to this token is considered greater than 979 * the existing child window in this token in terms of z-order. 980 */ 981 @Override isFirstChildWindowGreaterThanSecond(WindowState newWindow, WindowState existingWindow)982 protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow, 983 WindowState existingWindow) { 984 final int type1 = newWindow.mAttrs.type; 985 final int type2 = existingWindow.mAttrs.type; 986 987 // Base application windows should be z-ordered BELOW all other windows in the app token. 988 if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) { 989 return false; 990 } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) { 991 return true; 992 } 993 994 // Starting windows should be z-ordered ABOVE all other windows in the app token. 995 if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) { 996 return true; 997 } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) { 998 return false; 999 } 1000 1001 // Otherwise the new window is greater than the existing window. 1002 return true; 1003 } 1004 1005 @Override addWindow(WindowState w)1006 void addWindow(WindowState w) { 1007 super.addWindow(w); 1008 1009 boolean gotReplacementWindow = false; 1010 for (int i = mChildren.size() - 1; i >= 0; i--) { 1011 final WindowState candidate = mChildren.get(i); 1012 gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w); 1013 } 1014 1015 // if we got a replacement window, reset the timeout to give drawing more time 1016 if (gotReplacementWindow) { 1017 mService.scheduleWindowReplacementTimeouts(this); 1018 } 1019 checkKeyguardFlagsChanged(); 1020 } 1021 1022 @Override removeChild(WindowState child)1023 void removeChild(WindowState child) { 1024 super.removeChild(child); 1025 checkKeyguardFlagsChanged(); 1026 } 1027 waitingForReplacement()1028 private boolean waitingForReplacement() { 1029 for (int i = mChildren.size() - 1; i >= 0; i--) { 1030 final WindowState candidate = mChildren.get(i); 1031 if (candidate.waitingForReplacement()) { 1032 return true; 1033 } 1034 } 1035 return false; 1036 } 1037 onWindowReplacementTimeout()1038 void onWindowReplacementTimeout() { 1039 for (int i = mChildren.size() - 1; i >= 0; --i) { 1040 (mChildren.get(i)).onWindowReplacementTimeout(); 1041 } 1042 } 1043 reparent(Task task, int position)1044 void reparent(Task task, int position) { 1045 final Task currentTask = getTask(); 1046 if (task == currentTask) { 1047 throw new IllegalArgumentException( 1048 "window token=" + this + " already child of task=" + currentTask); 1049 } 1050 1051 if (currentTask.mStack != task.mStack) { 1052 throw new IllegalArgumentException( 1053 "window token=" + this + " current task=" + currentTask 1054 + " belongs to a different stack than " + task); 1055 } 1056 1057 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this 1058 + " from task=" + currentTask); 1059 final DisplayContent prevDisplayContent = getDisplayContent(); 1060 1061 mReparenting = true; 1062 1063 getParent().removeChild(this); 1064 task.addChild(this, position); 1065 1066 mReparenting = false; 1067 1068 // Relayout display(s). 1069 final DisplayContent displayContent = task.getDisplayContent(); 1070 displayContent.setLayoutNeeded(); 1071 if (prevDisplayContent != displayContent) { 1072 onDisplayChanged(displayContent); 1073 prevDisplayContent.setLayoutNeeded(); 1074 } 1075 } 1076 1077 /** 1078 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds 1079 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even 1080 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen 1081 * with a queue. 1082 */ freezeBounds()1083 private void freezeBounds() { 1084 final Task task = getTask(); 1085 mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds)); 1086 1087 if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) { 1088 // We didn't call prepareFreezingBounds on the task, so use the current value. 1089 mFrozenMergedConfig.offer(new Configuration(task.getConfiguration())); 1090 } else { 1091 mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig)); 1092 } 1093 // Calling unset() to make it equal to Configuration.EMPTY. 1094 task.mPreparedFrozenMergedConfig.unset(); 1095 } 1096 1097 /** 1098 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}. 1099 */ unfreezeBounds()1100 private void unfreezeBounds() { 1101 if (mFrozenBounds.isEmpty()) { 1102 return; 1103 } 1104 mFrozenBounds.remove(); 1105 if (!mFrozenMergedConfig.isEmpty()) { 1106 mFrozenMergedConfig.remove(); 1107 } 1108 for (int i = mChildren.size() - 1; i >= 0; i--) { 1109 final WindowState win = mChildren.get(i); 1110 win.onUnfreezeBounds(); 1111 } 1112 mService.mWindowPlacerLocked.performSurfacePlacement(); 1113 } 1114 setAppLayoutChanges(int changes, String reason)1115 void setAppLayoutChanges(int changes, String reason) { 1116 if (!mChildren.isEmpty()) { 1117 final DisplayContent dc = getDisplayContent(); 1118 dc.pendingLayoutChanges |= changes; 1119 if (DEBUG_LAYOUT_REPEATS) { 1120 mService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges); 1121 } 1122 } 1123 } 1124 removeReplacedWindowIfNeeded(WindowState replacement)1125 void removeReplacedWindowIfNeeded(WindowState replacement) { 1126 for (int i = mChildren.size() - 1; i >= 0; i--) { 1127 final WindowState win = mChildren.get(i); 1128 if (win.removeReplacedWindowIfNeeded(replacement)) { 1129 return; 1130 } 1131 } 1132 } 1133 startFreezingScreen()1134 void startFreezingScreen() { 1135 if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden=" 1136 + hidden + " freezing=" + mAppAnimator.freezingScreen + " hiddenRequested=" 1137 + hiddenRequested); 1138 if (!hiddenRequested) { 1139 if (!mAppAnimator.freezingScreen) { 1140 mAppAnimator.freezingScreen = true; 1141 mService.registerAppFreezeListener(this); 1142 mAppAnimator.lastFreezeDuration = 0; 1143 mService.mAppsFreezingScreen++; 1144 if (mService.mAppsFreezingScreen == 1) { 1145 mService.startFreezingDisplayLocked(false, 0, 0, getDisplayContent()); 1146 mService.mH.removeMessages(H.APP_FREEZE_TIMEOUT); 1147 mService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000); 1148 } 1149 } 1150 final int count = mChildren.size(); 1151 for (int i = 0; i < count; i++) { 1152 final WindowState w = mChildren.get(i); 1153 w.onStartFreezingScreen(); 1154 } 1155 } 1156 } 1157 stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force)1158 void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) { 1159 if (!mAppAnimator.freezingScreen) { 1160 return; 1161 } 1162 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force); 1163 final int count = mChildren.size(); 1164 boolean unfrozeWindows = false; 1165 for (int i = 0; i < count; i++) { 1166 final WindowState w = mChildren.get(i); 1167 unfrozeWindows |= w.onStopFreezingScreen(); 1168 } 1169 if (force || unfrozeWindows) { 1170 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this); 1171 mAppAnimator.freezingScreen = false; 1172 mService.unregisterAppFreezeListener(this); 1173 mAppAnimator.lastFreezeDuration = 1174 (int)(SystemClock.elapsedRealtime() - mService.mDisplayFreezeTime); 1175 mService.mAppsFreezingScreen--; 1176 mService.mLastFinishedFreezeSource = this; 1177 } 1178 if (unfreezeSurfaceNow) { 1179 if (unfrozeWindows) { 1180 mService.mWindowPlacerLocked.performSurfacePlacement(); 1181 } 1182 mService.stopFreezingDisplayLocked(); 1183 } 1184 } 1185 1186 @Override onAppFreezeTimeout()1187 public void onAppFreezeTimeout() { 1188 Slog.w(TAG_WM, "Force clearing freeze: " + this); 1189 stopFreezingScreen(true, true); 1190 } 1191 transferStartingWindow(IBinder transferFrom)1192 boolean transferStartingWindow(IBinder transferFrom) { 1193 final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom); 1194 if (fromToken == null) { 1195 return false; 1196 } 1197 1198 final WindowState tStartingWindow = fromToken.startingWindow; 1199 if (tStartingWindow != null && fromToken.startingSurface != null) { 1200 // In this case, the starting icon has already been displayed, so start 1201 // letting windows get shown immediately without any more transitions. 1202 mService.mSkipAppTransitionAnimation = true; 1203 1204 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Moving existing starting " + tStartingWindow 1205 + " from " + fromToken + " to " + this); 1206 1207 final long origId = Binder.clearCallingIdentity(); 1208 1209 // Transfer the starting window over to the new token. 1210 startingData = fromToken.startingData; 1211 startingSurface = fromToken.startingSurface; 1212 startingDisplayed = fromToken.startingDisplayed; 1213 fromToken.startingDisplayed = false; 1214 startingWindow = tStartingWindow; 1215 reportedVisible = fromToken.reportedVisible; 1216 fromToken.startingData = null; 1217 fromToken.startingSurface = null; 1218 fromToken.startingWindow = null; 1219 fromToken.startingMoved = true; 1220 tStartingWindow.mToken = this; 1221 tStartingWindow.mAppToken = this; 1222 1223 if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, 1224 "Removing starting " + tStartingWindow + " from " + fromToken); 1225 fromToken.removeChild(tStartingWindow); 1226 fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow); 1227 fromToken.mHiddenSetFromTransferredStartingWindow = false; 1228 addWindow(tStartingWindow); 1229 1230 // Propagate other interesting state between the tokens. If the old token is displayed, 1231 // we should immediately force the new one to be displayed. If it is animating, we need 1232 // to move that animation to the new one. 1233 if (fromToken.allDrawn) { 1234 allDrawn = true; 1235 deferClearAllDrawn = fromToken.deferClearAllDrawn; 1236 } 1237 if (fromToken.firstWindowDrawn) { 1238 firstWindowDrawn = true; 1239 } 1240 if (!fromToken.hidden) { 1241 hidden = false; 1242 hiddenRequested = false; 1243 mHiddenSetFromTransferredStartingWindow = true; 1244 } 1245 setClientHidden(fromToken.mClientHidden); 1246 fromToken.mAppAnimator.transferCurrentAnimation( 1247 mAppAnimator, tStartingWindow.mWinAnimator); 1248 1249 mService.updateFocusedWindowLocked( 1250 UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/); 1251 getDisplayContent().setLayoutNeeded(); 1252 mService.mWindowPlacerLocked.performSurfacePlacement(); 1253 Binder.restoreCallingIdentity(origId); 1254 return true; 1255 } else if (fromToken.startingData != null) { 1256 // The previous app was getting ready to show a 1257 // starting window, but hasn't yet done so. Steal it! 1258 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, 1259 "Moving pending starting from " + fromToken + " to " + this); 1260 startingData = fromToken.startingData; 1261 fromToken.startingData = null; 1262 fromToken.startingMoved = true; 1263 if (getController() != null) { 1264 getController().scheduleAddStartingWindow(); 1265 } 1266 return true; 1267 } 1268 1269 final AppWindowAnimator tAppAnimator = fromToken.mAppAnimator; 1270 final AppWindowAnimator wAppAnimator = mAppAnimator; 1271 if (tAppAnimator.thumbnail != null) { 1272 // The old token is animating with a thumbnail, transfer that to the new token. 1273 if (wAppAnimator.thumbnail != null) { 1274 wAppAnimator.thumbnail.destroy(); 1275 } 1276 wAppAnimator.thumbnail = tAppAnimator.thumbnail; 1277 wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer; 1278 wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation; 1279 tAppAnimator.thumbnail = null; 1280 } 1281 return false; 1282 } 1283 isLastWindow(WindowState win)1284 boolean isLastWindow(WindowState win) { 1285 return mChildren.size() == 1 && mChildren.get(0) == win; 1286 } 1287 setAllAppWinAnimators()1288 void setAllAppWinAnimators() { 1289 final ArrayList<WindowStateAnimator> allAppWinAnimators = mAppAnimator.mAllAppWinAnimators; 1290 allAppWinAnimators.clear(); 1291 1292 final int windowsCount = mChildren.size(); 1293 for (int j = 0; j < windowsCount; j++) { 1294 (mChildren.get(j)).addWinAnimatorToList(allAppWinAnimators); 1295 } 1296 } 1297 1298 @Override onAppTransitionDone()1299 void onAppTransitionDone() { 1300 sendingToBottom = false; 1301 } 1302 1303 /** 1304 * We override because this class doesn't want its children affecting its reported orientation 1305 * in anyway. 1306 */ 1307 @Override getOrientation(int candidate)1308 int getOrientation(int candidate) { 1309 if (candidate == SCREEN_ORIENTATION_BEHIND) { 1310 // Allow app to specify orientation regardless of its visibility state if the current 1311 // candidate want us to use orientation behind. I.e. the visible app on-top of this one 1312 // wants us to use the orientation of the app behind it. 1313 return mOrientation; 1314 } 1315 1316 // The {@link AppWindowToken} should only specify an orientation when it is not closing or 1317 // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to 1318 // an Activity in another task being started in the wrong orientation during the transition. 1319 if (!(sendingToBottom || mService.mClosingApps.contains(this)) 1320 && (isVisible() || mService.mOpeningApps.contains(this) || isOnTop())) { 1321 return mOrientation; 1322 } 1323 1324 return SCREEN_ORIENTATION_UNSET; 1325 } 1326 1327 /** Returns the app's preferred orientation regardless of its currently visibility state. */ getOrientationIgnoreVisibility()1328 int getOrientationIgnoreVisibility() { 1329 return mOrientation; 1330 } 1331 1332 @Override checkAppWindowsReadyToShow()1333 void checkAppWindowsReadyToShow() { 1334 if (allDrawn == mAppAnimator.allDrawn) { 1335 return; 1336 } 1337 1338 mAppAnimator.allDrawn = allDrawn; 1339 if (!allDrawn) { 1340 return; 1341 } 1342 1343 // The token has now changed state to having all windows shown... what to do, what to do? 1344 if (mAppAnimator.freezingScreen) { 1345 mAppAnimator.showAllWindowsLocked(); 1346 stopFreezingScreen(false, true); 1347 if (DEBUG_ORIENTATION) Slog.i(TAG, 1348 "Setting mOrientationChangeComplete=true because wtoken " + this 1349 + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows); 1350 // This will set mOrientationChangeComplete and cause a pass through layout. 1351 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER, 1352 "checkAppWindowsReadyToShow: freezingScreen"); 1353 } else { 1354 setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow"); 1355 1356 // We can now show all of the drawn windows! 1357 if (!mService.mOpeningApps.contains(this)) { 1358 mService.mAnimator.orAnimating(mAppAnimator.showAllWindowsLocked()); 1359 } 1360 } 1361 } 1362 1363 /** 1364 * Returns whether the drawn window states of this {@link AppWindowToken} has considered every 1365 * child {@link WindowState}. A child is considered if it has been passed into 1366 * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine 1367 * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as 1368 * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered. 1369 * 1370 * @return {@code true} If all children have been considered, {@code false}. 1371 */ allDrawnStatesConsidered()1372 private boolean allDrawnStatesConsidered() { 1373 for (int i = mChildren.size() - 1; i >= 0; --i) { 1374 final WindowState child = mChildren.get(i); 1375 if (child.mightAffectAllDrawn(false /*visibleOnly*/ ) 1376 && !child.getDrawnStateEvaluated()) { 1377 return false; 1378 } 1379 } 1380 return true; 1381 } 1382 1383 /** 1384 * Determines if the token has finished drawing. This should only be called from 1385 * {@link DisplayContent#applySurfaceChangesTransaction} 1386 */ updateAllDrawn()1387 void updateAllDrawn() { 1388 if (!allDrawn) { 1389 // Number of drawn windows can be less when a window is being relaunched, wait for 1390 // all windows to be launched and drawn for this token be considered all drawn. 1391 final int numInteresting = mNumInterestingWindows; 1392 1393 // We must make sure that all present children have been considered (determined by 1394 // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been 1395 // drawn. 1396 if (numInteresting > 0 && allDrawnStatesConsidered() 1397 && mNumDrawnWindows >= numInteresting && !isRelaunching()) { 1398 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this 1399 + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows); 1400 allDrawn = true; 1401 // Force an additional layout pass where 1402 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked(). 1403 if (mDisplayContent != null) { 1404 mDisplayContent.setLayoutNeeded(); 1405 } 1406 mService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget(); 1407 1408 // Notify the pinned stack upon all windows drawn. If there was an animation in 1409 // progress then this signal will resume that animation. 1410 final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID); 1411 if (pinnedStack != null) { 1412 pinnedStack.onAllWindowsDrawn(); 1413 } 1414 } 1415 } 1416 1417 if (!allDrawnExcludingSaved) { 1418 int numInteresting = mNumInterestingWindowsExcludingSaved; 1419 if (numInteresting > 0 && mNumDrawnWindowsExcludingSaved >= numInteresting) { 1420 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawnExcludingSaved: " + this 1421 + " interesting=" + numInteresting 1422 + " drawn=" + mNumDrawnWindowsExcludingSaved); 1423 allDrawnExcludingSaved = true; 1424 if (mDisplayContent != null) { 1425 mDisplayContent.setLayoutNeeded(); 1426 } 1427 if (isAnimatingInvisibleWithSavedSurface() 1428 && !mService.mFinishedEarlyAnim.contains(this)) { 1429 mService.mFinishedEarlyAnim.add(this); 1430 } 1431 } 1432 } 1433 } 1434 1435 /** 1436 * Updated this app token tracking states for interesting and drawn windows based on the window. 1437 * 1438 * @return Returns true if the input window is considered interesting and drawn while all the 1439 * windows in this app token where not considered drawn as of the last pass. 1440 */ updateDrawnWindowStates(WindowState w)1441 boolean updateDrawnWindowStates(WindowState w) { 1442 w.setDrawnStateEvaluated(true /*evaluated*/); 1443 1444 if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) { 1445 Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen() 1446 + " allDrawn=" + allDrawn + " freezingScreen=" + mAppAnimator.freezingScreen); 1447 } 1448 1449 if (allDrawn && allDrawnExcludingSaved && !mAppAnimator.freezingScreen) { 1450 return false; 1451 } 1452 1453 if (mLastTransactionSequence != mService.mTransactionSequence) { 1454 mLastTransactionSequence = mService.mTransactionSequence; 1455 mNumInterestingWindows = mNumDrawnWindows = 0; 1456 mNumInterestingWindowsExcludingSaved = 0; 1457 mNumDrawnWindowsExcludingSaved = 0; 1458 startingDisplayed = false; 1459 } 1460 1461 final WindowStateAnimator winAnimator = w.mWinAnimator; 1462 1463 boolean isInterestingAndDrawn = false; 1464 1465 if (!allDrawn && w.mightAffectAllDrawn(false /* visibleOnly */)) { 1466 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { 1467 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() 1468 + ", isAnimationSet=" + winAnimator.isAnimationSet()); 1469 if (!w.isDrawnLw()) { 1470 Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController 1471 + " pv=" + w.mPolicyVisibility 1472 + " mDrawState=" + winAnimator.drawStateToString() 1473 + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested 1474 + " a=" + winAnimator.mAnimating); 1475 } 1476 } 1477 1478 if (w != startingWindow) { 1479 if (w.isInteresting()) { 1480 mNumInterestingWindows++; 1481 if (w.isDrawnLw()) { 1482 mNumDrawnWindows++; 1483 1484 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, "tokenMayBeDrawn: " 1485 + this + " w=" + w + " numInteresting=" + mNumInterestingWindows 1486 + " freezingScreen=" + mAppAnimator.freezingScreen 1487 + " mAppFreezing=" + w.mAppFreezing); 1488 1489 isInterestingAndDrawn = true; 1490 } 1491 } 1492 } else if (w.isDrawnLw()) { 1493 if (getController() != null) { 1494 getController().reportStartingWindowDrawn(); 1495 } 1496 startingDisplayed = true; 1497 } 1498 } 1499 1500 if (!allDrawnExcludingSaved && w.mightAffectAllDrawn(true /* visibleOnly */)) { 1501 if (w != startingWindow && w.isInteresting()) { 1502 mNumInterestingWindowsExcludingSaved++; 1503 if (w.isDrawnLw() && !w.isAnimatingWithSavedSurface()) { 1504 mNumDrawnWindowsExcludingSaved++; 1505 1506 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, 1507 "tokenMayBeDrawnExcludingSaved: " + this + " w=" + w 1508 + " numInteresting=" + mNumInterestingWindowsExcludingSaved 1509 + " freezingScreen=" + mAppAnimator.freezingScreen 1510 + " mAppFreezing=" + w.mAppFreezing); 1511 1512 isInterestingAndDrawn = true; 1513 } 1514 } 1515 } 1516 1517 return isInterestingAndDrawn; 1518 } 1519 1520 @Override stepAppWindowsAnimation(long currentTime)1521 void stepAppWindowsAnimation(long currentTime) { 1522 mAppAnimator.wasAnimating = mAppAnimator.animating; 1523 if (mAppAnimator.stepAnimationLocked(currentTime)) { 1524 mAppAnimator.animating = true; 1525 mService.mAnimator.setAnimating(true); 1526 mService.mAnimator.mAppWindowAnimating = true; 1527 } else if (mAppAnimator.wasAnimating) { 1528 // stopped animating, do one more pass through the layout 1529 setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER, 1530 DEBUG_LAYOUT_REPEATS ? "appToken " + this + " done" : null); 1531 if (DEBUG_ANIM) Slog.v(TAG, "updateWindowsApps...: done animating " + this); 1532 } 1533 } 1534 1535 @Override forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)1536 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { 1537 // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent 1538 // before the non-exiting app tokens. So, we skip the exiting app tokens here. 1539 // TODO: Investigate if we need to continue to do this or if we can just process them 1540 // in-order. 1541 if (mIsExiting && !waitingForReplacement()) { 1542 return false; 1543 } 1544 return forAllWindowsUnchecked(callback, traverseTopToBottom); 1545 } 1546 forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)1547 boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback, 1548 boolean traverseTopToBottom) { 1549 return super.forAllWindows(callback, traverseTopToBottom); 1550 } 1551 1552 @Override asAppWindowToken()1553 AppWindowToken asAppWindowToken() { 1554 // I am an app window token! 1555 return this; 1556 } 1557 1558 @Override fillsParent()1559 boolean fillsParent() { 1560 return mFillsParent; 1561 } 1562 setFillsParent(boolean fillsParent)1563 void setFillsParent(boolean fillsParent) { 1564 mFillsParent = fillsParent; 1565 } 1566 containsDismissKeyguardWindow()1567 boolean containsDismissKeyguardWindow() { 1568 // Window state is transient during relaunch. We are not guaranteed to be frozen during the 1569 // entirety of the relaunch. 1570 if (isRelaunching()) { 1571 return mLastContainsDismissKeyguardWindow; 1572 } 1573 1574 for (int i = mChildren.size() - 1; i >= 0; i--) { 1575 if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) { 1576 return true; 1577 } 1578 } 1579 return false; 1580 } 1581 containsShowWhenLockedWindow()1582 boolean containsShowWhenLockedWindow() { 1583 // When we are relaunching, it is possible for us to be unfrozen before our previous 1584 // windows have been added back. Using the cached value ensures that our previous 1585 // showWhenLocked preference is honored until relaunching is complete. 1586 if (isRelaunching()) { 1587 return mLastContainsShowWhenLockedWindow; 1588 } 1589 1590 for (int i = mChildren.size() - 1; i >= 0; i--) { 1591 if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) { 1592 return true; 1593 } 1594 } 1595 1596 return false; 1597 } 1598 checkKeyguardFlagsChanged()1599 void checkKeyguardFlagsChanged() { 1600 final boolean containsDismissKeyguard = containsDismissKeyguardWindow(); 1601 final boolean containsShowWhenLocked = containsShowWhenLockedWindow(); 1602 if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow 1603 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) { 1604 mService.notifyKeyguardFlagsChanged(null /* callback */); 1605 } 1606 mLastContainsDismissKeyguardWindow = containsDismissKeyguard; 1607 mLastContainsShowWhenLockedWindow = containsShowWhenLocked; 1608 } 1609 getImeTargetBelowWindow(WindowState w)1610 WindowState getImeTargetBelowWindow(WindowState w) { 1611 final int index = mChildren.indexOf(w); 1612 if (index > 0) { 1613 final WindowState target = mChildren.get(index - 1); 1614 if (target.canBeImeTarget()) { 1615 return target; 1616 } 1617 } 1618 return null; 1619 } 1620 getLowestAnimLayer()1621 int getLowestAnimLayer() { 1622 for (int i = 0; i < mChildren.size(); i++) { 1623 final WindowState w = mChildren.get(i); 1624 if (w.mRemoved) { 1625 continue; 1626 } 1627 return w.mWinAnimator.mAnimLayer; 1628 } 1629 return Integer.MAX_VALUE; 1630 } 1631 getHighestAnimLayerWindow(WindowState currentTarget)1632 WindowState getHighestAnimLayerWindow(WindowState currentTarget) { 1633 WindowState candidate = null; 1634 for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) { 1635 final WindowState w = mChildren.get(i); 1636 if (w.mRemoved) { 1637 continue; 1638 } 1639 if (candidate == null || w.mWinAnimator.mAnimLayer > 1640 candidate.mWinAnimator.mAnimLayer) { 1641 candidate = w; 1642 } 1643 } 1644 return candidate; 1645 } 1646 1647 /** 1648 * See {@link Activity#setDisablePreviewScreenshots}. 1649 */ setDisablePreviewScreenshots(boolean disable)1650 void setDisablePreviewScreenshots(boolean disable) { 1651 mDisablePreviewScreenshots = disable; 1652 } 1653 1654 /** 1655 * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()} 1656 */ setCanTurnScreenOn(boolean canTurnScreenOn)1657 void setCanTurnScreenOn(boolean canTurnScreenOn) { 1658 mCanTurnScreenOn = canTurnScreenOn; 1659 } 1660 1661 /** 1662 * Indicates whether the current launch can turn the screen on. This is to prevent multiple 1663 * relayouts from turning the screen back on. The screen should only turn on at most 1664 * once per activity resume. 1665 * 1666 * @return true if the screen can be turned on. 1667 */ canTurnScreenOn()1668 boolean canTurnScreenOn() { 1669 return mCanTurnScreenOn; 1670 } 1671 1672 /** 1673 * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is 1674 * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when 1675 * we can't take a snapshot for other reasons, for example, if we have a secure window. 1676 * 1677 * @return True if we need to generate an app theme snapshot, false if we'd like to take a real 1678 * screenshot. 1679 */ shouldUseAppThemeSnapshot()1680 boolean shouldUseAppThemeSnapshot() { 1681 return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0, 1682 true /* topToBottom */); 1683 } 1684 1685 @Override getAnimLayerAdjustment()1686 int getAnimLayerAdjustment() { 1687 return mAppAnimator.animLayerAdjustment; 1688 } 1689 1690 @Override dump(PrintWriter pw, String prefix)1691 void dump(PrintWriter pw, String prefix) { 1692 super.dump(pw, prefix); 1693 if (appToken != null) { 1694 pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction); 1695 } 1696 pw.print(prefix); pw.print("task="); pw.println(getTask()); 1697 pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent); 1698 pw.print(" mOrientation="); pw.println(mOrientation); 1699 pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden 1700 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "") 1701 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible); 1702 if (paused) { 1703 pw.print(prefix); pw.print("paused="); pw.println(paused); 1704 } 1705 if (mAppStopped) { 1706 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped); 1707 } 1708 if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0 1709 || allDrawn || mAppAnimator.allDrawn) { 1710 pw.print(prefix); pw.print("mNumInterestingWindows="); 1711 pw.print(mNumInterestingWindows); 1712 pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows); 1713 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction); 1714 pw.print(" allDrawn="); pw.print(allDrawn); 1715 pw.print(" (animator="); pw.print(mAppAnimator.allDrawn); 1716 pw.println(")"); 1717 } 1718 if (inPendingTransaction) { 1719 pw.print(prefix); pw.print("inPendingTransaction="); 1720 pw.println(inPendingTransaction); 1721 } 1722 if (startingData != null || removed || firstWindowDrawn || mIsExiting) { 1723 pw.print(prefix); pw.print("startingData="); pw.print(startingData); 1724 pw.print(" removed="); pw.print(removed); 1725 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn); 1726 pw.print(" mIsExiting="); pw.println(mIsExiting); 1727 } 1728 if (startingWindow != null || startingSurface != null 1729 || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) { 1730 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow); 1731 pw.print(" startingSurface="); pw.print(startingSurface); 1732 pw.print(" startingDisplayed="); pw.print(startingDisplayed); 1733 pw.print(" startingMoved="); pw.print(startingMoved); 1734 pw.println(" mHiddenSetFromTransferredStartingWindow=" 1735 + mHiddenSetFromTransferredStartingWindow); 1736 } 1737 if (!mFrozenBounds.isEmpty()) { 1738 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds); 1739 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig); 1740 } 1741 if (mPendingRelaunchCount != 0) { 1742 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount); 1743 } 1744 if (getController() != null) { 1745 pw.print(prefix); pw.print("controller="); pw.println(getController()); 1746 } 1747 if (mRemovingFromDisplay) { 1748 pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay); 1749 } 1750 if (mAppAnimator.isAnimating()) { 1751 mAppAnimator.dump(pw, prefix + " "); 1752 } 1753 } 1754 1755 @Override toString()1756 public String toString() { 1757 if (stringName == null) { 1758 StringBuilder sb = new StringBuilder(); 1759 sb.append("AppWindowToken{"); 1760 sb.append(Integer.toHexString(System.identityHashCode(this))); 1761 sb.append(" token="); sb.append(token); sb.append('}'); 1762 stringName = sb.toString(); 1763 } 1764 return stringName + ((mIsExiting) ? " mIsExiting=" : ""); 1765 } 1766 } 1767