AppWindowToken.java revision 32de365bd82a748cc366aee50d281faca9d44815
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 17package com.android.server.wm; 18 19import static android.app.ActivityManager.StackId; 20import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 21import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 22import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS; 23import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 24import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW; 25import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 26import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT; 27import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 28import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 29import static com.android.server.wm.WindowManagerService.WINDOW_REPLACEMENT_TIMEOUT_DURATION; 30import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN; 31 32import com.android.server.input.InputApplicationHandle; 33import com.android.server.wm.WindowManagerService.H; 34 35import android.annotation.NonNull; 36import android.content.pm.ActivityInfo; 37import android.graphics.Rect; 38import android.os.Message; 39import android.os.RemoteException; 40import android.util.Slog; 41import android.view.IApplicationToken; 42import android.view.View; 43import android.view.WindowManager; 44 45import java.io.PrintWriter; 46import java.util.ArrayDeque; 47import java.util.ArrayList; 48 49class AppTokenList extends ArrayList<AppWindowToken> { 50} 51 52/** 53 * Version of WindowToken that is specifically for a particular application (or 54 * really activity) that is displaying windows. 55 */ 56class AppWindowToken extends WindowToken { 57 private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM; 58 59 // Non-null only for application tokens. 60 final IApplicationToken appToken; 61 62 // All of the windows and child windows that are included in this 63 // application token. Note this list is NOT sorted! 64 final WindowList allAppWindows = new WindowList(); 65 @NonNull final AppWindowAnimator mAppAnimator; 66 67 final boolean voiceInteraction; 68 69 Task mTask; 70 boolean appFullscreen; 71 int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 72 boolean layoutConfigChanges; 73 boolean showForAllUsers; 74 75 // The input dispatching timeout for this application token in nanoseconds. 76 long inputDispatchingTimeoutNanos; 77 78 // These are used for determining when all windows associated with 79 // an activity have been drawn, so they can be made visible together 80 // at the same time. 81 // initialize so that it doesn't match mTransactionSequence which is an int. 82 long lastTransactionSequence = Long.MIN_VALUE; 83 int numInterestingWindows; 84 int numDrawnWindows; 85 boolean inPendingTransaction; 86 boolean allDrawn; 87 // Set to true when this app creates a surface while in the middle of an animation. In that 88 // case do not clear allDrawn until the animation completes. 89 boolean deferClearAllDrawn; 90 91 // Is this window's surface needed? This is almost like hidden, except 92 // it will sometimes be true a little earlier: when the token has 93 // been shown, but is still waiting for its app transition to execute 94 // before making its windows shown. 95 boolean hiddenRequested; 96 97 // Have we told the window clients to hide themselves? 98 boolean clientHidden; 99 100 // Last visibility state we reported to the app token. 101 boolean reportedVisible; 102 103 // Last drawn state we reported to the app token. 104 boolean reportedDrawn; 105 106 // Set to true when the token has been removed from the window mgr. 107 boolean removed; 108 109 // Information about an application starting window if displayed. 110 StartingData startingData; 111 WindowState startingWindow; 112 View startingView; 113 boolean startingDisplayed; 114 boolean startingMoved; 115 boolean firstWindowDrawn; 116 117 // Input application handle used by the input dispatcher. 118 final InputApplicationHandle mInputApplicationHandle; 119 120 boolean mIsExiting; 121 122 boolean mLaunchTaskBehind; 123 boolean mEnteringAnimation; 124 125 boolean mAlwaysFocusable; 126 127 boolean mAppStopped; 128 int mPendingRelaunchCount; 129 130 ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>(); 131 132 AppWindowToken(WindowManagerService _service, IApplicationToken _token, 133 boolean _voiceInteraction) { 134 super(_service, _token.asBinder(), 135 WindowManager.LayoutParams.TYPE_APPLICATION, true); 136 appWindowToken = this; 137 appToken = _token; 138 voiceInteraction = _voiceInteraction; 139 mInputApplicationHandle = new InputApplicationHandle(this); 140 mAppAnimator = new AppWindowAnimator(this); 141 } 142 143 void sendAppVisibilityToClients() { 144 final int N = allAppWindows.size(); 145 for (int i=0; i<N; i++) { 146 WindowState win = allAppWindows.get(i); 147 if (win == startingWindow && clientHidden) { 148 // Don't hide the starting window. 149 continue; 150 } 151 try { 152 if (DEBUG_VISIBILITY) Slog.v(TAG, 153 "Setting visibility of " + win + ": " + (!clientHidden)); 154 win.mClient.dispatchAppVisibility(!clientHidden); 155 } catch (RemoteException e) { 156 } 157 } 158 } 159 160 void setVisibleBeforeClientHidden() { 161 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 162 final WindowState w = allAppWindows.get(i); 163 w.setVisibleBeforeClientHidden(); 164 } 165 } 166 167 void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) { 168 firstWindowDrawn = true; 169 170 // We now have a good window to show, remove dead placeholders 171 removeAllDeadWindows(); 172 173 if (startingData != null) { 174 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting " 175 + win.mToken + ": first real window is shown, no animation"); 176 // If this initial window is animating, stop it -- we will do an animation to reveal 177 // it from behind the starting window, so there is no need for it to also be doing its 178 // own stuff. 179 winAnimator.clearAnimation(); 180 winAnimator.mService.mFinishedStarting.add(this); 181 winAnimator.mService.mH.sendEmptyMessage(H.FINISHED_STARTING); 182 } 183 updateReportedVisibilityLocked(); 184 } 185 186 void updateReportedVisibilityLocked() { 187 if (appToken == null) { 188 return; 189 } 190 191 int numInteresting = 0; 192 int numVisible = 0; 193 int numDrawn = 0; 194 boolean nowGone = true; 195 196 if (DEBUG_VISIBILITY) Slog.v(TAG, 197 "Update reported visibility: " + this); 198 final int N = allAppWindows.size(); 199 for (int i=0; i<N; i++) { 200 WindowState win = allAppWindows.get(i); 201 if (win == startingWindow || win.mAppFreezing 202 || win.mViewVisibility != View.VISIBLE 203 || win.mAttrs.type == TYPE_APPLICATION_STARTING 204 || win.mDestroying) { 205 continue; 206 } 207 if (DEBUG_VISIBILITY) { 208 Slog.v(TAG, "Win " + win + ": isDrawn=" 209 + win.isDrawnLw() 210 + ", isAnimationSet=" + win.mWinAnimator.isAnimationSet()); 211 if (!win.isDrawnLw()) { 212 Slog.v(TAG, "Not displayed: s=" + 213 win.mWinAnimator.mSurfaceController 214 + " pv=" + win.mPolicyVisibility 215 + " mDrawState=" + win.mWinAnimator.mDrawState 216 + " ah=" + win.mAttachedHidden 217 + " th=" 218 + (win.mAppToken != null 219 ? win.mAppToken.hiddenRequested : false) 220 + " a=" + win.mWinAnimator.mAnimating); 221 } 222 } 223 numInteresting++; 224 if (win.isDrawnLw()) { 225 numDrawn++; 226 if (!win.mWinAnimator.isAnimationSet()) { 227 numVisible++; 228 } 229 nowGone = false; 230 } else if (win.mWinAnimator.isAnimationSet()) { 231 nowGone = false; 232 } 233 } 234 235 boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting; 236 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting; 237 if (!nowGone) { 238 // If the app is not yet gone, then it can only become visible/drawn. 239 if (!nowDrawn) { 240 nowDrawn = reportedDrawn; 241 } 242 if (!nowVisible) { 243 nowVisible = reportedVisible; 244 } 245 } 246 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting=" 247 + numInteresting + " visible=" + numVisible); 248 if (nowDrawn != reportedDrawn) { 249 if (nowDrawn) { 250 Message m = service.mH.obtainMessage( 251 H.REPORT_APPLICATION_TOKEN_DRAWN, this); 252 service.mH.sendMessage(m); 253 } 254 reportedDrawn = nowDrawn; 255 } 256 if (nowVisible != reportedVisible) { 257 if (DEBUG_VISIBILITY) Slog.v( 258 TAG, "Visibility changed in " + this 259 + ": vis=" + nowVisible); 260 reportedVisible = nowVisible; 261 Message m = service.mH.obtainMessage( 262 H.REPORT_APPLICATION_TOKEN_WINDOWS, 263 nowVisible ? 1 : 0, 264 nowGone ? 1 : 0, 265 this); 266 service.mH.sendMessage(m); 267 } 268 } 269 270 WindowState findMainWindow() { 271 WindowState candidate = null; 272 int j = windows.size(); 273 while (j > 0) { 274 j--; 275 WindowState win = windows.get(j); 276 if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION 277 || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { 278 // In cases where there are multiple windows, we prefer the non-exiting window. This 279 // happens for example when replacing windows during an activity relaunch. When 280 // constructing the animation, we want the new window, not the exiting one. 281 if (win.mAnimatingExit) { 282 candidate = win; 283 } else { 284 return win; 285 } 286 } 287 } 288 return candidate; 289 } 290 291 boolean windowsAreFocusable() { 292 return StackId.canReceiveKeys(mTask.mStack.mStackId) || mAlwaysFocusable; 293 } 294 295 boolean isVisible() { 296 final int N = allAppWindows.size(); 297 for (int i=0; i<N; i++) { 298 WindowState win = allAppWindows.get(i); 299 // If we're animating with a saved surface, we're already visible. 300 // Return true so that the alpha doesn't get cleared. 301 if (!win.mAppFreezing 302 && (win.mViewVisibility == View.VISIBLE || win.isAnimatingWithSavedSurface() 303 || (win.mWinAnimator.isAnimationSet() 304 && !service.mAppTransition.isTransitionSet())) 305 && !win.mDestroying 306 && win.isDrawnLw()) { 307 return true; 308 } 309 } 310 return false; 311 } 312 313 void removeAppFromTaskLocked() { 314 mIsExiting = false; 315 removeAllWindows(); 316 317 // Use local variable because removeAppToken will null out mTask. 318 final Task task = mTask; 319 if (task != null) { 320 if (!task.removeAppToken(this)) { 321 Slog.e(TAG, "removeAppFromTaskLocked: token=" + this 322 + " not found."); 323 } 324 task.mStack.mExitingAppTokens.remove(this); 325 } 326 } 327 328 // Here we destroy surfaces which have been marked as eligible by the animator, taking care 329 // to ensure the client has finished with them. If the client could still be using them 330 // we will skip destruction and try again when the client has stopped. 331 void destroySurfaces() { 332 final ArrayList<WindowState> allWindows = (ArrayList<WindowState>) allAppWindows.clone(); 333 final DisplayContentList displayList = new DisplayContentList(); 334 for (int i = allWindows.size() - 1; i >= 0; i--) { 335 final WindowState win = allWindows.get(i); 336 337 if (!(mAppStopped || win.mWindowRemovalAllowed)) { 338 continue; 339 } 340 341 win.mWinAnimator.destroyPreservedSurfaceLocked(); 342 343 if (!win.mDestroying) { 344 continue; 345 } 346 347 if (DEBUG_ADD_REMOVE) Slog.e(TAG_WM, "win=" + win 348 + " destroySurfaces: mAppStopped=" + mAppStopped 349 + " win.mWindowRemovalAllowed=" + win.mWindowRemovalAllowed 350 + " win.mRemoveOnExit=" + win.mRemoveOnExit); 351 352 win.destroyOrSaveSurface(); 353 if (win.mRemoveOnExit) { 354 service.removeWindowInnerLocked(win); 355 } 356 final DisplayContent displayContent = win.getDisplayContent(); 357 if (displayContent != null && !displayList.contains(displayContent)) { 358 displayList.add(displayContent); 359 } 360 win.mDestroying = false; 361 } 362 for (int i = 0; i < displayList.size(); i++) { 363 final DisplayContent displayContent = displayList.get(i); 364 service.mLayersController.assignLayersLocked(displayContent.getWindowList()); 365 displayContent.layoutNeeded = true; 366 } 367 } 368 369 /** 370 * If the application has stopped it is okay to destroy any surfaces which were keeping alive 371 * in case they were still being used. 372 */ 373 void notifyAppStopped(boolean stopped) { 374 if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: stopped=" + stopped + " " + this); 375 mAppStopped = stopped; 376 377 if (stopped) { 378 destroySurfaces(); 379 // Remove any starting window that was added for this app if they are still around. 380 mTask.mService.scheduleRemoveStartingWindowLocked(this); 381 } 382 } 383 384 /** 385 * Checks whether we should save surfaces for this app. 386 * 387 * @return true if the surfaces should be saved, false otherwise. 388 */ 389 boolean shouldSaveSurface() { 390 // We want to save surface if the app's windows are "allDrawn". 391 // (If we started entering animation early with saved surfaces, allDrawn 392 // should have been restored to true. So we'll save again in that case 393 // even if app didn't actually finish drawing.) 394 return allDrawn; 395 } 396 397 boolean canRestoreSurfaces() { 398 for (int i = allAppWindows.size() -1; i >= 0; i--) { 399 final WindowState w = allAppWindows.get(i); 400 if (w.canRestoreSurface()) { 401 return true; 402 } 403 } 404 return false; 405 } 406 407 void clearVisibleBeforeClientHidden() { 408 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 409 final WindowState w = allAppWindows.get(i); 410 w.clearVisibleBeforeClientHidden(); 411 } 412 } 413 414 void restoreSavedSurfaces() { 415 if (!canRestoreSurfaces()) { 416 clearVisibleBeforeClientHidden(); 417 return; 418 } 419 // Check if we have enough drawn windows to mark allDrawn= true. 420 int numInteresting = 0; 421 int numDrawn = 0; 422 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 423 WindowState w = allAppWindows.get(i); 424 if (w != startingWindow && !w.mAppDied && w.wasVisibleBeforeClientHidden() 425 && (!mAppAnimator.freezingScreen || !w.mAppFreezing)) { 426 numInteresting++; 427 if (w.hasSavedSurface()) { 428 w.restoreSavedSurface(); 429 } 430 if (w.isDrawnLw()) { 431 numDrawn++; 432 } 433 } 434 } 435 436 if (!allDrawn) { 437 allDrawn = (numInteresting > 0) && (numInteresting == numDrawn); 438 if (allDrawn) { 439 service.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget(); 440 } 441 } 442 clearVisibleBeforeClientHidden(); 443 444 if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.d(TAG, 445 "restoreSavedSurfaces: " + appWindowToken + " allDrawn=" + allDrawn 446 + " numInteresting=" + numInteresting + " numDrawn=" + numDrawn); 447 } 448 449 void destroySavedSurfaces() { 450 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 451 WindowState win = allAppWindows.get(i); 452 win.destroySavedSurface(); 453 } 454 } 455 456 void clearAllDrawn() { 457 allDrawn = false; 458 deferClearAllDrawn = false; 459 } 460 461 @Override 462 void removeAllWindows() { 463 for (int winNdx = allAppWindows.size() - 1; winNdx >= 0; 464 // removeWindowLocked at bottom of loop may remove multiple entries from 465 // allAppWindows if the window to be removed has child windows. It also may 466 // not remove any windows from allAppWindows at all if win is exiting and 467 // currently animating away. This ensures that winNdx is monotonically decreasing 468 // and never beyond allAppWindows bounds. 469 winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) { 470 WindowState win = allAppWindows.get(winNdx); 471 if (DEBUG_WINDOW_MOVEMENT) { 472 Slog.w(TAG, "removeAllWindows: removing win=" + win); 473 } 474 475 service.removeWindowLocked(win); 476 } 477 allAppWindows.clear(); 478 windows.clear(); 479 } 480 481 void removeAllDeadWindows() { 482 for (int winNdx = allAppWindows.size() - 1; winNdx >= 0; 483 // removeWindowLocked at bottom of loop may remove multiple entries from 484 // allAppWindows if the window to be removed has child windows. It also may 485 // not remove any windows from allAppWindows at all if win is exiting and 486 // currently animating away. This ensures that winNdx is monotonically decreasing 487 // and never beyond allAppWindows bounds. 488 winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) { 489 WindowState win = allAppWindows.get(winNdx); 490 if (win.mAppDied) { 491 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) { 492 Slog.w(TAG, "removeAllDeadWindows: " + win); 493 } 494 // Set mDestroying, we don't want any animation or delayed removal here. 495 win.mDestroying = true; 496 service.removeWindowLocked(win); 497 } 498 } 499 } 500 501 boolean hasWindowsAlive() { 502 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 503 if (!allAppWindows.get(i).mAppDied) { 504 return true; 505 } 506 } 507 return false; 508 } 509 510 void setReplacingWindows(boolean animate) { 511 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + appWindowToken 512 + " with replacing windows."); 513 514 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 515 final WindowState w = allAppWindows.get(i); 516 w.setReplacing(animate); 517 } 518 if (animate) { 519 // Set-up dummy animation so we can start treating windows associated with this 520 // token like they are in transition before the new app window is ready for us to 521 // run the real transition animation. 522 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, 523 "setReplacingWindow() Setting dummy animation on: " + this); 524 mAppAnimator.setDummyAnimation(); 525 } 526 } 527 528 void setReplacingChildren() { 529 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + appWindowToken 530 + " with replacing child windows."); 531 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 532 final WindowState w = allAppWindows.get(i); 533 if (w.shouldBeReplacedWithChildren()) { 534 w.setReplacing(false /* animate */); 535 } 536 } 537 } 538 539 void resetReplacingWindows() { 540 if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Resetting app token " + appWindowToken 541 + " of replacing window marks."); 542 543 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 544 final WindowState w = allAppWindows.get(i); 545 w.resetReplacing(); 546 } 547 } 548 549 void requestUpdateWallpaperIfNeeded() { 550 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 551 final WindowState w = allAppWindows.get(i); 552 w.requestUpdateWallpaperIfNeeded(); 553 } 554 } 555 556 boolean isRelaunching() { 557 return mPendingRelaunchCount > 0; 558 } 559 560 void startRelaunching() { 561 if (canFreezeBounds()) { 562 freezeBounds(); 563 } 564 mPendingRelaunchCount++; 565 } 566 567 void finishRelaunching() { 568 if (canFreezeBounds()) { 569 unfreezeBounds(); 570 } 571 if (mPendingRelaunchCount > 0) { 572 mPendingRelaunchCount--; 573 } 574 } 575 576 void addWindow(WindowState w) { 577 for (int i = allAppWindows.size() - 1; i >= 0; i--) { 578 WindowState candidate = allAppWindows.get(i); 579 if (candidate.mWillReplaceWindow && candidate.mReplacingWindow == null && 580 candidate.getWindowTag().toString().equals(w.getWindowTag().toString())) { 581 candidate.mReplacingWindow = w; 582 w.mSkipEnterAnimationForSeamlessReplacement = !candidate.mAnimateReplacingWindow; 583 584 // if we got a replacement window, reset the timeout to give drawing more time 585 service.scheduleReplacingWindowTimeouts(this); 586 } 587 } 588 allAppWindows.add(w); 589 } 590 591 boolean waitingForReplacement() { 592 for (int i = allAppWindows.size() -1; i >= 0; i--) { 593 WindowState candidate = allAppWindows.get(i); 594 if (candidate.mWillReplaceWindow) { 595 return true; 596 } 597 } 598 return false; 599 } 600 601 void clearTimedoutReplacesLocked() { 602 for (int i = allAppWindows.size() - 1; i >= 0; 603 // removeWindowLocked at bottom of loop may remove multiple entries from 604 // allAppWindows if the window to be removed has child windows. It also may 605 // not remove any windows from allAppWindows at all if win is exiting and 606 // currently animating away. This ensures that winNdx is monotonically decreasing 607 // and never beyond allAppWindows bounds. 608 i = Math.min(i - 1, allAppWindows.size() - 1)) { 609 WindowState candidate = allAppWindows.get(i); 610 if (candidate.mWillReplaceWindow == false) { 611 continue; 612 } 613 candidate.mWillReplaceWindow = false; 614 if (candidate.mReplacingWindow != null) { 615 candidate.mReplacingWindow.mSkipEnterAnimationForSeamlessReplacement = false; 616 } 617 // Since the window already timed out, remove it immediately now. 618 // Use removeWindowInnerLocked() instead of removeWindowLocked(), as the latter 619 // delays removal on certain conditions, which will leave the stale window in the 620 // stack and marked mWillReplaceWindow=false, so the window will never be removed. 621 service.removeWindowInnerLocked(candidate); 622 } 623 } 624 625 private boolean canFreezeBounds() { 626 // For freeform windows, we can't freeze the bounds at the moment because this would make 627 // the resizing unresponsive. 628 return mTask != null && !mTask.inFreeformWorkspace(); 629 } 630 631 /** 632 * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds 633 * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even 634 * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen 635 * with a queue. 636 */ 637 private void freezeBounds() { 638 mFrozenBounds.offer(new Rect(mTask.mPreparedFrozenBounds)); 639 } 640 641 /** 642 * Unfreezes the previously frozen bounds. See {@link #freezeBounds}. 643 */ 644 private void unfreezeBounds() { 645 mFrozenBounds.remove(); 646 for (int i = windows.size() - 1; i >= 0; i--) { 647 final WindowState win = windows.get(i); 648 if (!win.mHasSurface) { 649 continue; 650 } 651 win.mLayoutNeeded = true; 652 win.setDisplayLayoutNeeded(); 653 if (!service.mResizingWindows.contains(win)) { 654 service.mResizingWindows.add(win); 655 } 656 } 657 service.mWindowPlacerLocked.performSurfacePlacement(); 658 } 659 660 @Override 661 void dump(PrintWriter pw, String prefix) { 662 super.dump(pw, prefix); 663 if (appToken != null) { 664 pw.print(prefix); pw.print("app=true voiceInteraction="); pw.println(voiceInteraction); 665 } 666 if (allAppWindows.size() > 0) { 667 pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows); 668 } 669 pw.print(prefix); pw.print("task="); pw.println(mTask); 670 pw.print(prefix); pw.print(" appFullscreen="); pw.print(appFullscreen); 671 pw.print(" requestedOrientation="); pw.println(requestedOrientation); 672 pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested); 673 pw.print(" clientHidden="); pw.print(clientHidden); 674 pw.print(" reportedDrawn="); pw.print(reportedDrawn); 675 pw.print(" reportedVisible="); pw.println(reportedVisible); 676 if (paused) { 677 pw.print(prefix); pw.print("paused="); pw.println(paused); 678 } 679 if (mAppStopped) { 680 pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped); 681 } 682 if (numInterestingWindows != 0 || numDrawnWindows != 0 683 || allDrawn || mAppAnimator.allDrawn) { 684 pw.print(prefix); pw.print("numInterestingWindows="); 685 pw.print(numInterestingWindows); 686 pw.print(" numDrawnWindows="); pw.print(numDrawnWindows); 687 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction); 688 pw.print(" allDrawn="); pw.print(allDrawn); 689 pw.print(" (animator="); pw.print(mAppAnimator.allDrawn); 690 pw.println(")"); 691 } 692 if (inPendingTransaction) { 693 pw.print(prefix); pw.print("inPendingTransaction="); 694 pw.println(inPendingTransaction); 695 } 696 if (startingData != null || removed || firstWindowDrawn || mIsExiting) { 697 pw.print(prefix); pw.print("startingData="); pw.print(startingData); 698 pw.print(" removed="); pw.print(removed); 699 pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn); 700 pw.print(" mIsExiting="); pw.println(mIsExiting); 701 } 702 if (startingWindow != null || startingView != null 703 || startingDisplayed || startingMoved) { 704 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow); 705 pw.print(" startingView="); pw.print(startingView); 706 pw.print(" startingDisplayed="); pw.print(startingDisplayed); 707 pw.print(" startingMoved="); pw.println(startingMoved); 708 } 709 if (!mFrozenBounds.isEmpty()) { 710 pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds); 711 } 712 if (mPendingRelaunchCount != 0) { 713 pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount); 714 } 715 } 716 717 @Override 718 public String toString() { 719 if (stringName == null) { 720 StringBuilder sb = new StringBuilder(); 721 sb.append("AppWindowToken{"); 722 sb.append(Integer.toHexString(System.identityHashCode(this))); 723 sb.append(" token="); sb.append(token); sb.append('}'); 724 stringName = sb.toString(); 725 } 726 return stringName; 727 } 728} 729