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