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.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 21 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 22 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 23 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 24 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS; 25 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 26 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW; 27 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 28 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT; 29 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 30 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 31 import static com.android.server.wm.WindowManagerService.WINDOW_REPLACEMENT_TIMEOUT_DURATION; 32 import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN; 33 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE; 34 35 import com.android.server.input.InputApplicationHandle; 36 import com.android.server.wm.WindowManagerService.H; 37 38 import android.annotation.NonNull; 39 import android.content.pm.ActivityInfo; 40 import android.content.res.Configuration; 41 import android.graphics.Rect; 42 import android.os.Message; 43 import android.os.RemoteException; 44 import android.util.Slog; 45 import android.view.IApplicationToken; 46 import android.view.View; 47 import android.view.WindowManager; 48 import android.view.animation.Animation; 49 50 import java.io.PrintWriter; 51 import java.util.ArrayDeque; 52 import java.util.ArrayList; 53 54 class AppTokenList extends ArrayList<AppWindowToken> { 55 } 56 57 /** 58 * Version of WindowToken that is specifically for a particular application (or 59 * really activity) that is displaying windows. 60 */ 61 class AppWindowToken extends WindowToken { 62 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM; 63 64 // Non-null only for application tokens. 65 final IApplicationToken appToken; 66 67 // All of the windows and child windows that are included in this 68 // application token. Note this list is NOT sorted! 69 final WindowList allAppWindows = new WindowList(); 70 @NonNull final AppWindowAnimator mAppAnimator; 71 72 final boolean voiceInteraction; 73 74 Task mTask; 75 boolean appFullscreen; 76 int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 77 boolean layoutConfigChanges; 78 boolean showForAllUsers; 79 int targetSdk; 80 81 // The input dispatching timeout for this application token in nanoseconds. 82 long inputDispatchingTimeoutNanos; 83 84 // These are used for determining when all windows associated with 85 // an activity have been drawn, so they can be made visible together 86 // at the same time. 87 // initialize so that it doesn't match mTransactionSequence which is an int. 88 long lastTransactionSequence = Long.MIN_VALUE; 89 int numInterestingWindows; 90 int numDrawnWindows; 91 boolean inPendingTransaction; 92 boolean allDrawn; 93 // Set to true when this app creates a surface while in the middle of an animation. In that 94 // case do not clear allDrawn until the animation completes. 95 boolean deferClearAllDrawn; 96 97 // These are to track the app's real drawing status if there were no saved surfaces. 98 boolean allDrawnExcludingSaved; 99 int numInterestingWindowsExcludingSaved; 100 int numDrawnWindowsExclusingSaved; 101 102 // Is this window's surface needed? This is almost like hidden, except 103 // it will sometimes be true a little earlier: when the token has 104 // been shown, but is still waiting for its app transition to execute 105 // before making its windows shown. 106 boolean hiddenRequested; 107 108 // Have we told the window clients to hide themselves? 109 boolean clientHidden; 110 111 // Last visibility state we reported to the app token. 112 boolean reportedVisible; 113 114 // Last drawn state we reported to the app token. 115 boolean reportedDrawn; 116 117 // Set to true when the token has been removed from the window mgr. 118 boolean removed; 119 120 // Information about an application starting window if displayed. 121 StartingData startingData; 122 WindowState startingWindow; 123 View startingView; 124 boolean startingDisplayed; 125 boolean startingMoved; 126 boolean firstWindowDrawn; 127 128 // Input application handle used by the input dispatcher. 129 final InputApplicationHandle mInputApplicationHandle; 130 131 boolean mIsExiting; 132 133 boolean mLaunchTaskBehind; 134 boolean mEnteringAnimation; 135 136 boolean mAlwaysFocusable; 137 138 boolean mAppStopped; 139 int mRotationAnimationHint; 140 int mPendingRelaunchCount; 141 142 private ArrayList<WindowSurfaceController.SurfaceControlWithBackground> mSurfaceViewBackgrounds = 143 new ArrayList<WindowSurfaceController.SurfaceControlWithBackground>(); 144 145 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>(); 146 ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>(); 147 148 AppWindowToken(WindowManagerService _service, IApplicationToken _token, 149 boolean _voiceInteraction) { 150 super(_service, _token.asBinder(), 151 WindowManager.LayoutParams.TYPE_APPLICATION, true); 152 appWindowToken = this; 153 appToken = _token; 154 voiceInteraction = _voiceInteraction; 155 mInputApplicationHandle = new InputApplicationHandle(this); 156 mAppAnimator = new AppWindowAnimator(this); 157 } 158 159 void sendAppVisibilityToClients() { 160 final int N = allAppWindows.size(); 161 for (int i=0; i<N; i++) { 162 WindowState win = allAppWindows.get(i); 163 if (win == startingWindow && clientHidden) { 164 // Don't hide the starting window. 165 continue; 166 } 167 try { 168 if (DEBUG_VISIBILITY) Slog.v(TAG, 169 "Setting visibility of " + win + ": " + (!clientHidden)); 170 win.mClient.dispatchAppVisibility(!clientHidden); 171 } catch (RemoteException e) { 172 } 173 } 174 } 175 176 void setVisibleBeforeClientHidden() { 177 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 178 final WindowState w = allAppWindows.get(i); 179 w.setVisibleBeforeClientHidden(); 180 } 181 } 182 183 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) { 184 firstWindowDrawn = true; 185 186 // We now have a good window to show, remove dead placeholders 187 removeAllDeadWindows(); 188 189 if (startingData != null) { 190 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting " 191 + win.mToken + ": first real window is shown, no animation"); 192 // If this initial window is animating, stop it -- we will do an animation to reveal 193 // it from behind the starting window, so there is no need for it to also be doing its 194 // own stuff. 195 winAnimator.clearAnimation(); 196 winAnimator.mService.mFinishedStarting.add(this); 197 winAnimator.mService.mH.sendEmptyMessage(H.FINISHED_STARTING); 198 } 199 updateReportedVisibilityLocked(); 200 } 201 202 void updateReportedVisibilityLocked() { 203 if (appToken == null) { 204 return; 205 } 206 207 int numInteresting = 0; 208 int numVisible = 0; 209 int numDrawn = 0; 210 boolean nowGone = true; 211 212 if (DEBUG_VISIBILITY) Slog.v(TAG, 213 "Update reported visibility: " + this); 214 final int N = allAppWindows.size(); 215 for (int i=0; i<N; i++) { 216 WindowState win = allAppWindows.get(i); 217 if (win == startingWindow || win.mAppFreezing 218 || win.mViewVisibility != View.VISIBLE 219 || win.mAttrs.type == TYPE_APPLICATION_STARTING 220 || win.mDestroying) { 221 continue; 222 } 223 if (DEBUG_VISIBILITY) { 224 Slog.v(TAG, "Win " + win + ": isDrawn=" 225 + win.isDrawnLw() 226 + ", isAnimationSet=" + win.mWinAnimator.isAnimationSet()); 227 if (!win.isDrawnLw()) { 228 Slog.v(TAG, "Not displayed: s=" + 229 win.mWinAnimator.mSurfaceController 230 + " pv=" + win.mPolicyVisibility 231 + " mDrawState=" + win.mWinAnimator.mDrawState 232 + " ah=" + win.mAttachedHidden 233 + " th=" 234 + (win.mAppToken != null 235 ? win.mAppToken.hiddenRequested : false) 236 + " a=" + win.mWinAnimator.mAnimating); 237 } 238 } 239 numInteresting++; 240 if (win.isDrawnLw()) { 241 numDrawn++; 242 if (!win.mWinAnimator.isAnimationSet()) { 243 numVisible++; 244 } 245 nowGone = false; 246 } else if (win.mWinAnimator.isAnimationSet()) { 247 nowGone = false; 248 } 249 } 250 251 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting; 252 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting; 253 if (!nowGone) { 254 // If the app is not yet gone, then it can only become visible/drawn. 255 if (!nowDrawn) { 256 nowDrawn = reportedDrawn; 257 } 258 if (!nowVisible) { 259 nowVisible = reportedVisible; 260 } 261 } 262 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting=" 263 + numInteresting + " visible=" + numVisible); 264 if (nowDrawn != reportedDrawn) { 265 if (nowDrawn) { 266 Message m = service.mH.obtainMessage( 267 H.REPORT_APPLICATION_TOKEN_DRAWN, this); 268 service.mH.sendMessage(m); 269 } 270 reportedDrawn = nowDrawn; 271 } 272 if (nowVisible != reportedVisible) { 273 if (DEBUG_VISIBILITY) Slog.v( 274 TAG, "Visibility changed in " + this 275 + ": vis=" + nowVisible); 276 reportedVisible = nowVisible; 277 Message m = service.mH.obtainMessage( 278 H.REPORT_APPLICATION_TOKEN_WINDOWS, 279 nowVisible ? 1 : 0, 280 nowGone ? 1 : 0, 281 this); 282 service.mH.sendMessage(m); 283 } 284 } 285 286 WindowState findMainWindow() { 287 WindowState candidate = null; 288 int j = windows.size(); 289 while (j > 0) { 290 j--; 291 WindowState win = windows.get(j); 292 if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION 293 || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { 294 // In cases where there are multiple windows, we prefer the non-exiting window. This 295 // happens for example when replacing windows during an activity relaunch. When 296 // constructing the animation, we want the new window, not the exiting one. 297 if (win.mAnimatingExit) { 298 candidate = win; 299 } else { 300 return win; 301 } 302 } 303 } 304 return candidate; 305 } 306 307 boolean windowsAreFocusable() { 308 return StackId.canReceiveKeys(mTask.mStack.mStackId) || mAlwaysFocusable; 309 } 310 311 boolean isVisible() { 312 final int N = allAppWindows.size(); 313 for (int i=0; i<N; i++) { 314 WindowState win = allAppWindows.get(i); 315 // If we're animating with a saved surface, we're already visible. 316 // Return true so that the alpha doesn't get cleared. 317 if (!win.mAppFreezing 318 && (win.mViewVisibility == View.VISIBLE || win.isAnimatingWithSavedSurface() 319 || (win.mWinAnimator.isAnimationSet() 320 && !service.mAppTransition.isTransitionSet())) 321 && !win.mDestroying 322 && win.isDrawnLw()) { 323 return true; 324 } 325 } 326 return false; 327 } 328 329 void removeAppFromTaskLocked() { 330 mIsExiting = false; 331 removeAllWindows(); 332 333 // Use local variable because removeAppToken will null out mTask. 334 final Task task = mTask; 335 if (task != null) { 336 if (!task.removeAppToken(this)) { 337 Slog.e(TAG, "removeAppFromTaskLocked: token=" + this 338 + " not found."); 339 } 340 task.mStack.mExitingAppTokens.remove(this); 341 } 342 } 343 344 void clearAnimatingFlags() { 345 boolean wallpaperMightChange = false; 346 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 347 final WindowState win = allAppWindows.get(i); 348 // We don't want to clear it out for windows that get replaced, because the 349 // animation depends on the flag to remove the replaced window. 350 // 351 // We also don't clear the mAnimatingExit flag for windows which have the 352 // mRemoveOnExit flag. This indicates an explicit remove request has been issued 353 // by the client. We should let animation proceed and not clear this flag or 354 // they won't eventually be removed by WindowStateAnimator#finishExit. 355 if (!win.mWillReplaceWindow && !win.mRemoveOnExit) { 356 // Clear mAnimating flag together with mAnimatingExit. When animation 357 // changes from exiting to entering, we need to clear this flag until the 358 // new animation gets applied, so that isAnimationStarting() becomes true 359 // until then. 360 // Otherwise applySurfaceChangesTransaction will faill to skip surface 361 // placement for this window during this period, one or more frame will 362 // show up with wrong position or scale. 363 if (win.mAnimatingExit) { 364 win.mAnimatingExit = false; 365 wallpaperMightChange = true; 366 } 367 if (win.mWinAnimator.mAnimating) { 368 win.mWinAnimator.mAnimating = false; 369 wallpaperMightChange = true; 370 } 371 if (win.mDestroying) { 372 win.mDestroying = false; 373 service.mDestroySurface.remove(win); 374 wallpaperMightChange = true; 375 } 376 } 377 } 378 if (wallpaperMightChange) { 379 requestUpdateWallpaperIfNeeded(); 380 } 381 } 382 383 void destroySurfaces() { 384 destroySurfaces(false /*cleanupOnResume*/); 385 } 386 387 /** 388 * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure 389 * the client has finished with them. 390 * 391 * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If 392 * set to true, destroy only surfaces of removed windows, and clear relevant flags of the 393 * others so that they are ready to be reused. If set to false (common case), destroy all 394 * surfaces that's eligible, if the app is already stopped. 395 */ 396 397 private void destroySurfaces(boolean cleanupOnResume) { 398 final ArrayList<WindowState> allWindows = (ArrayList<WindowState>) allAppWindows.clone(); 399 final DisplayContentList displayList = new DisplayContentList(); 400 for (int i = allWindows.size() - 1; i >= 0; i--) { 401 final WindowState win = allWindows.get(i); 402 403 if (!(mAppStopped || win.mWindowRemovalAllowed || cleanupOnResume)) { 404 continue; 405 } 406 407 win.mWinAnimator.destroyPreservedSurfaceLocked(); 408 409 if (!win.mDestroying) { 410 continue; 411 } 412 413 if (DEBUG_ADD_REMOVE) Slog.e(TAG_WM, "win=" + win 414 + " destroySurfaces: mAppStopped=" + mAppStopped 415 + " win.mWindowRemovalAllowed=" + win.mWindowRemovalAllowed 416 + " win.mRemoveOnExit=" + win.mRemoveOnExit); 417 418 if (!cleanupOnResume || win.mRemoveOnExit) { 419 win.destroyOrSaveSurface(); 420 } 421 if (win.mRemoveOnExit) { 422 service.removeWindowInnerLocked(win); 423 } 424 final DisplayContent displayContent = win.getDisplayContent(); 425 if (displayContent != null && !displayList.contains(displayContent)) { 426 displayList.add(displayContent); 427 } 428 if (cleanupOnResume) { 429 win.requestUpdateWallpaperIfNeeded(); 430 } 431 win.mDestroying = false; 432 } 433 for (int i = 0; i < displayList.size(); i++) { 434 final DisplayContent displayContent = displayList.get(i); 435 service.mLayersController.assignLayersLocked(displayContent.getWindowList()); 436 displayContent.layoutNeeded = true; 437 } 438 } 439 440 /** 441 * Notify that the app is now resumed, and it was not stopped before, perform a clean 442 * up of the surfaces 443 */ 444 void notifyAppResumed(boolean wasStopped, boolean allowSavedSurface) { 445 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped 446 + " allowSavedSurface=" + allowSavedSurface + " " + this); 447 mAppStopped = false; 448 if (!wasStopped) { 449 destroySurfaces(true /*cleanupOnResume*/); 450 } 451 if (!allowSavedSurface) { 452 destroySavedSurfaces(); 453 } 454 } 455 456 /** 457 * Notify that the app has stopped, and it is okay to destroy any surfaces which were 458 * keeping alive in case they were still being used. 459 */ 460 void notifyAppStopped() { 461 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this); 462 mAppStopped = true; 463 destroySurfaces(); 464 // Remove any starting window that was added for this app if they are still around. 465 mTask.mService.scheduleRemoveStartingWindowLocked(this); 466 } 467 468 /** 469 * Checks whether we should save surfaces for this app. 470 * 471 * @return true if the surfaces should be saved, false otherwise. 472 */ 473 boolean shouldSaveSurface() { 474 // We want to save surface if the app's windows are "allDrawn". 475 // (If we started entering animation early with saved surfaces, allDrawn 476 // should have been restored to true. So we'll save again in that case 477 // even if app didn't actually finish drawing.) 478 return allDrawn; 479 } 480 481 boolean canRestoreSurfaces() { 482 for (int i = allAppWindows.size() -1; i >= 0; i--) { 483 final WindowState w = allAppWindows.get(i); 484 if (w.canRestoreSurface()) { 485 return true; 486 } 487 } 488 return false; 489 } 490 491 void clearVisibleBeforeClientHidden() { 492 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 493 final WindowState w = allAppWindows.get(i); 494 w.clearVisibleBeforeClientHidden(); 495 } 496 } 497 498 /** 499 * Whether the app has some window that is invisible in layout, but 500 * animating with saved surface. 501 */ 502 boolean isAnimatingInvisibleWithSavedSurface() { 503 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 504 final WindowState w = allAppWindows.get(i); 505 if (w.isAnimatingInvisibleWithSavedSurface()) { 506 return true; 507 } 508 } 509 return false; 510 } 511 512 /** 513 * Hide all window surfaces that's still invisible in layout but animating 514 * with a saved surface, and mark them destroying. 515 */ 516 void stopUsingSavedSurfaceLocked() { 517 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 518 final WindowState w = allAppWindows.get(i); 519 if (w.isAnimatingInvisibleWithSavedSurface()) { 520 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.d(TAG, 521 "stopUsingSavedSurfaceLocked: " + w); 522 w.clearAnimatingWithSavedSurface(); 523 w.mDestroying = true; 524 w.mWinAnimator.hide("stopUsingSavedSurfaceLocked"); 525 w.mWinAnimator.mWallpaperControllerLocked.hideWallpapers(w); 526 } 527 } 528 destroySurfaces(); 529 } 530 531 void markSavedSurfaceExiting() { 532 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 533 final WindowState w = allAppWindows.get(i); 534 if (w.isAnimatingInvisibleWithSavedSurface()) { 535 w.mAnimatingExit = true; 536 w.mWinAnimator.mAnimating = true; 537 } 538 } 539 } 540 541 void restoreSavedSurfaces() { 542 if (!canRestoreSurfaces()) { 543 clearVisibleBeforeClientHidden(); 544 return; 545 } 546 // Check if we have enough drawn windows to mark allDrawn= true. 547 int numInteresting = 0; 548 int numDrawn = 0; 549 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 550 WindowState w = allAppWindows.get(i); 551 if (w != startingWindow && !w.mAppDied && w.wasVisibleBeforeClientHidden() 552 && (!mAppAnimator.freezingScreen || !w.mAppFreezing)) { 553 numInteresting++; 554 if (w.hasSavedSurface()) { 555 w.restoreSavedSurface(); 556 } 557 if (w.isDrawnLw()) { 558 numDrawn++; 559 } 560 } 561 } 562 563 if (!allDrawn) { 564 allDrawn = (numInteresting > 0) && (numInteresting == numDrawn); 565 if (allDrawn) { 566 service.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget(); 567 } 568 } 569 clearVisibleBeforeClientHidden(); 570 571 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.d(TAG, 572 "restoreSavedSurfaces: " + appWindowToken + " allDrawn=" + allDrawn 573 + " numInteresting=" + numInteresting + " numDrawn=" + numDrawn); 574 } 575 576 void destroySavedSurfaces() { 577 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 578 WindowState win = allAppWindows.get(i); 579 win.destroySavedSurface(); 580 } 581 } 582 583 void clearAllDrawn() { 584 allDrawn = false; 585 deferClearAllDrawn = false; 586 allDrawnExcludingSaved = false; 587 } 588 589 @Override 590 void removeAllWindows() { 591 for (int winNdx = allAppWindows.size() - 1; winNdx >= 0; 592 // removeWindowLocked at bottom of loop may remove multiple entries from 593 // allAppWindows if the window to be removed has child windows. It also may 594 // not remove any windows from allAppWindows at all if win is exiting and 595 // currently animating away. This ensures that winNdx is monotonically decreasing 596 // and never beyond allAppWindows bounds. 597 winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) { 598 WindowState win = allAppWindows.get(winNdx); 599 if (DEBUG_WINDOW_MOVEMENT) { 600 Slog.w(TAG, "removeAllWindows: removing win=" + win); 601 } 602 603 service.removeWindowLocked(win); 604 } 605 allAppWindows.clear(); 606 windows.clear(); 607 } 608 609 void removeAllDeadWindows() { 610 for (int winNdx = allAppWindows.size() - 1; winNdx >= 0; 611 // removeWindowLocked at bottom of loop may remove multiple entries from 612 // allAppWindows if the window to be removed has child windows. It also may 613 // not remove any windows from allAppWindows at all if win is exiting and 614 // currently animating away. This ensures that winNdx is monotonically decreasing 615 // and never beyond allAppWindows bounds. 616 winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) { 617 WindowState win = allAppWindows.get(winNdx); 618 if (win.mAppDied) { 619 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) { 620 Slog.w(TAG, "removeAllDeadWindows: " + win); 621 } 622 // Set mDestroying, we don't want any animation or delayed removal here. 623 win.mDestroying = true; 624 service.removeWindowLocked(win); 625 } 626 } 627 } 628 629 boolean hasWindowsAlive() { 630 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 631 if (!allAppWindows.get(i).mAppDied) { 632 return true; 633 } 634 } 635 return false; 636 } 637 638 void setReplacingWindows(boolean animate) { 639 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + appWindowToken 640 + " with replacing windows."); 641 642 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 643 final WindowState w = allAppWindows.get(i); 644 w.setReplacing(animate); 645 } 646 if (animate) { 647 // Set-up dummy animation so we can start treating windows associated with this 648 // token like they are in transition before the new app window is ready for us to 649 // run the real transition animation. 650 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, 651 "setReplacingWindow() Setting dummy animation on: " + this); 652 mAppAnimator.setDummyAnimation(); 653 } 654 } 655 656 void setReplacingChildren() { 657 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + appWindowToken 658 + " with replacing child windows."); 659 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 660 final WindowState w = allAppWindows.get(i); 661 if (w.shouldBeReplacedWithChildren()) { 662 w.setReplacing(false /* animate */); 663 } 664 } 665 } 666 667 void resetReplacingWindows() { 668 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Resetting app token " + appWindowToken 669 + " of replacing window marks."); 670 671 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 672 final WindowState w = allAppWindows.get(i); 673 w.resetReplacing(); 674 } 675 } 676 677 void requestUpdateWallpaperIfNeeded() { 678 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 679 final WindowState w = allAppWindows.get(i); 680 w.requestUpdateWallpaperIfNeeded(); 681 } 682 } 683 684 boolean isRelaunching() { 685 return mPendingRelaunchCount > 0; 686 } 687 688 void startRelaunching() { 689 if (canFreezeBounds()) { 690 freezeBounds(); 691 } 692 mPendingRelaunchCount++; 693 } 694 695 void finishRelaunching() { 696 if (canFreezeBounds()) { 697 unfreezeBounds(); 698 } 699 if (mPendingRelaunchCount > 0) { 700 mPendingRelaunchCount--; 701 } 702 } 703 704 void clearRelaunching() { 705 if (mPendingRelaunchCount == 0) { 706 return; 707 } 708 if (canFreezeBounds()) { 709 unfreezeBounds(); 710 } 711 mPendingRelaunchCount = 0; 712 } 713 714 void addWindow(WindowState w) { 715 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 716 WindowState candidate = allAppWindows.get(i); 717 if (candidate.mWillReplaceWindow && candidate.mReplacingWindow == null && 718 candidate.getWindowTag().toString().equals(w.getWindowTag().toString())) { 719 candidate.mReplacingWindow = w; 720 w.mSkipEnterAnimationForSeamlessReplacement = !candidate.mAnimateReplacingWindow; 721 722 // if we got a replacement window, reset the timeout to give drawing more time 723 service.scheduleReplacingWindowTimeouts(this); 724 } 725 } 726 allAppWindows.add(w); 727 } 728 729 boolean waitingForReplacement() { 730 for (int i = allAppWindows.size() -1; i >= 0; i--) { 731 WindowState candidate = allAppWindows.get(i); 732 if (candidate.mWillReplaceWindow) { 733 return true; 734 } 735 } 736 return false; 737 } 738 739 void clearTimedoutReplacesLocked() { 740 for (int i = allAppWindows.size() - 1; i >= 0; 741 // removeWindowLocked at bottom of loop may remove multiple entries from 742 // allAppWindows if the window to be removed has child windows. It also may 743 // not remove any windows from allAppWindows at all if win is exiting and 744 // currently animating away. This ensures that winNdx is monotonically decreasing 745 // and never beyond allAppWindows bounds. 746 i = Math.min(i - 1, allAppWindows.size() - 1)) { 747 WindowState candidate = allAppWindows.get(i); 748 if (candidate.mWillReplaceWindow == false) { 749 continue; 750 } 751 candidate.mWillReplaceWindow = false; 752 if (candidate.mReplacingWindow != null) { 753 candidate.mReplacingWindow.mSkipEnterAnimationForSeamlessReplacement = false; 754 } 755 // Since the window already timed out, remove it immediately now. 756 // Use removeWindowInnerLocked() instead of removeWindowLocked(), as the latter 757 // delays removal on certain conditions, which will leave the stale window in the 758 // stack and marked mWillReplaceWindow=false, so the window will never be removed. 759 service.removeWindowInnerLocked(candidate); 760 } 761 } 762 763 private boolean canFreezeBounds() { 764 // For freeform windows, we can't freeze the bounds at the moment because this would make 765 // the resizing unresponsive. 766 return mTask != null && !mTask.inFreeformWorkspace(); 767 } 768 769 /** 770 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds 771 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even 772 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen 773 * with a queue. 774 */ 775 private void freezeBounds() { 776 mFrozenBounds.offer(new Rect(mTask.mPreparedFrozenBounds)); 777 778 if (mTask.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) { 779 // We didn't call prepareFreezingBounds on the task, so use the current value. 780 final Configuration config = new Configuration(service.mCurConfiguration); 781 config.updateFrom(mTask.mOverrideConfig); 782 mFrozenMergedConfig.offer(config); 783 } else { 784 mFrozenMergedConfig.offer(new Configuration(mTask.mPreparedFrozenMergedConfig)); 785 } 786 mTask.mPreparedFrozenMergedConfig.setToDefaults(); 787 } 788 789 /** 790 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}. 791 */ 792 private void unfreezeBounds() { 793 if (!mFrozenBounds.isEmpty()) { 794 mFrozenBounds.remove(); 795 } 796 if (!mFrozenMergedConfig.isEmpty()) { 797 mFrozenMergedConfig.remove(); 798 } 799 for (int i = windows.size() - 1; i >= 0; i--) { 800 final WindowState win = windows.get(i); 801 if (!win.mHasSurface) { 802 continue; 803 } 804 win.mLayoutNeeded = true; 805 win.setDisplayLayoutNeeded(); 806 if (!service.mResizingWindows.contains(win)) { 807 service.mResizingWindows.add(win); 808 } 809 } 810 service.mWindowPlacerLocked.performSurfacePlacement(); 811 } 812 813 void addSurfaceViewBackground(WindowSurfaceController.SurfaceControlWithBackground background) { 814 mSurfaceViewBackgrounds.add(background); 815 } 816 817 void removeSurfaceViewBackground(WindowSurfaceController.SurfaceControlWithBackground background) { 818 mSurfaceViewBackgrounds.remove(background); 819 updateSurfaceViewBackgroundVisibilities(); 820 } 821 822 // We use DimLayers behind SurfaceViews to prevent holes while resizing and creating. 823 // However, we need to ensure one SurfaceView doesn't cover another when they are both placed 824 // below the main app window (as traditionally a SurfaceView which is never drawn 825 // to is totally translucent). So we look at all our SurfaceView backgrounds and only enable 826 // the background for the SurfaceView with lowest Z order 827 void updateSurfaceViewBackgroundVisibilities() { 828 WindowSurfaceController.SurfaceControlWithBackground bottom = null; 829 int bottomLayer = Integer.MAX_VALUE; 830 for (int i = 0; i < mSurfaceViewBackgrounds.size(); i++) { 831 WindowSurfaceController.SurfaceControlWithBackground sc = mSurfaceViewBackgrounds.get(i); 832 if (sc.mVisible && sc.mLayer < bottomLayer) { 833 bottomLayer = sc.mLayer; 834 bottom = sc; 835 } 836 } 837 for (int i = 0; i < mSurfaceViewBackgrounds.size(); i++) { 838 WindowSurfaceController.SurfaceControlWithBackground sc = mSurfaceViewBackgrounds.get(i); 839 sc.updateBackgroundVisibility(sc != bottom); 840 } 841 } 842 843 /** 844 * See {@link WindowManagerService#overridePlayingAppAnimationsLw} 845 */ 846 void overridePlayingAppAnimations(Animation a) { 847 if (mAppAnimator.isAnimating()) { 848 final WindowState win = findMainWindow(); 849 if (win == null) { 850 return; 851 } 852 final int width = win.mContainingFrame.width(); 853 final int height = win.mContainingFrame.height(); 854 mAppAnimator.setAnimation(a, width, height, false, STACK_CLIP_NONE); 855 } 856 } 857 858 @Override 859 void dump(PrintWriter pw, String prefix) { 860 super.dump(pw, prefix); 861 if (appToken != null) { 862 pw.print(prefix); pw.print("app=true voiceInteraction="); pw.println(voiceInteraction); 863 } 864 if (allAppWindows.size() > 0) { 865 pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows); 866 } 867 pw.print(prefix); pw.print("task="); pw.println(mTask); 868 pw.print(prefix); pw.print(" appFullscreen="); pw.print(appFullscreen); 869 pw.print(" requestedOrientation="); pw.println(requestedOrientation); 870 pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested); 871 pw.print(" clientHidden="); pw.print(clientHidden); 872 pw.print(" reportedDrawn="); pw.print(reportedDrawn); 873 pw.print(" reportedVisible="); pw.println(reportedVisible); 874 if (paused) { 875 pw.print(prefix); pw.print("paused="); pw.println(paused); 876 } 877 if (mAppStopped) { 878 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped); 879 } 880 if (numInterestingWindows != 0 || numDrawnWindows != 0 881 || allDrawn || mAppAnimator.allDrawn) { 882 pw.print(prefix); pw.print("numInterestingWindows="); 883 pw.print(numInterestingWindows); 884 pw.print(" numDrawnWindows="); pw.print(numDrawnWindows); 885 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction); 886 pw.print(" allDrawn="); pw.print(allDrawn); 887 pw.print(" (animator="); pw.print(mAppAnimator.allDrawn); 888 pw.println(")"); 889 } 890 if (inPendingTransaction) { 891 pw.print(prefix); pw.print("inPendingTransaction="); 892 pw.println(inPendingTransaction); 893 } 894 if (startingData != null || removed || firstWindowDrawn || mIsExiting) { 895 pw.print(prefix); pw.print("startingData="); pw.print(startingData); 896 pw.print(" removed="); pw.print(removed); 897 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn); 898 pw.print(" mIsExiting="); pw.println(mIsExiting); 899 } 900 if (startingWindow != null || startingView != null 901 || startingDisplayed || startingMoved) { 902 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow); 903 pw.print(" startingView="); pw.print(startingView); 904 pw.print(" startingDisplayed="); pw.print(startingDisplayed); 905 pw.print(" startingMoved="); pw.println(startingMoved); 906 } 907 if (!mFrozenBounds.isEmpty()) { 908 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds); 909 pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig); 910 } 911 if (mPendingRelaunchCount != 0) { 912 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount); 913 } 914 } 915 916 @Override 917 public String toString() { 918 if (stringName == null) { 919 StringBuilder sb = new StringBuilder(); 920 sb.append("AppWindowToken{"); 921 sb.append(Integer.toHexString(System.identityHashCode(this))); 922 sb.append(" token="); sb.append(token); sb.append('}'); 923 stringName = sb.toString(); 924 } 925 return stringName; 926 } 927 } 928