WindowStateAnimator.java revision d7f6e7c7694305c3231a575cf709ba13075bfe48
1/* 2 * Copyright (C) 2014 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.view.Display.DEFAULT_DISPLAY; 20import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; 21import static android.view.WindowManager.LayoutParams.FLAG_SCALED; 22import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 23import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; 24import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM; 25import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; 26import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 27import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS; 28import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; 29import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; 30import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW; 31import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE; 32import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; 33import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER; 34import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_CROP; 35import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; 36import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC; 37import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; 38import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 39import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 40import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER; 41import static com.android.server.wm.WindowManagerService.localLOGV; 42import static com.android.server.wm.WindowManagerService.logWithStack; 43import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE; 44import static com.android.server.wm.WindowSurfacePlacer.SET_TURN_ON_SCREEN; 45 46import android.content.Context; 47import android.graphics.Matrix; 48import android.graphics.PixelFormat; 49import android.graphics.Point; 50import android.graphics.Rect; 51import android.graphics.Region; 52import android.os.Debug; 53import android.os.RemoteException; 54import android.util.Slog; 55import android.view.DisplayInfo; 56import android.view.MagnificationSpec; 57import android.view.Surface.OutOfResourcesException; 58import android.view.SurfaceControl; 59import android.view.WindowManager; 60import android.view.WindowManager.LayoutParams; 61import android.view.WindowManagerPolicy; 62import android.view.animation.Animation; 63import android.view.animation.AnimationSet; 64import android.view.animation.AnimationUtils; 65import android.view.animation.Transformation; 66 67import com.android.server.wm.WindowManagerService.H; 68 69import java.io.PrintWriter; 70 71/** 72 * Keep track of animations and surface operations for a single WindowState. 73 **/ 74class WindowStateAnimator { 75 static final String TAG = TAG_WITH_CLASS_NAME ? "WindowStateAnimator" : TAG_WM; 76 static final int WINDOW_FREEZE_LAYER = TYPE_LAYER_MULTIPLIER * 200; 77 78 /** 79 * Mode how the window gets clipped by the stack bounds during an animation: The clipping should 80 * be applied after applying the animation transformation, i.e. the stack bounds don't move 81 * during the animation. 82 */ 83 static final int STACK_CLIP_AFTER_ANIM = 0; 84 85 /** 86 * Mode how the window gets clipped by the stack bounds: The clipping should be applied before 87 * applying the animation transformation, i.e. the stack bounds move with the window. 88 */ 89 static final int STACK_CLIP_BEFORE_ANIM = 1; 90 91 /** 92 * Mode how window gets clipped by the stack bounds during an animation: Don't clip the window 93 * by the stack bounds. 94 */ 95 static final int STACK_CLIP_NONE = 2; 96 97 // Unchanging local convenience fields. 98 final WindowManagerService mService; 99 final WindowState mWin; 100 final WindowStateAnimator mAttachedWinAnimator; 101 final WindowAnimator mAnimator; 102 AppWindowAnimator mAppAnimator; 103 final Session mSession; 104 final WindowManagerPolicy mPolicy; 105 final Context mContext; 106 final boolean mIsWallpaper; 107 final WallpaperController mWallpaperControllerLocked; 108 109 // Currently running animation. 110 boolean mAnimating; 111 boolean mLocalAnimating; 112 Animation mAnimation; 113 boolean mAnimationIsEntrance; 114 boolean mHasTransformation; 115 boolean mHasLocalTransformation; 116 final Transformation mTransformation = new Transformation(); 117 boolean mWasAnimating; // Were we animating going into the most recent animation step? 118 int mAnimLayer; 119 int mLastLayer; 120 long mAnimationStartTime; 121 long mLastAnimationTime; 122 int mStackClip = STACK_CLIP_BEFORE_ANIM; 123 124 /** 125 * Set when we have changed the size of the surface, to know that 126 * we must tell them application to resize (and thus redraw itself). 127 */ 128 boolean mSurfaceResized; 129 /** 130 * Whether we should inform the client on next relayoutWindow that 131 * the surface has been resized since last time. 132 */ 133 boolean mReportSurfaceResized; 134 WindowSurfaceController mSurfaceController; 135 private WindowSurfaceController mPendingDestroySurface; 136 137 /** 138 * Set if the client has asked that the destroy of its surface be delayed 139 * until it explicitly says it is okay. 140 */ 141 boolean mSurfaceDestroyDeferred; 142 143 private boolean mDestroyPreservedSurfaceUponRedraw; 144 float mShownAlpha = 0; 145 float mAlpha = 0; 146 float mLastAlpha = 0; 147 148 boolean mHasClipRect; 149 Rect mClipRect = new Rect(); 150 Rect mTmpClipRect = new Rect(); 151 Rect mTmpFinalClipRect = new Rect(); 152 Rect mLastClipRect = new Rect(); 153 Rect mLastFinalClipRect = new Rect(); 154 Rect mTmpStackBounds = new Rect(); 155 156 /** 157 * This is rectangle of the window's surface that is not covered by 158 * system decorations. 159 */ 160 private final Rect mSystemDecorRect = new Rect(); 161 private final Rect mLastSystemDecorRect = new Rect(); 162 163 // Used to save animation distances between the time they are calculated and when they are used. 164 private int mAnimDx; 165 private int mAnimDy; 166 167 /** Is the next animation to be started a window move animation? */ 168 private boolean mAnimateMove = false; 169 170 float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1; 171 float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1; 172 173 boolean mHaveMatrix; 174 175 // Set to true if, when the window gets displayed, it should perform 176 // an enter animation. 177 boolean mEnterAnimationPending; 178 179 /** Used to indicate that this window is undergoing an enter animation. Used for system 180 * windows to make the callback to View.dispatchOnWindowShownCallback(). Set when the 181 * window is first added or shown, cleared when the callback has been made. */ 182 boolean mEnteringAnimation; 183 184 boolean mKeyguardGoingAwayAnimation; 185 boolean mKeyguardGoingAwayWithWallpaper; 186 187 /** The pixel format of the underlying SurfaceControl */ 188 int mSurfaceFormat; 189 190 /** This is set when there is no Surface */ 191 static final int NO_SURFACE = 0; 192 /** This is set after the Surface has been created but before the window has been drawn. During 193 * this time the surface is hidden. */ 194 static final int DRAW_PENDING = 1; 195 /** This is set after the window has finished drawing for the first time but before its surface 196 * is shown. The surface will be displayed when the next layout is run. */ 197 static final int COMMIT_DRAW_PENDING = 2; 198 /** This is set during the time after the window's drawing has been committed, and before its 199 * surface is actually shown. It is used to delay showing the surface until all windows in a 200 * token are ready to be shown. */ 201 static final int READY_TO_SHOW = 3; 202 /** Set when the window has been shown in the screen the first time. */ 203 static final int HAS_DRAWN = 4; 204 205 String drawStateToString() { 206 switch (mDrawState) { 207 case NO_SURFACE: return "NO_SURFACE"; 208 case DRAW_PENDING: return "DRAW_PENDING"; 209 case COMMIT_DRAW_PENDING: return "COMMIT_DRAW_PENDING"; 210 case READY_TO_SHOW: return "READY_TO_SHOW"; 211 case HAS_DRAWN: return "HAS_DRAWN"; 212 default: return Integer.toString(mDrawState); 213 } 214 } 215 int mDrawState; 216 217 /** Was this window last hidden? */ 218 boolean mLastHidden; 219 220 int mAttrType; 221 222 private final Rect mTmpSize = new Rect(); 223 224 WindowStateAnimator(final WindowState win) { 225 final WindowManagerService service = win.mService; 226 227 mService = service; 228 mAnimator = service.mAnimator; 229 mPolicy = service.mPolicy; 230 mContext = service.mContext; 231 final DisplayContent displayContent = win.getDisplayContent(); 232 if (displayContent != null) { 233 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 234 mAnimDx = displayInfo.appWidth; 235 mAnimDy = displayInfo.appHeight; 236 } else { 237 Slog.w(TAG, "WindowStateAnimator ctor: Display has been removed"); 238 // This is checked on return and dealt with. 239 } 240 241 mWin = win; 242 mAttachedWinAnimator = win.mAttachedWindow == null 243 ? null : win.mAttachedWindow.mWinAnimator; 244 mAppAnimator = win.mAppToken == null ? null : win.mAppToken.mAppAnimator; 245 mSession = win.mSession; 246 mAttrType = win.mAttrs.type; 247 mIsWallpaper = win.mIsWallpaper; 248 mWallpaperControllerLocked = mService.mWallpaperControllerLocked; 249 } 250 251 public void setAnimation(Animation anim, long startTime, int stackClip) { 252 if (localLOGV) Slog.v(TAG, "Setting animation in " + this + ": " + anim); 253 mAnimating = false; 254 mLocalAnimating = false; 255 mAnimation = anim; 256 mAnimation.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION); 257 mAnimation.scaleCurrentDuration(mService.getWindowAnimationScaleLocked()); 258 // Start out animation gone if window is gone, or visible if window is visible. 259 mTransformation.clear(); 260 mTransformation.setAlpha(mLastHidden ? 0 : 1); 261 mHasLocalTransformation = true; 262 mAnimationStartTime = startTime; 263 mStackClip = stackClip; 264 } 265 266 public void setAnimation(Animation anim, int stackClip) { 267 setAnimation(anim, -1, stackClip); 268 } 269 270 public void setAnimation(Animation anim) { 271 setAnimation(anim, -1, STACK_CLIP_AFTER_ANIM); 272 } 273 274 public void clearAnimation() { 275 if (mAnimation != null) { 276 mAnimating = true; 277 mLocalAnimating = false; 278 mAnimation.cancel(); 279 mAnimation = null; 280 mKeyguardGoingAwayAnimation = false; 281 mKeyguardGoingAwayWithWallpaper = false; 282 mStackClip = STACK_CLIP_BEFORE_ANIM; 283 } 284 } 285 286 /** Is the window or its container currently animating? */ 287 boolean isAnimating() { 288 return mAnimation != null 289 || (mAttachedWinAnimator != null && mAttachedWinAnimator.mAnimation != null) 290 || (mAppAnimator != null && mAppAnimator.isAnimating()); 291 } 292 293 /** Is the window animating the DummyAnimation? */ 294 boolean isDummyAnimation() { 295 return mAppAnimator != null 296 && mAppAnimator.animation == AppWindowAnimator.sDummyAnimation; 297 } 298 299 /** Is this window currently set to animate or currently animating? */ 300 boolean isWindowAnimating() { 301 return mAnimation != null; 302 } 303 304 void cancelExitAnimationForNextAnimationLocked() { 305 if (DEBUG_ANIM) Slog.d(TAG, 306 "cancelExitAnimationForNextAnimationLocked: " + mWin); 307 308 if (mAnimation != null) { 309 mAnimation.cancel(); 310 mAnimation = null; 311 mLocalAnimating = false; 312 mWin.destroyOrSaveSurface(); 313 } 314 } 315 316 private boolean stepAnimation(long currentTime) { 317 if ((mAnimation == null) || !mLocalAnimating) { 318 return false; 319 } 320 mTransformation.clear(); 321 final boolean more = mAnimation.getTransformation(currentTime, mTransformation); 322 if (false && DEBUG_ANIM) Slog.v(TAG, "Stepped animation in " + this + ": more=" + more 323 + ", xform=" + mTransformation); 324 return more; 325 } 326 327 // This must be called while inside a transaction. Returns true if 328 // there is more animation to run. 329 boolean stepAnimationLocked(long currentTime) { 330 // Save the animation state as it was before this step so WindowManagerService can tell if 331 // we just started or just stopped animating by comparing mWasAnimating with isAnimating(). 332 mWasAnimating = mAnimating; 333 final DisplayContent displayContent = mWin.getDisplayContent(); 334 if (displayContent != null && mService.okToDisplay()) { 335 // We will run animations as long as the display isn't frozen. 336 337 if (mWin.isDrawnLw() && mAnimation != null) { 338 mHasTransformation = true; 339 mHasLocalTransformation = true; 340 if (!mLocalAnimating) { 341 if (DEBUG_ANIM) Slog.v( 342 TAG, "Starting animation in " + this + 343 " @ " + currentTime + ": ww=" + mWin.mFrame.width() + 344 " wh=" + mWin.mFrame.height() + 345 " dx=" + mAnimDx + " dy=" + mAnimDy + 346 " scale=" + mService.getWindowAnimationScaleLocked()); 347 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 348 if (mAnimateMove) { 349 mAnimateMove = false; 350 mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(), 351 mAnimDx, mAnimDy); 352 } else { 353 mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(), 354 displayInfo.appWidth, displayInfo.appHeight); 355 } 356 mAnimDx = displayInfo.appWidth; 357 mAnimDy = displayInfo.appHeight; 358 mAnimation.setStartTime(mAnimationStartTime != -1 359 ? mAnimationStartTime 360 : currentTime); 361 mLocalAnimating = true; 362 mAnimating = true; 363 } 364 if ((mAnimation != null) && mLocalAnimating) { 365 mLastAnimationTime = currentTime; 366 if (stepAnimation(currentTime)) { 367 return true; 368 } 369 } 370 if (DEBUG_ANIM) Slog.v( 371 TAG, "Finished animation in " + this + 372 " @ " + currentTime); 373 //WindowManagerService.this.dump(); 374 } 375 mHasLocalTransformation = false; 376 if ((!mLocalAnimating || mAnimationIsEntrance) && mAppAnimator != null 377 && mAppAnimator.animation != null) { 378 // When our app token is animating, we kind-of pretend like 379 // we are as well. Note the mLocalAnimating mAnimationIsEntrance 380 // part of this check means that we will only do this if 381 // our window is not currently exiting, or it is not 382 // locally animating itself. The idea being that one that 383 // is exiting and doing a local animation should be removed 384 // once that animation is done. 385 mAnimating = true; 386 mHasTransformation = true; 387 mTransformation.clear(); 388 return false; 389 } else if (mHasTransformation) { 390 // Little trick to get through the path below to act like 391 // we have finished an animation. 392 mAnimating = true; 393 } else if (isAnimating()) { 394 mAnimating = true; 395 } 396 } else if (mAnimation != null) { 397 // If the display is frozen, and there is a pending animation, 398 // clear it and make sure we run the cleanup code. 399 mAnimating = true; 400 } 401 402 if (!mAnimating && !mLocalAnimating) { 403 return false; 404 } 405 406 // Done animating, clean up. 407 if (DEBUG_ANIM) Slog.v( 408 TAG, "Animation done in " + this + ": exiting=" + mWin.mAnimatingExit 409 + ", reportedVisible=" 410 + (mWin.mAppToken != null ? mWin.mAppToken.reportedVisible : false)); 411 412 mAnimating = false; 413 mKeyguardGoingAwayAnimation = false; 414 mKeyguardGoingAwayWithWallpaper = false; 415 mLocalAnimating = false; 416 if (mAnimation != null) { 417 mAnimation.cancel(); 418 mAnimation = null; 419 } 420 if (mAnimator.mWindowDetachedWallpaper == mWin) { 421 mAnimator.mWindowDetachedWallpaper = null; 422 } 423 mAnimLayer = mWin.mLayer 424 + mService.mLayersController.getSpecialWindowAnimLayerAdjustment(mWin); 425 if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this + " anim layer: " + mAnimLayer); 426 mHasTransformation = false; 427 mHasLocalTransformation = false; 428 mStackClip = STACK_CLIP_BEFORE_ANIM; 429 mWin.checkPolicyVisibilityChange(); 430 mTransformation.clear(); 431 if (mDrawState == HAS_DRAWN 432 && mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING 433 && mWin.mAppToken != null 434 && mWin.mAppToken.firstWindowDrawn 435 && mWin.mAppToken.startingData != null) { 436 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting " 437 + mWin.mToken + ": first real window done animating"); 438 mService.mFinishedStarting.add(mWin.mAppToken); 439 mService.mH.sendEmptyMessage(H.FINISHED_STARTING); 440 } else if (mAttrType == LayoutParams.TYPE_STATUS_BAR && mWin.mPolicyVisibility) { 441 // Upon completion of a not-visible to visible status bar animation a relayout is 442 // required. 443 if (displayContent != null) { 444 displayContent.layoutNeeded = true; 445 } 446 } 447 448 finishExit(); 449 final int displayId = mWin.getDisplayId(); 450 mAnimator.setPendingLayoutChanges(displayId, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM); 451 if (DEBUG_LAYOUT_REPEATS) 452 mService.mWindowPlacerLocked.debugLayoutRepeats( 453 "WindowStateAnimator", mAnimator.getPendingLayoutChanges(displayId)); 454 455 if (mWin.mAppToken != null) { 456 mWin.mAppToken.updateReportedVisibilityLocked(); 457 } 458 459 return false; 460 } 461 462 void finishExit() { 463 if (DEBUG_ANIM) Slog.v( 464 TAG, "finishExit in " + this 465 + ": exiting=" + mWin.mAnimatingExit 466 + " remove=" + mWin.mRemoveOnExit 467 + " windowAnimating=" + isWindowAnimating()); 468 469 if (!mWin.mChildWindows.isEmpty()) { 470 // Copying to a different list as multiple children can be removed. 471 final WindowList childWindows = new WindowList(mWin.mChildWindows); 472 for (int i = childWindows.size() - 1; i >= 0; i--) { 473 childWindows.get(i).mWinAnimator.finishExit(); 474 } 475 } 476 477 if (mEnteringAnimation) { 478 mEnteringAnimation = false; 479 mService.requestTraversal(); 480 // System windows don't have an activity and an app token as a result, but need a way 481 // to be informed about their entrance animation end. 482 if (mWin.mAppToken == null) { 483 try { 484 mWin.mClient.dispatchWindowShown(); 485 } catch (RemoteException e) { 486 } 487 } 488 } 489 490 if (!isWindowAnimating()) { 491 //TODO (multidisplay): Accessibility is supported only for the default display. 492 if (mService.mAccessibilityController != null 493 && mWin.getDisplayId() == DEFAULT_DISPLAY) { 494 mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked(); 495 } 496 } 497 498 if (!mWin.mAnimatingExit) { 499 return; 500 } 501 502 if (isWindowAnimating()) { 503 return; 504 } 505 506 if (WindowManagerService.localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG, 507 "Exit animation finished in " + this + ": remove=" + mWin.mRemoveOnExit); 508 509 510 mWin.mDestroying = true; 511 512 final boolean hasSurface = hasSurface(); 513 if (hasSurface) { 514 hide("finishExit"); 515 } 516 517 // If we have an app token, we ask it to destroy the surface for us, 518 // so that it can take care to ensure the activity has actually stopped 519 // and the surface is not still in use. Otherwise we add the service to 520 // mDestroySurface and allow it to be processed in our next transaction. 521 if (mWin.mAppToken != null) { 522 mWin.mAppToken.destroySurfaces(); 523 } else { 524 if (hasSurface) { 525 mService.mDestroySurface.add(mWin); 526 } 527 if (mWin.mRemoveOnExit) { 528 mService.mPendingRemove.add(mWin); 529 mWin.mRemoveOnExit = false; 530 } 531 } 532 mWin.mAnimatingExit = false; 533 mWallpaperControllerLocked.hideWallpapers(mWin); 534 } 535 536 void hide(String reason) { 537 if (!mLastHidden) { 538 //dump(); 539 mLastHidden = true; 540 if (mSurfaceController != null) { 541 mSurfaceController.hideInTransaction(reason); 542 } 543 } 544 } 545 546 boolean finishDrawingLocked() { 547 final boolean startingWindow = 548 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 549 if (DEBUG_STARTING_WINDOW && startingWindow) { 550 Slog.v(TAG, "Finishing drawing window " + mWin + ": mDrawState=" 551 + drawStateToString()); 552 } 553 if (mWin.mAppToken != null && mWin.mAppToken.mAnimatingWithSavedSurface) { 554 // App has drawn something to its windows, we're no longer animating with 555 // the saved surfaces. If the user exits now, we only want to save again 556 // if allDrawn is true. 557 if (DEBUG_ANIM) Slog.d(TAG, 558 "finishDrawingLocked: mAnimatingWithSavedSurface=false " + mWin); 559 mWin.mAppToken.mAnimatingWithSavedSurface = false; 560 } 561 if (mDrawState == DRAW_PENDING) { 562 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION) 563 Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + mWin + " in " 564 + mSurfaceController); 565 if (DEBUG_STARTING_WINDOW && startingWindow) { 566 Slog.v(TAG, "Draw state now committed in " + mWin); 567 } 568 mDrawState = COMMIT_DRAW_PENDING; 569 return true; 570 } 571 572 return false; 573 } 574 575 // This must be called while inside a transaction. 576 boolean commitFinishDrawingLocked() { 577 if (DEBUG_STARTING_WINDOW && 578 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { 579 Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState=" 580 + drawStateToString()); 581 } 582 if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) { 583 return false; 584 } 585 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) { 586 Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurfaceController); 587 } 588 mDrawState = READY_TO_SHOW; 589 boolean result = false; 590 final AppWindowToken atoken = mWin.mAppToken; 591 if (atoken == null || atoken.allDrawn || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) { 592 result = performShowLocked(); 593 } 594 return result; 595 } 596 597 void preserveSurfaceLocked() { 598 if (mDestroyPreservedSurfaceUponRedraw) { 599 // This could happen when switching the surface mode very fast. For example, 600 // we preserved a surface when dragResizing changed to true. Then before the 601 // preserved surface is removed, dragResizing changed to false again. 602 // In this case, we need to leave the preserved surface alone, and destroy 603 // the actual surface, so that the createSurface call could create a surface 604 // of the proper size. The preserved surface will still be removed when client 605 // finishes drawing to the new surface. 606 mSurfaceDestroyDeferred = false; 607 destroySurfaceLocked(); 608 mSurfaceDestroyDeferred = true; 609 return; 610 } 611 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "SET FREEZE LAYER", false); 612 if (mSurfaceController != null) { 613 mSurfaceController.setLayer(mAnimLayer + 1); 614 } 615 mDestroyPreservedSurfaceUponRedraw = true; 616 mSurfaceDestroyDeferred = true; 617 destroySurfaceLocked(); 618 } 619 620 void destroyPreservedSurfaceLocked() { 621 if (!mDestroyPreservedSurfaceUponRedraw) { 622 return; 623 } 624 destroyDeferredSurfaceLocked(); 625 mDestroyPreservedSurfaceUponRedraw = false; 626 } 627 628 WindowSurfaceController createSurfaceLocked() { 629 final WindowState w = mWin; 630 if (w.hasSavedSurface()) { 631 if (DEBUG_ANIM) Slog.i(TAG, 632 "createSurface: " + this + ": called when we had a saved surface"); 633 w.restoreSavedSurface(); 634 return mSurfaceController; 635 } 636 637 if (mSurfaceController != null) { 638 return mSurfaceController; 639 } 640 641 w.setHasSurface(false); 642 643 if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG, 644 "createSurface " + this + ": mDrawState=DRAW_PENDING"); 645 646 mDrawState = DRAW_PENDING; 647 if (w.mAppToken != null) { 648 if (w.mAppToken.mAppAnimator.animation == null) { 649 w.mAppToken.allDrawn = false; 650 w.mAppToken.deferClearAllDrawn = false; 651 } else { 652 // Currently animating, persist current state of allDrawn until animation 653 // is complete. 654 w.mAppToken.deferClearAllDrawn = true; 655 } 656 } 657 658 mService.makeWindowFreezingScreenIfNeededLocked(w); 659 660 int flags = SurfaceControl.HIDDEN; 661 final WindowManager.LayoutParams attrs = w.mAttrs; 662 663 if (mService.isSecureLocked(w)) { 664 flags |= SurfaceControl.SECURE; 665 } 666 667 mTmpSize.set(w.mFrame.left + w.mXOffset, w.mFrame.top + w.mYOffset, 0, 0); 668 calculateSurfaceBounds(w, attrs); 669 final int width = mTmpSize.width(); 670 final int height = mTmpSize.height(); 671 672 if (DEBUG_VISIBILITY) { 673 Slog.v(TAG, "Creating surface in session " 674 + mSession.mSurfaceSession + " window " + this 675 + " w=" + width + " h=" + height 676 + " x=" + mTmpSize.left + " y=" + mTmpSize.top 677 + " format=" + attrs.format + " flags=" + flags); 678 } 679 680 // We may abort, so initialize to defaults. 681 mLastSystemDecorRect.set(0, 0, 0, 0); 682 mHasClipRect = false; 683 mClipRect.set(0, 0, 0, 0); 684 mLastClipRect.set(0, 0, 0, 0); 685 686 // Set up surface control with initial size. 687 try { 688 689 final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0; 690 final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format; 691 if (!PixelFormat.formatHasAlpha(attrs.format) 692 // Don't make surface with surfaceInsets opaque as they display a 693 // translucent shadow. 694 && attrs.surfaceInsets.left == 0 695 && attrs.surfaceInsets.top == 0 696 && attrs.surfaceInsets.right == 0 697 && attrs.surfaceInsets.bottom == 0 698 // Don't make surface opaque when resizing to reduce the amount of 699 // artifacts shown in areas the app isn't drawing content to. 700 && !w.isDragResizing()) { 701 flags |= SurfaceControl.OPAQUE; 702 } 703 704 mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession, 705 attrs.getTitle().toString(), 706 width, height, format, flags, this); 707 708 w.setHasSurface(true); 709 710 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { 711 Slog.i(TAG, " CREATE SURFACE " 712 + mSurfaceController + " IN SESSION " 713 + mSession.mSurfaceSession 714 + ": pid=" + mSession.mPid + " format=" 715 + attrs.format + " flags=0x" 716 + Integer.toHexString(flags) 717 + " / " + this); 718 } 719 } catch (OutOfResourcesException e) { 720 Slog.w(TAG, "OutOfResourcesException creating surface"); 721 mService.reclaimSomeSurfaceMemoryLocked(this, "create", true); 722 mDrawState = NO_SURFACE; 723 return null; 724 } catch (Exception e) { 725 Slog.e(TAG, "Exception creating surface", e); 726 mDrawState = NO_SURFACE; 727 return null; 728 } 729 730 if (WindowManagerService.localLOGV) Slog.v(TAG, "Got surface: " + mSurfaceController 731 + ", set left=" + w.mFrame.left + " top=" + w.mFrame.top 732 + ", animLayer=" + mAnimLayer); 733 734 if (SHOW_LIGHT_TRANSACTIONS) { 735 Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked"); 736 WindowManagerService.logSurface(w, "CREATE pos=(" 737 + w.mFrame.left + "," + w.mFrame.top + ") (" 738 + width + "x" + height + "), layer=" + mAnimLayer + " HIDE", false); 739 } 740 741 // Start a new transaction and apply position & offset. 742 final int layerStack = w.getDisplayContent().getDisplay().getLayerStack(); 743 mSurfaceController.setPositionAndLayer(mTmpSize.left, mTmpSize.top, layerStack, mAnimLayer); 744 mLastHidden = true; 745 746 if (WindowManagerService.localLOGV) Slog.v(TAG, "Created surface " + this); 747 return mSurfaceController; 748 } 749 750 private void calculateSurfaceBounds(WindowState w, LayoutParams attrs) { 751 if ((attrs.flags & FLAG_SCALED) != 0) { 752 // For a scaled surface, we always want the requested size. 753 mTmpSize.right = mTmpSize.left + w.mRequestedWidth; 754 mTmpSize.bottom = mTmpSize.top + w.mRequestedHeight; 755 } else { 756 // When we're doing a drag-resizing, request a surface that's fullscreen size, 757 // so that we don't need to reallocate during the process. This also prevents 758 // buffer drops due to size mismatch. 759 if (w.isDragResizing()) { 760 if (w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM) { 761 mTmpSize.left = 0; 762 mTmpSize.top = 0; 763 } 764 final DisplayInfo displayInfo = w.getDisplayInfo(); 765 mTmpSize.right = mTmpSize.left + displayInfo.logicalWidth; 766 mTmpSize.bottom = mTmpSize.top + displayInfo.logicalHeight; 767 } else { 768 mTmpSize.right = mTmpSize.left + w.mCompatFrame.width(); 769 mTmpSize.bottom = mTmpSize.top + w.mCompatFrame.height(); 770 } 771 } 772 773 // Something is wrong and SurfaceFlinger will not like this, try to revert to sane values. 774 // This doesn't necessarily mean that there is an error in the system. The sizes might be 775 // incorrect, because it is before the first layout or draw. 776 if (mTmpSize.width() < 1) { 777 mTmpSize.right = mTmpSize.left + 1; 778 } 779 if (mTmpSize.height() < 1) { 780 mTmpSize.bottom = mTmpSize.top + 1; 781 } 782 783 final int displayId = w.getDisplayId(); 784 float scale = 1.0f; 785 // Magnification is supported only for the default display. 786 if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) { 787 final MagnificationSpec spec = 788 mService.mAccessibilityController.getMagnificationSpecForWindowLocked(w); 789 if (spec != null && !spec.isNop()) { 790 scale = spec.scale; 791 } 792 } 793 794 // Adjust for surface insets. 795 mTmpSize.left -= scale * attrs.surfaceInsets.left; 796 mTmpSize.top -= scale * attrs.surfaceInsets.top; 797 mTmpSize.right += scale * (attrs.surfaceInsets.left + attrs.surfaceInsets.right); 798 mTmpSize.bottom += scale * (attrs.surfaceInsets.top + attrs.surfaceInsets.bottom); 799 } 800 801 boolean hasSurface() { 802 return !mWin.mSurfaceSaved 803 && mSurfaceController != null && mSurfaceController.hasSurface(); 804 } 805 806 void destroySurfaceLocked() { 807 final AppWindowToken wtoken = mWin.mAppToken; 808 if (wtoken != null) { 809 wtoken.mAnimatingWithSavedSurface = false; 810 if (mWin == wtoken.startingWindow) { 811 wtoken.startingDisplayed = false; 812 } 813 } 814 815 mWin.mSurfaceSaved = false; 816 817 if (mSurfaceController == null) { 818 return; 819 } 820 821 int i = mWin.mChildWindows.size(); 822 // When destroying a surface we want to make sure child windows are hidden. If we are 823 // preserving the surface until redraw though we intend to swap it out with another surface 824 // for resizing. In this case the window always remains visible to the user and the child 825 // windows should likewise remain visible. 826 while (!mDestroyPreservedSurfaceUponRedraw && i > 0) { 827 i--; 828 WindowState c = mWin.mChildWindows.get(i); 829 c.mAttachedHidden = true; 830 } 831 832 try { 833 if (DEBUG_VISIBILITY) logWithStack(TAG, "Window " + this + " destroying surface " 834 + mSurfaceController + ", session " + mSession); 835 if (mSurfaceDestroyDeferred) { 836 if (mSurfaceController != null && mPendingDestroySurface != mSurfaceController) { 837 if (mPendingDestroySurface != null) { 838 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { 839 WindowManagerService.logSurface(mWin, "DESTROY PENDING", true); 840 } 841 mPendingDestroySurface.destroyInTransaction(); 842 } 843 mPendingDestroySurface = mSurfaceController; 844 } 845 } else { 846 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { 847 WindowManagerService.logSurface(mWin, "DESTROY", true); 848 } 849 destroySurface(); 850 } 851 // Don't hide wallpaper if we're deferring the surface destroy 852 // because of a surface change. 853 if (!mDestroyPreservedSurfaceUponRedraw) { 854 mWallpaperControllerLocked.hideWallpapers(mWin); 855 } 856 } catch (RuntimeException e) { 857 Slog.w(TAG, "Exception thrown when destroying Window " + this 858 + " surface " + mSurfaceController + " session " + mSession + ": " + e.toString()); 859 } 860 861 // Whether the surface was preserved (and copied to mPendingDestroySurface) or not, it 862 // needs to be cleared to match the WindowState.mHasSurface state. It is also necessary 863 // so it can be recreated successfully in mPendingDestroySurface case. 864 mWin.setHasSurface(false); 865 if (mSurfaceController != null) { 866 mSurfaceController.setShown(false); 867 } 868 mSurfaceController = null; 869 mDrawState = NO_SURFACE; 870 } 871 872 void destroyDeferredSurfaceLocked() { 873 try { 874 if (mPendingDestroySurface != null) { 875 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { 876 WindowManagerService.logSurface(mWin, "DESTROY PENDING", true); 877 } 878 mPendingDestroySurface.destroyInTransaction(); 879 // Don't hide wallpaper if we're destroying a deferred surface 880 // after a surface mode change. 881 if (!mDestroyPreservedSurfaceUponRedraw) { 882 mWallpaperControllerLocked.hideWallpapers(mWin); 883 } 884 } 885 } catch (RuntimeException e) { 886 Slog.w(TAG, "Exception thrown when destroying Window " 887 + this + " surface " + mPendingDestroySurface 888 + " session " + mSession + ": " + e.toString()); 889 } 890 mSurfaceDestroyDeferred = false; 891 mPendingDestroySurface = null; 892 } 893 894 void computeShownFrameLocked() { 895 final boolean selfTransformation = mHasLocalTransformation; 896 Transformation attachedTransformation = 897 (mAttachedWinAnimator != null && mAttachedWinAnimator.mHasLocalTransformation) 898 ? mAttachedWinAnimator.mTransformation : null; 899 Transformation appTransformation = (mAppAnimator != null && mAppAnimator.hasTransformation) 900 ? mAppAnimator.transformation : null; 901 902 // Wallpapers are animated based on the "real" window they 903 // are currently targeting. 904 final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget(); 905 if (mIsWallpaper && wallpaperTarget != null && mService.mAnimateWallpaperWithTarget) { 906 final WindowStateAnimator wallpaperAnimator = wallpaperTarget.mWinAnimator; 907 if (wallpaperAnimator.mHasLocalTransformation && 908 wallpaperAnimator.mAnimation != null && 909 !wallpaperAnimator.mAnimation.getDetachWallpaper()) { 910 attachedTransformation = wallpaperAnimator.mTransformation; 911 if (DEBUG_WALLPAPER && attachedTransformation != null) { 912 Slog.v(TAG, "WP target attached xform: " + attachedTransformation); 913 } 914 } 915 final AppWindowAnimator wpAppAnimator = wallpaperTarget.mAppToken == null ? 916 null : wallpaperTarget.mAppToken.mAppAnimator; 917 if (wpAppAnimator != null && wpAppAnimator.hasTransformation 918 && wpAppAnimator.animation != null 919 && !wpAppAnimator.animation.getDetachWallpaper()) { 920 appTransformation = wpAppAnimator.transformation; 921 if (DEBUG_WALLPAPER && appTransformation != null) { 922 Slog.v(TAG, "WP target app xform: " + appTransformation); 923 } 924 } 925 } 926 927 final int displayId = mWin.getDisplayId(); 928 final ScreenRotationAnimation screenRotationAnimation = 929 mAnimator.getScreenRotationAnimationLocked(displayId); 930 final boolean screenAnimation = 931 screenRotationAnimation != null && screenRotationAnimation.isAnimating(); 932 933 mHasClipRect = false; 934 if (selfTransformation || attachedTransformation != null 935 || appTransformation != null || screenAnimation) { 936 // cache often used attributes locally 937 final Rect frame = mWin.mFrame; 938 final float tmpFloats[] = mService.mTmpFloats; 939 final Matrix tmpMatrix = mWin.mTmpMatrix; 940 941 // Compute the desired transformation. 942 if (screenAnimation && screenRotationAnimation.isRotating()) { 943 // If we are doing a screen animation, the global rotation 944 // applied to windows can result in windows that are carefully 945 // aligned with each other to slightly separate, allowing you 946 // to see what is behind them. An unsightly mess. This... 947 // thing... magically makes it call good: scale each window 948 // slightly (two pixels larger in each dimension, from the 949 // window's center). 950 final float w = frame.width(); 951 final float h = frame.height(); 952 if (w>=1 && h>=1) { 953 tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2); 954 } else { 955 tmpMatrix.reset(); 956 } 957 } else { 958 tmpMatrix.reset(); 959 } 960 tmpMatrix.postScale(mWin.mGlobalScale, mWin.mGlobalScale); 961 if (selfTransformation) { 962 tmpMatrix.postConcat(mTransformation.getMatrix()); 963 } 964 if (attachedTransformation != null) { 965 tmpMatrix.postConcat(attachedTransformation.getMatrix()); 966 } 967 if (appTransformation != null) { 968 tmpMatrix.postConcat(appTransformation.getMatrix()); 969 } 970 971 // The translation that applies the position of the window needs to be applied at the 972 // end in case that other translations include scaling. Otherwise the scaling will 973 // affect this translation. But it needs to be set before the screen rotation animation 974 // so the pivot point is at the center of the screen for all windows. 975 tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset); 976 if (screenAnimation) { 977 tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix()); 978 } 979 980 //TODO (multidisplay): Magnification is supported only for the default display. 981 if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) { 982 MagnificationSpec spec = mService.mAccessibilityController 983 .getMagnificationSpecForWindowLocked(mWin); 984 if (spec != null && !spec.isNop()) { 985 tmpMatrix.postScale(spec.scale, spec.scale); 986 tmpMatrix.postTranslate(spec.offsetX, spec.offsetY); 987 } 988 } 989 990 // "convert" it into SurfaceFlinger's format 991 // (a 2x2 matrix + an offset) 992 // Here we must not transform the position of the surface 993 // since it is already included in the transformation. 994 //Slog.i(TAG_WM, "Transform: " + matrix); 995 996 mHaveMatrix = true; 997 tmpMatrix.getValues(tmpFloats); 998 mDsDx = tmpFloats[Matrix.MSCALE_X]; 999 mDtDx = tmpFloats[Matrix.MSKEW_Y]; 1000 mDsDy = tmpFloats[Matrix.MSKEW_X]; 1001 mDtDy = tmpFloats[Matrix.MSCALE_Y]; 1002 float x = tmpFloats[Matrix.MTRANS_X]; 1003 float y = tmpFloats[Matrix.MTRANS_Y]; 1004 mWin.mShownPosition.set((int) x, (int) y); 1005 1006 // Now set the alpha... but because our current hardware 1007 // can't do alpha transformation on a non-opaque surface, 1008 // turn it off if we are running an animation that is also 1009 // transforming since it is more important to have that 1010 // animation be smooth. 1011 mShownAlpha = mAlpha; 1012 if (!mService.mLimitedAlphaCompositing 1013 || (!PixelFormat.formatHasAlpha(mWin.mAttrs.format) 1014 || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy) 1015 && x == frame.left && y == frame.top))) { 1016 //Slog.i(TAG_WM, "Applying alpha transform"); 1017 if (selfTransformation) { 1018 mShownAlpha *= mTransformation.getAlpha(); 1019 } 1020 if (attachedTransformation != null) { 1021 mShownAlpha *= attachedTransformation.getAlpha(); 1022 } 1023 if (appTransformation != null) { 1024 mShownAlpha *= appTransformation.getAlpha(); 1025 if (appTransformation.hasClipRect()) { 1026 mClipRect.set(appTransformation.getClipRect()); 1027 mHasClipRect = true; 1028 // The app transformation clip will be in the coordinate space of the main 1029 // activity window, which the animation correctly assumes will be placed at 1030 // (0,0)+(insets) relative to the containing frame. This isn't necessarily 1031 // true for child windows though which can have an arbitrary frame position 1032 // relative to their containing frame. We need to offset the difference 1033 // between the containing frame as used to calculate the crop and our 1034 // bounds to compensate for this. 1035 if (mWin.isChildWindow() && mWin.layoutInParentFrame()) { 1036 mClipRect.offset( (mWin.mContainingFrame.left - mWin.mFrame.left), 1037 mWin.mContainingFrame.top - mWin.mFrame.top ); 1038 } 1039 } 1040 } 1041 if (screenAnimation) { 1042 mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha(); 1043 } 1044 } else { 1045 //Slog.i(TAG_WM, "Not applying alpha transform"); 1046 } 1047 1048 if ((DEBUG_SURFACE_TRACE || WindowManagerService.localLOGV) 1049 && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v( 1050 TAG, "computeShownFrameLocked: Animating " + this + " mAlpha=" + mAlpha 1051 + " self=" + (selfTransformation ? mTransformation.getAlpha() : "null") 1052 + " attached=" + (attachedTransformation == null ? 1053 "null" : attachedTransformation.getAlpha()) 1054 + " app=" + (appTransformation == null ? "null" : appTransformation.getAlpha()) 1055 + " screen=" + (screenAnimation ? 1056 screenRotationAnimation.getEnterTransformation().getAlpha() : "null")); 1057 return; 1058 } else if (mIsWallpaper && mService.mWindowPlacerLocked.mWallpaperActionPending) { 1059 return; 1060 } else if (mWin.isDragResizeChanged()) { 1061 // This window is awaiting a relayout because user just started (or ended) 1062 // drag-resizing. The shown frame (which affects surface size and pos) 1063 // should not be updated until we get next finished draw with the new surface. 1064 // Otherwise one or two frames rendered with old settings would be displayed 1065 // with new geometry. 1066 return; 1067 } 1068 1069 if (WindowManagerService.localLOGV) Slog.v( 1070 TAG, "computeShownFrameLocked: " + this + 1071 " not attached, mAlpha=" + mAlpha); 1072 1073 MagnificationSpec spec = null; 1074 //TODO (multidisplay): Magnification is supported only for the default display. 1075 if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) { 1076 spec = mService.mAccessibilityController.getMagnificationSpecForWindowLocked(mWin); 1077 } 1078 if (spec != null) { 1079 final Rect frame = mWin.mFrame; 1080 final float tmpFloats[] = mService.mTmpFloats; 1081 final Matrix tmpMatrix = mWin.mTmpMatrix; 1082 1083 tmpMatrix.setScale(mWin.mGlobalScale, mWin.mGlobalScale); 1084 tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset); 1085 1086 if (spec != null && !spec.isNop()) { 1087 tmpMatrix.postScale(spec.scale, spec.scale); 1088 tmpMatrix.postTranslate(spec.offsetX, spec.offsetY); 1089 } 1090 1091 tmpMatrix.getValues(tmpFloats); 1092 1093 mHaveMatrix = true; 1094 mDsDx = tmpFloats[Matrix.MSCALE_X]; 1095 mDtDx = tmpFloats[Matrix.MSKEW_Y]; 1096 mDsDy = tmpFloats[Matrix.MSKEW_X]; 1097 mDtDy = tmpFloats[Matrix.MSCALE_Y]; 1098 float x = tmpFloats[Matrix.MTRANS_X]; 1099 float y = tmpFloats[Matrix.MTRANS_Y]; 1100 mWin.mShownPosition.set((int) x, (int) y); 1101 1102 mShownAlpha = mAlpha; 1103 } else { 1104 mWin.mShownPosition.set(mWin.mFrame.left, mWin.mFrame.top); 1105 if (mWin.mXOffset != 0 || mWin.mYOffset != 0) { 1106 mWin.mShownPosition.offset(mWin.mXOffset, mWin.mYOffset); 1107 } 1108 mShownAlpha = mAlpha; 1109 mHaveMatrix = false; 1110 mDsDx = mWin.mGlobalScale; 1111 mDtDx = 0; 1112 mDsDy = 0; 1113 mDtDy = mWin.mGlobalScale; 1114 } 1115 } 1116 1117 private void calculateSystemDecorRect() { 1118 final WindowState w = mWin; 1119 final Rect decorRect = w.mDecorFrame; 1120 final int width = w.mFrame.width(); 1121 final int height = w.mFrame.height(); 1122 1123 // Compute the offset of the window in relation to the decor rect. 1124 final int left = w.mXOffset + w.mFrame.left; 1125 final int top = w.mYOffset + w.mFrame.top; 1126 1127 // Initialize the decor rect to the entire frame. 1128 if (w.isDockedResizing() || 1129 (w.isChildWindow() && w.mAttachedWindow.isDockedResizing())) { 1130 1131 // If we are resizing with the divider, the task bounds might be smaller than the 1132 // stack bounds. The system decor is used to clip to the task bounds, which we don't 1133 // want in this case in order to avoid holes. 1134 // 1135 // We take care to not shrink the width, for surfaces which are larger than 1136 // the display region. Of course this area will not eventually be visible 1137 // but if we truncate the width now, we will calculate incorrectly 1138 // when adjusting to the stack bounds. 1139 final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo(); 1140 mSystemDecorRect.set(0, 0, 1141 Math.max(width, displayInfo.logicalWidth), 1142 Math.max(height, displayInfo.logicalHeight)); 1143 } else { 1144 mSystemDecorRect.set(0, 0, width, height); 1145 } 1146 1147 // If a freeform window is animating from a position where it would be cutoff, it would be 1148 // cutoff during the animation. We don't want that, so for the duration of the animation 1149 // we ignore the decor cropping and depend on layering to position windows correctly. 1150 final boolean cropToDecor = !(w.inFreeformWorkspace() && w.isAnimatingLw()); 1151 if (cropToDecor) { 1152 // Intersect with the decor rect, offsetted by window position. 1153 mSystemDecorRect.intersect(decorRect.left - left, decorRect.top - top, 1154 decorRect.right - left, decorRect.bottom - top); 1155 } 1156 1157 // If size compatibility is being applied to the window, the 1158 // surface is scaled relative to the screen. Also apply this 1159 // scaling to the crop rect. We aren't using the standard rect 1160 // scale function because we want to round things to make the crop 1161 // always round to a larger rect to ensure we don't crop too 1162 // much and hide part of the window that should be seen. 1163 if (w.mEnforceSizeCompat && w.mInvGlobalScale != 1.0f) { 1164 final float scale = w.mInvGlobalScale; 1165 mSystemDecorRect.left = (int) (mSystemDecorRect.left * scale - 0.5f); 1166 mSystemDecorRect.top = (int) (mSystemDecorRect.top * scale - 0.5f); 1167 mSystemDecorRect.right = (int) ((mSystemDecorRect.right+1) * scale - 0.5f); 1168 mSystemDecorRect.bottom = (int) ((mSystemDecorRect.bottom+1) * scale - 0.5f); 1169 } 1170 } 1171 1172 void calculateSurfaceWindowCrop(Rect clipRect, Rect finalClipRect) { 1173 final WindowState w = mWin; 1174 final DisplayContent displayContent = w.getDisplayContent(); 1175 if (displayContent == null) { 1176 clipRect.setEmpty(); 1177 finalClipRect.setEmpty(); 1178 return; 1179 } 1180 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 1181 if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Updating crop for window: " + w + ", " + "mLastCrop=" + 1182 mLastClipRect); 1183 1184 // Need to recompute a new system decor rect each time. 1185 if (!w.isDefaultDisplay()) { 1186 // On a different display there is no system decor. Crop the window 1187 // by the screen boundaries. 1188 mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height()); 1189 mSystemDecorRect.intersect(-w.mCompatFrame.left, -w.mCompatFrame.top, 1190 displayInfo.logicalWidth - w.mCompatFrame.left, 1191 displayInfo.logicalHeight - w.mCompatFrame.top); 1192 } else if (w.mLayer >= mService.mSystemDecorLayer) { 1193 // Above the decor layer is easy, just use the entire window. 1194 mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height()); 1195 } else if (w.mDecorFrame.isEmpty()) { 1196 // Windows without policy decor aren't cropped. 1197 mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height()); 1198 } else if (w.mAttrs.type == LayoutParams.TYPE_WALLPAPER && mAnimator.isAnimating()) { 1199 // If we're animating, the wallpaper crop should only be updated at the end of the 1200 // animation. 1201 mTmpClipRect.set(mSystemDecorRect); 1202 calculateSystemDecorRect(); 1203 mSystemDecorRect.union(mTmpClipRect); 1204 } else { 1205 // Crop to the system decor specified by policy. 1206 calculateSystemDecorRect(); 1207 if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop for " + w + ", mDecorFrame=" 1208 + w.mDecorFrame + ", mSystemDecorRect=" + mSystemDecorRect); 1209 } 1210 1211 final boolean fullscreen = w.isFrameFullscreen(displayInfo); 1212 final boolean isFreeformResizing = 1213 w.isDragResizing() && w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM; 1214 1215 // We use the clip rect as provided by the tranformation for non-fullscreen windows to 1216 // avoid premature clipping with the system decor rect. 1217 clipRect.set((mHasClipRect && !fullscreen) ? mClipRect : mSystemDecorRect); 1218 if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Initial clip rect: " + clipRect + ", mHasClipRect=" 1219 + mHasClipRect + ", fullscreen=" + fullscreen); 1220 1221 if (isFreeformResizing && !w.isChildWindow()) { 1222 // For freeform resizing non child windows, we are using the big surface positioned 1223 // at 0,0. Thus we must express the crop in that coordinate space. 1224 clipRect.offset(w.mShownPosition.x, w.mShownPosition.y); 1225 } 1226 1227 // Expand the clip rect for surface insets. 1228 final WindowManager.LayoutParams attrs = w.mAttrs; 1229 clipRect.left -= attrs.surfaceInsets.left; 1230 clipRect.top -= attrs.surfaceInsets.top; 1231 clipRect.right += attrs.surfaceInsets.right; 1232 clipRect.bottom += attrs.surfaceInsets.bottom; 1233 1234 if (mHasClipRect && fullscreen) { 1235 // We intersect the clip rect specified by the transformation with the expanded system 1236 // decor rect to prevent artifacts from drawing during animation if the transformation 1237 // clip rect extends outside the system decor rect. 1238 clipRect.intersect(mClipRect); 1239 } 1240 // The clip rect was generated assuming (0,0) as the window origin, 1241 // so we need to translate to match the actual surface coordinates. 1242 clipRect.offset(attrs.surfaceInsets.left, attrs.surfaceInsets.top); 1243 1244 finalClipRect.setEmpty(); 1245 adjustCropToStackBounds(w, clipRect, finalClipRect, isFreeformResizing); 1246 if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Clip rect after stack adjustment=" + clipRect); 1247 1248 w.transformFromScreenToSurfaceSpace(clipRect); 1249 1250 // See {@link WindowState#notifyMovedInStack} for why this is necessary. 1251 if (w.hasJustMovedInStack() && mLastClipRect.isEmpty() && !clipRect.isEmpty()) { 1252 clipRect.setEmpty(); 1253 } 1254 } 1255 1256 void updateSurfaceWindowCrop(Rect clipRect, Rect finalClipRect, boolean recoveringMemory) { 1257 if (!clipRect.equals(mLastClipRect)) { 1258 mLastClipRect.set(clipRect); 1259 mSurfaceController.setCropInTransaction(clipRect, recoveringMemory); 1260 } 1261 if (!finalClipRect.equals(mLastFinalClipRect)) { 1262 mLastFinalClipRect.set(finalClipRect); 1263 mSurfaceController.setFinalCropInTransaction(finalClipRect); 1264 } 1265 } 1266 1267 private int resolveStackClip() { 1268 1269 // App animation overrides window animation stack clip mode. 1270 if (mAppAnimator != null && mAppAnimator.animation != null) { 1271 return mAppAnimator.getStackClip(); 1272 } else { 1273 return mStackClip; 1274 } 1275 } 1276 private void adjustCropToStackBounds(WindowState w, Rect clipRect, Rect finalClipRect, 1277 boolean isFreeformResizing) { 1278 final Task task = w.getTask(); 1279 if (task == null || !task.cropWindowsToStackBounds()) { 1280 return; 1281 } 1282 1283 final int stackClip = resolveStackClip(); 1284 1285 // It's animating and we don't want to clip it to stack bounds during animation - abort. 1286 if (isAnimating() && stackClip == STACK_CLIP_NONE) { 1287 return; 1288 } 1289 1290 final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw(); 1291 if (w == winShowWhenLocked && mPolicy.isKeyguardShowingOrOccluded()) { 1292 return; 1293 } 1294 1295 final TaskStack stack = task.mStack; 1296 stack.getDimBounds(mTmpStackBounds); 1297 // When we resize we use the big surface approach, which means we can't trust the 1298 // window frame bounds anymore. Instead, the window will be placed at 0, 0, but to avoid 1299 // hardcoding it, we use surface coordinates. 1300 final int frameX = isFreeformResizing ? (int) mSurfaceController.getX() : 1301 w.mFrame.left + mWin.mXOffset - w.getAttrs().surfaceInsets.left; 1302 final int frameY = isFreeformResizing ? (int) mSurfaceController.getY() : 1303 w.mFrame.top + mWin.mYOffset - w.getAttrs().surfaceInsets.top; 1304 1305 // If we are animating, we either apply the clip before applying all the animation 1306 // transformation or after all the transformation. 1307 final boolean useFinalClipRect = isAnimating() && stackClip == STACK_CLIP_AFTER_ANIM; 1308 1309 // We need to do some acrobatics with surface position, because their clip region is 1310 // relative to the inside of the surface, but the stack bounds aren't. 1311 if (useFinalClipRect) { 1312 finalClipRect.set(mTmpStackBounds); 1313 } else { 1314 clipRect.left = Math.max(0, 1315 Math.max(mTmpStackBounds.left, frameX + clipRect.left) - frameX); 1316 clipRect.top = Math.max(0, 1317 Math.max(mTmpStackBounds.top, frameY + clipRect.top) - frameY); 1318 clipRect.right = Math.max(0, 1319 Math.min(mTmpStackBounds.right, frameX + clipRect.right) - frameX); 1320 clipRect.bottom = Math.max(0, 1321 Math.min(mTmpStackBounds.bottom, frameY + clipRect.bottom) - frameY); 1322 } 1323 } 1324 1325 void setSurfaceBoundariesLocked(final boolean recoveringMemory) { 1326 final WindowState w = mWin; 1327 final Task task = w.getTask(); 1328 1329 // We got resized, so block all updates until we got the new surface. 1330 if (w.mResizedWhileNotDragResizing) { 1331 return; 1332 } 1333 1334 mTmpSize.set(w.mShownPosition.x, w.mShownPosition.y, 0, 0); 1335 calculateSurfaceBounds(w, w.getAttrs()); 1336 1337 float extraHScale = (float) 1.0; 1338 float extraVScale = (float) 1.0; 1339 1340 calculateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect); 1341 if (task != null && task.mStack.getForceScaleToCrop()) { 1342 extraHScale = mTmpClipRect.width() / (float)mTmpSize.width(); 1343 extraVScale = mTmpClipRect.height() / (float)mTmpSize.height(); 1344 1345 // In the case of ForceScaleToCrop we scale entire tasks together, 1346 // and so we need to scale our offsets relative to the task bounds 1347 // or parent and child windows would fall out of alignment. 1348 int posX = (int) (mTmpSize.left - w.mAttrs.x * (1 - extraHScale)); 1349 int posY = (int) (mTmpSize.top - w.mAttrs.y * (1 - extraVScale)); 1350 posX += w.getAttrs().surfaceInsets.left * (1 - extraHScale); 1351 posY += w.getAttrs().surfaceInsets.top * (1 - extraVScale); 1352 mSurfaceController.setPositionInTransaction(posX, posY, recoveringMemory); 1353 1354 // Since we are scaled to fit in our previously desired crop, we can now 1355 // expose the whole window in buffer space, and not risk extending 1356 // past where the system would have cropped us 1357 mTmpClipRect.set(0, 0, mTmpSize.width(), mTmpSize.height()); 1358 mTmpFinalClipRect.setEmpty(); 1359 updateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect, recoveringMemory); 1360 } else { 1361 mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top, 1362 recoveringMemory); 1363 updateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect, recoveringMemory); 1364 } 1365 1366 1367 mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * extraHScale, 1368 mDtDx * w.mVScale * extraVScale, 1369 mDsDy * w.mHScale * extraHScale, 1370 mDtDy * w.mVScale * extraVScale, recoveringMemory); 1371 mSurfaceResized = mSurfaceController.setSizeInTransaction( 1372 mTmpSize.width(), mTmpSize.height(), 1373 recoveringMemory); 1374 1375 if (mSurfaceResized) { 1376 mReportSurfaceResized = true; 1377 mAnimator.setPendingLayoutChanges(w.getDisplayId(), 1378 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); 1379 w.applyDimLayerIfNeeded(); 1380 } 1381 1382 } 1383 1384 void prepareSurfaceLocked(final boolean recoveringMemory) { 1385 final WindowState w = mWin; 1386 if (!hasSurface()) { 1387 if (w.mOrientationChanging) { 1388 if (DEBUG_ORIENTATION) { 1389 Slog.v(TAG, "Orientation change skips hidden " + w); 1390 } 1391 w.mOrientationChanging = false; 1392 } 1393 return; 1394 } 1395 1396 boolean displayed = false; 1397 1398 computeShownFrameLocked(); 1399 1400 setSurfaceBoundariesLocked(recoveringMemory); 1401 1402 if (mIsWallpaper && !mWin.mWallpaperVisible) { 1403 // Wallpaper is no longer visible and there is no wp target => hide it. 1404 hide("prepareSurfaceLocked"); 1405 } else if (w.mAttachedHidden || !w.isOnScreen()) { 1406 hide("prepareSurfaceLocked"); 1407 mWallpaperControllerLocked.hideWallpapers(w); 1408 1409 // If we are waiting for this window to handle an 1410 // orientation change, well, it is hidden, so 1411 // doesn't really matter. Note that this does 1412 // introduce a potential glitch if the window 1413 // becomes unhidden before it has drawn for the 1414 // new orientation. 1415 if (w.mOrientationChanging) { 1416 w.mOrientationChanging = false; 1417 if (DEBUG_ORIENTATION) Slog.v(TAG, 1418 "Orientation change skips hidden " + w); 1419 } 1420 } else if (mLastLayer != mAnimLayer 1421 || mLastAlpha != mShownAlpha 1422 || mLastDsDx != mDsDx 1423 || mLastDtDx != mDtDx 1424 || mLastDsDy != mDsDy 1425 || mLastDtDy != mDtDy 1426 || w.mLastHScale != w.mHScale 1427 || w.mLastVScale != w.mVScale 1428 || mLastHidden) { 1429 displayed = true; 1430 mLastAlpha = mShownAlpha; 1431 mLastLayer = mAnimLayer; 1432 mLastDsDx = mDsDx; 1433 mLastDtDx = mDtDx; 1434 mLastDsDy = mDsDy; 1435 mLastDtDy = mDtDy; 1436 w.mLastHScale = w.mHScale; 1437 w.mLastVScale = w.mVScale; 1438 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, 1439 "controller=" + mSurfaceController + 1440 "alpha=" + mShownAlpha + " layer=" + mAnimLayer 1441 + " matrix=[" + mDsDx + "*" + w.mHScale 1442 + "," + mDtDx + "*" + w.mVScale 1443 + "][" + mDsDy + "*" + w.mHScale 1444 + "," + mDtDy + "*" + w.mVScale + "]", false); 1445 1446 boolean prepared = 1447 mSurfaceController.prepareToShowInTransaction(mShownAlpha, mAnimLayer, 1448 mDsDx * w.mHScale, mDtDx * w.mVScale, 1449 mDsDy * w.mHScale, mDtDy * w.mVScale, 1450 recoveringMemory); 1451 1452 if (prepared && mLastHidden && mDrawState == HAS_DRAWN) { 1453 if (showSurfaceRobustlyLocked()) { 1454 if (mDestroyPreservedSurfaceUponRedraw) { 1455 mService.mDestroyPreservedSurface.add(mWin); 1456 } 1457 mAnimator.requestRemovalOfReplacedWindows(w); 1458 mLastHidden = false; 1459 if (mIsWallpaper) { 1460 mWallpaperControllerLocked.dispatchWallpaperVisibility(w, true); 1461 } 1462 // This draw means the difference between unique content and mirroring. 1463 // Run another pass through performLayout to set mHasContent in the 1464 // LogicalDisplay. 1465 mAnimator.setPendingLayoutChanges(w.getDisplayId(), 1466 WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM); 1467 } else { 1468 w.mOrientationChanging = false; 1469 } 1470 } 1471 if (hasSurface()) { 1472 w.mToken.hasVisible = true; 1473 } 1474 } else { 1475 if (DEBUG_ANIM && isAnimating()) { 1476 Slog.v(TAG, "prepareSurface: No changes in animation for " + this); 1477 } 1478 displayed = true; 1479 } 1480 1481 if (displayed) { 1482 if (w.mOrientationChanging) { 1483 if (!w.isDrawnLw()) { 1484 mAnimator.mBulkUpdateParams &= ~SET_ORIENTATION_CHANGE_COMPLETE; 1485 mAnimator.mLastWindowFreezeSource = w; 1486 if (DEBUG_ORIENTATION) Slog.v(TAG, 1487 "Orientation continue waiting for draw in " + w); 1488 } else { 1489 w.mOrientationChanging = false; 1490 if (DEBUG_ORIENTATION) Slog.v(TAG, "Orientation change complete in " + w); 1491 } 1492 } 1493 w.mToken.hasVisible = true; 1494 } 1495 } 1496 1497 void setTransparentRegionHintLocked(final Region region) { 1498 if (mSurfaceController == null) { 1499 Slog.w(TAG, "setTransparentRegionHint: null mSurface after mHasSurface true"); 1500 return; 1501 } 1502 mSurfaceController.setTransparentRegionHint(region); 1503 } 1504 1505 void setWallpaperOffset(Point shownPosition) { 1506 final LayoutParams attrs = mWin.getAttrs(); 1507 final int left = shownPosition.x - attrs.surfaceInsets.left; 1508 final int top = shownPosition.y - attrs.surfaceInsets.top; 1509 1510 try { 1511 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset"); 1512 SurfaceControl.openTransaction(); 1513 mSurfaceController.setPositionInTransaction(mWin.mFrame.left + left, 1514 mWin.mFrame.top + top, false); 1515 calculateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect); 1516 updateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect, false); 1517 } catch (RuntimeException e) { 1518 Slog.w(TAG, "Error positioning surface of " + mWin 1519 + " pos=(" + left + "," + top + ")", e); 1520 } finally { 1521 SurfaceControl.closeTransaction(); 1522 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 1523 "<<< CLOSE TRANSACTION setWallpaperOffset"); 1524 } 1525 } 1526 1527 /** 1528 * Try to change the pixel format without recreating the surface. This 1529 * will be common in the case of changing from PixelFormat.OPAQUE to 1530 * PixelFormat.TRANSLUCENT in the hardware-accelerated case as both 1531 * requested formats resolve to the same underlying SurfaceControl format 1532 * @return True if format was succesfully changed, false otherwise 1533 */ 1534 boolean tryChangeFormatInPlaceLocked() { 1535 if (mSurfaceController == null) { 1536 return false; 1537 } 1538 final LayoutParams attrs = mWin.getAttrs(); 1539 final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0; 1540 final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format; 1541 if (format == mSurfaceFormat) { 1542 setOpaqueLocked(!PixelFormat.formatHasAlpha(attrs.format)); 1543 return true; 1544 } 1545 return false; 1546 } 1547 1548 void setOpaqueLocked(boolean isOpaque) { 1549 if (mSurfaceController == null) { 1550 return; 1551 } 1552 mSurfaceController.setOpaque(isOpaque); 1553 } 1554 1555 void setSecureLocked(boolean isSecure) { 1556 if (mSurfaceController == null) { 1557 return; 1558 } 1559 mSurfaceController.setSecure(isSecure); 1560 } 1561 1562 // This must be called while inside a transaction. 1563 boolean performShowLocked() { 1564 if (mWin.isHiddenFromUserLocked()) { 1565 if (DEBUG_VISIBILITY) Slog.w(TAG, "hiding " + mWin + ", belonging to " + mWin.mOwnerUid); 1566 mWin.hideLw(false); 1567 return false; 1568 } 1569 if (DEBUG_VISIBILITY || (DEBUG_STARTING_WINDOW && 1570 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING)) { 1571 Slog.v(TAG, "performShow on " + this 1572 + ": mDrawState=" + drawStateToString() + " readyForDisplay=" 1573 + mWin.isReadyForDisplayIgnoringKeyguard() 1574 + " starting=" + (mWin.mAttrs.type == TYPE_APPLICATION_STARTING) 1575 + " during animation: policyVis=" + mWin.mPolicyVisibility 1576 + " attHidden=" + mWin.mAttachedHidden 1577 + " tok.hiddenRequested=" 1578 + (mWin.mAppToken != null ? mWin.mAppToken.hiddenRequested : false) 1579 + " tok.hidden=" 1580 + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false) 1581 + " animating=" + mAnimating 1582 + " tok animating=" 1583 + (mAppAnimator != null ? mAppAnimator.animating : false) + " Callers=" 1584 + Debug.getCallers(3)); 1585 } 1586 if (mDrawState == READY_TO_SHOW && mWin.isReadyForDisplayIgnoringKeyguard()) { 1587 if (DEBUG_VISIBILITY || (DEBUG_STARTING_WINDOW && 1588 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING)) { 1589 Slog.v(TAG, "Showing " + this 1590 + " during animation: policyVis=" + mWin.mPolicyVisibility 1591 + " attHidden=" + mWin.mAttachedHidden 1592 + " tok.hiddenRequested=" 1593 + (mWin.mAppToken != null ? mWin.mAppToken.hiddenRequested : false) 1594 + " tok.hidden=" 1595 + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false) 1596 + " animating=" + mAnimating 1597 + " tok animating=" 1598 + (mAppAnimator != null ? mAppAnimator.animating : false)); 1599 } 1600 1601 mService.enableScreenIfNeededLocked(); 1602 1603 applyEnterAnimationLocked(); 1604 1605 // Force the show in the next prepareSurfaceLocked() call. 1606 mLastAlpha = -1; 1607 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) 1608 Slog.v(TAG, "performShowLocked: mDrawState=HAS_DRAWN in " + mWin); 1609 mDrawState = HAS_DRAWN; 1610 mService.scheduleAnimationLocked(); 1611 1612 int i = mWin.mChildWindows.size(); 1613 while (i > 0) { 1614 i--; 1615 WindowState c = mWin.mChildWindows.get(i); 1616 if (c.mAttachedHidden) { 1617 c.mAttachedHidden = false; 1618 if (c.mWinAnimator.mSurfaceController != null) { 1619 c.mWinAnimator.performShowLocked(); 1620 // It hadn't been shown, which means layout not 1621 // performed on it, so now we want to make sure to 1622 // do a layout. If called from within the transaction 1623 // loop, this will cause it to restart with a new 1624 // layout. 1625 final DisplayContent displayContent = c.getDisplayContent(); 1626 if (displayContent != null) { 1627 displayContent.layoutNeeded = true; 1628 } 1629 } 1630 } 1631 } 1632 1633 if (mWin.mAttrs.type != TYPE_APPLICATION_STARTING && mWin.mAppToken != null) { 1634 mWin.mAppToken.onFirstWindowDrawn(mWin, this); 1635 } 1636 1637 return true; 1638 } 1639 return false; 1640 } 1641 1642 /** 1643 * Have the surface flinger show a surface, robustly dealing with 1644 * error conditions. In particular, if there is not enough memory 1645 * to show the surface, then we will try to get rid of other surfaces 1646 * in order to succeed. 1647 * 1648 * @return Returns true if the surface was successfully shown. 1649 */ 1650 private boolean showSurfaceRobustlyLocked() { 1651 boolean shown = mSurfaceController.showRobustlyInTransaction(); 1652 if (!shown) 1653 return false; 1654 1655 if (mWin.mTurnOnScreen) { 1656 if (DEBUG_VISIBILITY) Slog.v(TAG, "Show surface turning screen on: " + mWin); 1657 mWin.mTurnOnScreen = false; 1658 mAnimator.mBulkUpdateParams |= SET_TURN_ON_SCREEN; 1659 } 1660 return true; 1661 } 1662 1663 void applyEnterAnimationLocked() { 1664 final int transit; 1665 if (mEnterAnimationPending) { 1666 mEnterAnimationPending = false; 1667 transit = WindowManagerPolicy.TRANSIT_ENTER; 1668 } else { 1669 transit = WindowManagerPolicy.TRANSIT_SHOW; 1670 } 1671 applyAnimationLocked(transit, true); 1672 //TODO (multidisplay): Magnification is supported only for the default display. 1673 if (mService.mAccessibilityController != null 1674 && mWin.getDisplayId() == DEFAULT_DISPLAY) { 1675 mService.mAccessibilityController.onWindowTransitionLocked(mWin, transit); 1676 } 1677 } 1678 1679 /** 1680 * Choose the correct animation and set it to the passed WindowState. 1681 * @param transit If AppTransition.TRANSIT_PREVIEW_DONE and the app window has been drawn 1682 * then the animation will be app_starting_exit. Any other value loads the animation from 1683 * the switch statement below. 1684 * @param isEntrance The animation type the last time this was called. Used to keep from 1685 * loading the same animation twice. 1686 * @return true if an animation has been loaded. 1687 */ 1688 boolean applyAnimationLocked(int transit, boolean isEntrance) { 1689 if ((mLocalAnimating && mAnimationIsEntrance == isEntrance) 1690 || mKeyguardGoingAwayAnimation) { 1691 // If we are trying to apply an animation, but already running 1692 // an animation of the same type, then just leave that one alone. 1693 1694 // If we are in a keyguard exit animation, and the window should animate away, modify 1695 // keyguard exit animation such that it also fades out. 1696 if (mAnimation != null && mKeyguardGoingAwayAnimation 1697 && transit == WindowManagerPolicy.TRANSIT_PREVIEW_DONE) { 1698 applyFadeoutDuringKeyguardExitAnimation(); 1699 } 1700 return true; 1701 } 1702 1703 // Only apply an animation if the display isn't frozen. If it is 1704 // frozen, there is no reason to animate and it can cause strange 1705 // artifacts when we unfreeze the display if some different animation 1706 // is running. 1707 if (mService.okToDisplay()) { 1708 int anim = mPolicy.selectAnimationLw(mWin, transit); 1709 int attr = -1; 1710 Animation a = null; 1711 if (anim != 0) { 1712 a = anim != -1 ? AnimationUtils.loadAnimation(mContext, anim) : null; 1713 } else { 1714 switch (transit) { 1715 case WindowManagerPolicy.TRANSIT_ENTER: 1716 attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation; 1717 break; 1718 case WindowManagerPolicy.TRANSIT_EXIT: 1719 attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation; 1720 break; 1721 case WindowManagerPolicy.TRANSIT_SHOW: 1722 attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation; 1723 break; 1724 case WindowManagerPolicy.TRANSIT_HIDE: 1725 attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation; 1726 break; 1727 } 1728 if (attr >= 0) { 1729 a = mService.mAppTransition.loadAnimationAttr(mWin.mAttrs, attr); 1730 } 1731 } 1732 if (DEBUG_ANIM) Slog.v(TAG, 1733 "applyAnimation: win=" + this 1734 + " anim=" + anim + " attr=0x" + Integer.toHexString(attr) 1735 + " a=" + a 1736 + " transit=" + transit 1737 + " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3)); 1738 if (a != null) { 1739 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this); 1740 setAnimation(a); 1741 mAnimationIsEntrance = isEntrance; 1742 } 1743 } else { 1744 clearAnimation(); 1745 } 1746 1747 return mAnimation != null; 1748 } 1749 1750 private void applyFadeoutDuringKeyguardExitAnimation() { 1751 long startTime = mAnimation.getStartTime(); 1752 long duration = mAnimation.getDuration(); 1753 long elapsed = mLastAnimationTime - startTime; 1754 long fadeDuration = duration - elapsed; 1755 if (fadeDuration <= 0) { 1756 // Never mind, this would be no visible animation, so abort the animation change. 1757 return; 1758 } 1759 AnimationSet newAnimation = new AnimationSet(false /* shareInterpolator */); 1760 newAnimation.setDuration(duration); 1761 newAnimation.setStartTime(startTime); 1762 newAnimation.addAnimation(mAnimation); 1763 Animation fadeOut = AnimationUtils.loadAnimation( 1764 mContext, com.android.internal.R.anim.app_starting_exit); 1765 fadeOut.setDuration(fadeDuration); 1766 fadeOut.setStartOffset(elapsed); 1767 newAnimation.addAnimation(fadeOut); 1768 newAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(), mAnimDx, mAnimDy); 1769 mAnimation = newAnimation; 1770 } 1771 1772 public void dump(PrintWriter pw, String prefix, boolean dumpAll) { 1773 if (mAnimating || mLocalAnimating || mAnimationIsEntrance 1774 || mAnimation != null) { 1775 pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating); 1776 pw.print(" mLocalAnimating="); pw.print(mLocalAnimating); 1777 pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance); 1778 pw.print(" mAnimation="); pw.println(mAnimation); 1779 pw.print(" mStackClip="); pw.println(mStackClip); 1780 } 1781 if (mHasTransformation || mHasLocalTransformation) { 1782 pw.print(prefix); pw.print("XForm: has="); 1783 pw.print(mHasTransformation); 1784 pw.print(" hasLocal="); pw.print(mHasLocalTransformation); 1785 pw.print(" "); mTransformation.printShortString(pw); 1786 pw.println(); 1787 } 1788 if (mSurfaceController != null) { 1789 mSurfaceController.dump(pw, prefix, dumpAll); 1790 } 1791 if (dumpAll) { 1792 pw.print(prefix); pw.print("mDrawState="); pw.print(drawStateToString()); 1793 pw.print(prefix); pw.print(" mLastHidden="); pw.println(mLastHidden); 1794 pw.print(prefix); pw.print("mSystemDecorRect="); mSystemDecorRect.printShortString(pw); 1795 pw.print(" last="); mLastSystemDecorRect.printShortString(pw); 1796 if (mHasClipRect) { 1797 pw.print(" mLastClipRect="); mLastClipRect.printShortString(pw); 1798 } 1799 if (!mLastFinalClipRect.isEmpty()) { 1800 pw.print(" mLastFinalClipRect="); mLastFinalClipRect.printShortString(pw); 1801 } 1802 pw.println(); 1803 } 1804 1805 if (mPendingDestroySurface != null) { 1806 pw.print(prefix); pw.print("mPendingDestroySurface="); 1807 pw.println(mPendingDestroySurface); 1808 } 1809 if (mSurfaceResized || mSurfaceDestroyDeferred) { 1810 pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized); 1811 pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred); 1812 } 1813 if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) { 1814 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha); 1815 pw.print(" mAlpha="); pw.print(mAlpha); 1816 pw.print(" mLastAlpha="); pw.println(mLastAlpha); 1817 } 1818 if (mHaveMatrix || mWin.mGlobalScale != 1) { 1819 pw.print(prefix); pw.print("mGlobalScale="); pw.print(mWin.mGlobalScale); 1820 pw.print(" mDsDx="); pw.print(mDsDx); 1821 pw.print(" mDtDx="); pw.print(mDtDx); 1822 pw.print(" mDsDy="); pw.print(mDsDy); 1823 pw.print(" mDtDy="); pw.println(mDtDy); 1824 } 1825 } 1826 1827 @Override 1828 public String toString() { 1829 StringBuffer sb = new StringBuffer("WindowStateAnimator{"); 1830 sb.append(Integer.toHexString(System.identityHashCode(this))); 1831 sb.append(' '); 1832 sb.append(mWin.mAttrs.getTitle()); 1833 sb.append('}'); 1834 return sb.toString(); 1835 } 1836 1837 void reclaimSomeSurfaceMemory(String operation, boolean secure) { 1838 mService.reclaimSomeSurfaceMemoryLocked(this, operation, secure); 1839 } 1840 1841 boolean getShown() { 1842 if (mSurfaceController != null) { 1843 return mSurfaceController.getShown(); 1844 } 1845 return false; 1846 } 1847 1848 void destroySurface() { 1849 try { 1850 if (mSurfaceController != null) { 1851 mSurfaceController.destroyInTransaction(); 1852 } 1853 } catch (RuntimeException e) { 1854 Slog.w(TAG, "Exception thrown when destroying surface " + this 1855 + " surface " + mSurfaceController + " session " + mSession + ": " + e); 1856 } finally { 1857 mWin.setHasSurface(false); 1858 mSurfaceController = null; 1859 mDrawState = NO_SURFACE; 1860 } 1861 } 1862 1863 void setMoveAnimation(int left, int top) { 1864 final Animation a = AnimationUtils.loadAnimation(mContext, 1865 com.android.internal.R.anim.window_move_from_decor); 1866 setAnimation(a); 1867 mAnimDx = mWin.mLastFrame.left - left; 1868 mAnimDy = mWin.mLastFrame.top - top; 1869 mAnimateMove = true; 1870 } 1871} 1872