WindowStateAnimator.java revision 76a7165719dc3ccce902953f6244e2c2668aa753
1// Copyright 2012 Google Inc. All Rights Reserved. 2 3package com.android.server.wm; 4 5import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 6 7import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE; 8import static com.android.server.wm.WindowManagerService.LayoutFields.SET_TURN_ON_SCREEN; 9 10import android.content.Context; 11import android.graphics.Matrix; 12import android.graphics.PixelFormat; 13import android.graphics.Point; 14import android.graphics.PointF; 15import android.graphics.Rect; 16import android.graphics.Region; 17import android.os.Debug; 18import android.util.Slog; 19import android.view.DisplayInfo; 20import android.view.Surface; 21import android.view.SurfaceSession; 22import android.view.WindowManager; 23import android.view.WindowManagerPolicy; 24import android.view.WindowManager.LayoutParams; 25import android.view.animation.Animation; 26import android.view.animation.AnimationUtils; 27import android.view.animation.Transformation; 28 29import com.android.server.wm.WindowManagerService.H; 30 31import java.io.PrintWriter; 32import java.util.ArrayList; 33 34class WinAnimatorList extends ArrayList<WindowStateAnimator> { 35} 36 37/** 38 * Keep track of animations and surface operations for a single WindowState. 39 **/ 40class WindowStateAnimator { 41 static final boolean DEBUG_VISIBILITY = WindowManagerService.DEBUG_VISIBILITY; 42 static final boolean DEBUG_ANIM = WindowManagerService.DEBUG_ANIM; 43 static final boolean DEBUG_LAYERS = WindowManagerService.DEBUG_LAYERS; 44 static final boolean DEBUG_STARTING_WINDOW = WindowManagerService.DEBUG_STARTING_WINDOW; 45 static final boolean SHOW_TRANSACTIONS = WindowManagerService.SHOW_TRANSACTIONS; 46 static final boolean SHOW_LIGHT_TRANSACTIONS = WindowManagerService.SHOW_LIGHT_TRANSACTIONS; 47 static final boolean SHOW_SURFACE_ALLOC = WindowManagerService.SHOW_SURFACE_ALLOC; 48 static final boolean localLOGV = WindowManagerService.localLOGV; 49 static final boolean DEBUG_ORIENTATION = WindowManagerService.DEBUG_ORIENTATION; 50 static final boolean DEBUG_SURFACE_TRACE = WindowManagerService.DEBUG_SURFACE_TRACE; 51 52 static final String TAG = "WindowStateAnimator"; 53 54 // Unchanging local convenience fields. 55 final WindowManagerService mService; 56 final WindowState mWin; 57 final WindowStateAnimator mAttachedWinAnimator; 58 final WindowAnimator mAnimator; 59 final AppWindowAnimator mAppAnimator; 60 final Session mSession; 61 final WindowManagerPolicy mPolicy; 62 final Context mContext; 63 final boolean mIsWallpaper; 64 65 // If this is a universe background window, this is the transformation 66 // it is applying to the rest of the universe. 67 final Transformation mUniverseTransform = new Transformation(); 68 69 // Currently running animation. 70 boolean mAnimating; 71 boolean mLocalAnimating; 72 Animation mAnimation; 73 boolean mAnimationIsEntrance; 74 boolean mHasTransformation; 75 boolean mHasLocalTransformation; 76 final Transformation mTransformation = new Transformation(); 77 boolean mWasAnimating; // Were we animating going into the most recent animation step? 78 int mAnimLayer; 79 int mLastLayer; 80 81 Surface mSurface; 82 Surface mPendingDestroySurface; 83 84 /** 85 * Set when we have changed the size of the surface, to know that 86 * we must tell them application to resize (and thus redraw itself). 87 */ 88 boolean mSurfaceResized; 89 90 /** 91 * Set if the client has asked that the destroy of its surface be delayed 92 * until it explicitly says it is okay. 93 */ 94 boolean mSurfaceDestroyDeferred; 95 96 float mShownAlpha = 0; 97 float mAlpha = 0; 98 float mLastAlpha = 0; 99 100 // Used to save animation distances between the time they are calculated and when they are 101 // used. 102 int mAnimDw; 103 int mAnimDh; 104 float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1; 105 float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1; 106 107 boolean mHaveMatrix; 108 109 // For debugging, this is the last information given to the surface flinger. 110 boolean mSurfaceShown; 111 float mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH; 112 int mSurfaceLayer; 113 float mSurfaceAlpha; 114 115 // Set to true if, when the window gets displayed, it should perform 116 // an enter animation. 117 boolean mEnterAnimationPending; 118 119 /** This is set when there is no Surface */ 120 static final int NO_SURFACE = 0; 121 /** This is set after the Surface has been created but before the window has been drawn. During 122 * this time the surface is hidden. */ 123 static final int DRAW_PENDING = 1; 124 /** This is set after the window has finished drawing for the first time but before its surface 125 * is shown. The surface will be displayed when the next layout is run. */ 126 static final int COMMIT_DRAW_PENDING = 2; 127 /** This is set during the time after the window's drawing has been committed, and before its 128 * surface is actually shown. It is used to delay showing the surface until all windows in a 129 * token are ready to be shown. */ 130 static final int READY_TO_SHOW = 3; 131 /** Set when the window has been shown in the screen the first time. */ 132 static final int HAS_DRAWN = 4; 133 static String drawStateToString(int state) { 134 switch (state) { 135 case NO_SURFACE: return "NO_SURFACE"; 136 case DRAW_PENDING: return "DRAW_PENDING"; 137 case COMMIT_DRAW_PENDING: return "COMMIT_DRAW_PENDING"; 138 case READY_TO_SHOW: return "READY_TO_SHOW"; 139 case HAS_DRAWN: return "HAS_DRAWN"; 140 default: return Integer.toString(state); 141 } 142 } 143 int mDrawState; 144 145 /** Was this window last hidden? */ 146 boolean mLastHidden; 147 148 int mAttrFlags; 149 int mAttrType; 150 151 final int mLayerStack; 152 153 public WindowStateAnimator(final WindowState win) { 154 final WindowManagerService service = win.mService; 155 156 mService = service; 157 mAnimator = service.mAnimator; 158 mPolicy = service.mPolicy; 159 mContext = service.mContext; 160 final DisplayInfo displayInfo = win.mDisplayContent.getDisplayInfo(); 161 mAnimDw = displayInfo.appWidth; 162 mAnimDh = displayInfo.appHeight; 163 164 mWin = win; 165 mAttachedWinAnimator = win.mAttachedWindow == null 166 ? null : win.mAttachedWindow.mWinAnimator; 167 mAppAnimator = win.mAppToken == null ? null : win.mAppToken.mAppAnimator; 168 mSession = win.mSession; 169 mAttrFlags = win.mAttrs.flags; 170 mAttrType = win.mAttrs.type; 171 mIsWallpaper = win.mIsWallpaper; 172 mLayerStack = win.mDisplayContent.getDisplay().getLayerStack(); 173 } 174 175 public void setAnimation(Animation anim) { 176 if (localLOGV) Slog.v(TAG, "Setting animation in " + this + ": " + anim); 177 mAnimating = false; 178 mLocalAnimating = false; 179 mAnimation = anim; 180 mAnimation.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION); 181 mAnimation.scaleCurrentDuration(mService.mWindowAnimationScale); 182 // Start out animation gone if window is gone, or visible if window is visible. 183 mTransformation.clear(); 184 mTransformation.setAlpha(mLastHidden ? 0 : 1); 185 mHasLocalTransformation = true; 186 } 187 188 public void clearAnimation() { 189 if (mAnimation != null) { 190 mAnimating = true; 191 mLocalAnimating = false; 192 mAnimation.cancel(); 193 mAnimation = null; 194 } 195 } 196 197 /** Is the window or its container currently animating? */ 198 boolean isAnimating() { 199 return mAnimation != null 200 || (mAttachedWinAnimator != null && mAttachedWinAnimator.mAnimation != null) 201 || (mAppAnimator != null && 202 (mAppAnimator.animation != null 203 || mAppAnimator.mAppToken.inPendingTransaction)); 204 } 205 206 /** Is the window animating the DummyAnimation? */ 207 boolean isDummyAnimation() { 208 return mAppAnimator != null 209 && mAppAnimator.animation == AppWindowAnimator.sDummyAnimation; 210 } 211 212 /** Is this window currently animating? */ 213 boolean isWindowAnimating() { 214 return mAnimation != null; 215 } 216 217 void cancelExitAnimationForNextAnimationLocked() { 218 if (mAnimation != null) { 219 mAnimation.cancel(); 220 mAnimation = null; 221 mLocalAnimating = false; 222 destroySurfaceLocked(); 223 } 224 } 225 226 private boolean stepAnimation(long currentTime) { 227 if ((mAnimation == null) || !mLocalAnimating) { 228 return false; 229 } 230 mTransformation.clear(); 231 final boolean more = mAnimation.getTransformation(currentTime, mTransformation); 232 if (false && DEBUG_ANIM) Slog.v( 233 TAG, "Stepped animation in " + this + 234 ": more=" + more + ", xform=" + mTransformation); 235 return more; 236 } 237 238 // This must be called while inside a transaction. Returns true if 239 // there is more animation to run. 240 boolean stepAnimationLocked(long currentTime) { 241 // Save the animation state as it was before this step so WindowManagerService can tell if 242 // we just started or just stopped animating by comparing mWasAnimating with isAnimating(). 243 mWasAnimating = mAnimating; 244 if (mService.okToDisplay()) { 245 // We will run animations as long as the display isn't frozen. 246 247 if (mWin.isDrawnLw() && mAnimation != null) { 248 mHasTransformation = true; 249 mHasLocalTransformation = true; 250 if (!mLocalAnimating) { 251 if (DEBUG_ANIM) Slog.v( 252 TAG, "Starting animation in " + this + 253 " @ " + currentTime + ": ww=" + mWin.mFrame.width() + 254 " wh=" + mWin.mFrame.height() + 255 " dw=" + mAnimDw + " dh=" + mAnimDh + 256 " scale=" + mService.mWindowAnimationScale); 257 mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(), 258 mAnimDw, mAnimDh); 259 final DisplayInfo displayInfo = mWin.mDisplayContent.getDisplayInfo(); 260 mAnimDw = displayInfo.appWidth; 261 mAnimDh = displayInfo.appHeight; 262 mAnimation.setStartTime(currentTime); 263 mLocalAnimating = true; 264 mAnimating = true; 265 } 266 if ((mAnimation != null) && mLocalAnimating) { 267 if (stepAnimation(currentTime)) { 268 return true; 269 } 270 } 271 if (DEBUG_ANIM) Slog.v( 272 TAG, "Finished animation in " + this + 273 " @ " + currentTime); 274 //WindowManagerService.this.dump(); 275 } 276 mHasLocalTransformation = false; 277 if ((!mLocalAnimating || mAnimationIsEntrance) && mAppAnimator != null 278 && mAppAnimator.animation != null) { 279 // When our app token is animating, we kind-of pretend like 280 // we are as well. Note the mLocalAnimating mAnimationIsEntrance 281 // part of this check means that we will only do this if 282 // our window is not currently exiting, or it is not 283 // locally animating itself. The idea being that one that 284 // is exiting and doing a local animation should be removed 285 // once that animation is done. 286 mAnimating = true; 287 mHasTransformation = true; 288 mTransformation.clear(); 289 return false; 290 } else if (mHasTransformation) { 291 // Little trick to get through the path below to act like 292 // we have finished an animation. 293 mAnimating = true; 294 } else if (isAnimating()) { 295 mAnimating = true; 296 } 297 } else if (mAnimation != null) { 298 // If the display is frozen, and there is a pending animation, 299 // clear it and make sure we run the cleanup code. 300 mAnimating = true; 301 } 302 303 if (!mAnimating && !mLocalAnimating) { 304 return false; 305 } 306 307 // Done animating, clean up. 308 if (DEBUG_ANIM) Slog.v( 309 TAG, "Animation done in " + this + ": exiting=" + mWin.mExiting 310 + ", reportedVisible=" 311 + (mWin.mAppToken != null ? mWin.mAppToken.reportedVisible : false)); 312 313 mAnimating = false; 314 mLocalAnimating = false; 315 if (mAnimation != null) { 316 mAnimation.cancel(); 317 mAnimation = null; 318 } 319 if (mAnimator.mWindowDetachedWallpaper == mWin) { 320 mAnimator.mWindowDetachedWallpaper = null; 321 } 322 mAnimLayer = mWin.mLayer; 323 if (mWin.mIsImWindow) { 324 mAnimLayer += mService.mInputMethodAnimLayerAdjustment; 325 } else if (mIsWallpaper) { 326 mAnimLayer += mService.mWallpaperAnimLayerAdjustment; 327 } 328 if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this 329 + " anim layer: " + mAnimLayer); 330 mHasTransformation = false; 331 mHasLocalTransformation = false; 332 if (mWin.mPolicyVisibility != mWin.mPolicyVisibilityAfterAnim) { 333 if (WindowState.DEBUG_VISIBILITY) { 334 Slog.v(TAG, "Policy visibility changing after anim in " + this + ": " 335 + mWin.mPolicyVisibilityAfterAnim); 336 } 337 mWin.mPolicyVisibility = mWin.mPolicyVisibilityAfterAnim; 338 mService.mLayoutNeeded = true; 339 if (!mWin.mPolicyVisibility) { 340 if (mService.mCurrentFocus == mWin) { 341 mService.mFocusMayChange = true; 342 } 343 // Window is no longer visible -- make sure if we were waiting 344 // for it to be displayed before enabling the display, that 345 // we allow the display to be enabled now. 346 mService.enableScreenIfNeededLocked(); 347 } 348 } 349 mTransformation.clear(); 350 if (mDrawState == HAS_DRAWN 351 && mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING 352 && mWin.mAppToken != null 353 && mWin.mAppToken.firstWindowDrawn 354 && mWin.mAppToken.startingData != null) { 355 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting " 356 + mWin.mToken + ": first real window done animating"); 357 mService.mFinishedStarting.add(mWin.mAppToken); 358 mService.mH.sendEmptyMessage(H.FINISHED_STARTING); 359 } 360 361 finishExit(); 362 final int displayId = mWin.mDisplayContent.getDisplayId(); 363 mAnimator.setPendingLayoutChanges(displayId, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM); 364 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) mService.debugLayoutRepeats( 365 "WindowStateAnimator", mAnimator.mPendingLayoutChanges.get(displayId)); 366 367 if (mWin.mAppToken != null) { 368 mWin.mAppToken.updateReportedVisibilityLocked(); 369 } 370 371 return false; 372 } 373 374 void finishExit() { 375 if (WindowManagerService.DEBUG_ANIM) Slog.v( 376 TAG, "finishExit in " + this 377 + ": exiting=" + mWin.mExiting 378 + " remove=" + mWin.mRemoveOnExit 379 + " windowAnimating=" + isWindowAnimating()); 380 381 final int N = mWin.mChildWindows.size(); 382 for (int i=0; i<N; i++) { 383 mWin.mChildWindows.get(i).mWinAnimator.finishExit(); 384 } 385 386 if (!mWin.mExiting) { 387 return; 388 } 389 390 if (isWindowAnimating()) { 391 return; 392 } 393 394 if (WindowManagerService.localLOGV) Slog.v( 395 TAG, "Exit animation finished in " + this 396 + ": remove=" + mWin.mRemoveOnExit); 397 if (mSurface != null) { 398 mService.mDestroySurface.add(mWin); 399 mWin.mDestroying = true; 400 if (WindowState.SHOW_TRANSACTIONS) WindowManagerService.logSurface( 401 mWin, "HIDE (finishExit)", null); 402 hide(); 403 } 404 mWin.mExiting = false; 405 if (mWin.mRemoveOnExit) { 406 mService.mPendingRemove.add(mWin); 407 mWin.mRemoveOnExit = false; 408 } 409 mAnimator.hideWallpapersLocked(mWin); 410 } 411 412 void hide() { 413 if (!mLastHidden) { 414 //dump(); 415 mLastHidden = true; 416 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, 417 "HIDE (performLayout)", null); 418 if (mSurface != null) { 419 mSurfaceShown = false; 420 try { 421 mSurface.hide(); 422 } catch (RuntimeException e) { 423 Slog.w(TAG, "Exception hiding surface in " + mWin); 424 } 425 } 426 } 427 } 428 429 boolean finishDrawingLocked() { 430 if (DEBUG_STARTING_WINDOW && 431 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { 432 Slog.v(TAG, "Finishing drawing window " + mWin + ": mDrawState=" 433 + drawStateToString(mDrawState)); 434 } 435 if (mDrawState == DRAW_PENDING) { 436 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION) 437 Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + this + " in " 438 + mSurface); 439 if (DEBUG_STARTING_WINDOW && 440 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { 441 Slog.v(TAG, "Draw state now committed in " + mWin); 442 } 443 mDrawState = COMMIT_DRAW_PENDING; 444 return true; 445 } 446 return false; 447 } 448 449 // This must be called while inside a transaction. 450 boolean commitFinishDrawingLocked(long currentTime) { 451 if (DEBUG_STARTING_WINDOW && 452 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { 453 Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState=" 454 + drawStateToString(mDrawState)); 455 } 456 if (mDrawState != COMMIT_DRAW_PENDING) { 457 return false; 458 } 459 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) { 460 Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurface); 461 } 462 mDrawState = READY_TO_SHOW; 463 final boolean starting = mWin.mAttrs.type == TYPE_APPLICATION_STARTING; 464 final AppWindowToken atoken = mWin.mAppToken; 465 if (atoken == null || atoken.allDrawn || starting) { 466 performShowLocked(); 467 } 468 return true; 469 } 470 471 static class SurfaceTrace extends Surface { 472 private final static String SURFACE_TAG = "SurfaceTrace"; 473 final static ArrayList<SurfaceTrace> sSurfaces = new ArrayList<SurfaceTrace>(); 474 475 private float mSurfaceTraceAlpha = 0; 476 private int mLayer; 477 private final PointF mPosition = new PointF(); 478 private final Point mSize = new Point(); 479 private final Rect mWindowCrop = new Rect(); 480 private boolean mShown = false; 481 private int mLayerStack; 482 private String mName; 483 484 public SurfaceTrace(SurfaceSession s, 485 String name, int w, int h, int format, int flags) 486 throws OutOfResourcesException { 487 super(s, name, w, h, format, flags); 488 mName = name != null ? name : "Not named"; 489 mSize.set(w, h); 490 Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by " 491 + Debug.getCallers(3)); 492 } 493 494 @Override 495 public void setAlpha(float alpha) { 496 super.setAlpha(alpha); 497 mSurfaceTraceAlpha = alpha; 498 Slog.v(SURFACE_TAG, "setAlpha: " + this + ". Called by " 499 + Debug.getCallers(3)); 500 } 501 502 @Override 503 public void setLayer(int zorder) { 504 super.setLayer(zorder); 505 mLayer = zorder; 506 Slog.v(SURFACE_TAG, "setLayer: " + this + ". Called by " 507 + Debug.getCallers(3)); 508 509 sSurfaces.remove(this); 510 int i; 511 for (i = sSurfaces.size() - 1; i >= 0; i--) { 512 SurfaceTrace s = sSurfaces.get(i); 513 if (s.mLayer < zorder) { 514 break; 515 } 516 } 517 sSurfaces.add(i + 1, this); 518 } 519 520 @Override 521 public void setPosition(float x, float y) { 522 super.setPosition(x, y); 523 mPosition.set(x, y); 524 Slog.v(SURFACE_TAG, "setPosition: " + this + ". Called by " 525 + Debug.getCallers(3)); 526 } 527 528 @Override 529 public void setSize(int w, int h) { 530 super.setSize(w, h); 531 mSize.set(w, h); 532 Slog.v(SURFACE_TAG, "setSize: " + this + ". Called by " 533 + Debug.getCallers(3)); 534 } 535 536 @Override 537 public void setWindowCrop(Rect crop) { 538 super.setWindowCrop(crop); 539 if (crop != null) { 540 mWindowCrop.set(crop); 541 } 542 Slog.v(SURFACE_TAG, "setWindowCrop: " + this + ". Called by " 543 + Debug.getCallers(3)); 544 } 545 546 @Override 547 public void setLayerStack(int layerStack) { 548 super.setLayerStack(layerStack); 549 mLayerStack = layerStack; 550 Slog.v(SURFACE_TAG, "setLayerStack: " + this + ". Called by " + Debug.getCallers(3)); 551 } 552 553 @Override 554 public void hide() { 555 super.hide(); 556 mShown = false; 557 Slog.v(SURFACE_TAG, "hide: " + this + ". Called by " 558 + Debug.getCallers(3)); 559 } 560 @Override 561 public void show() { 562 super.show(); 563 mShown = true; 564 Slog.v(SURFACE_TAG, "show: " + this + ". Called by " 565 + Debug.getCallers(3)); 566 } 567 568 @Override 569 public void destroy() { 570 super.destroy(); 571 Slog.v(SURFACE_TAG, "destroy: " + this + ". Called by " 572 + Debug.getCallers(3)); 573 sSurfaces.remove(this); 574 } 575 576 @Override 577 public void release() { 578 super.release(); 579 Slog.v(SURFACE_TAG, "release: " + this + ". Called by " 580 + Debug.getCallers(3)); 581 sSurfaces.remove(this); 582 } 583 584 static void dumpAllSurfaces() { 585 final int N = sSurfaces.size(); 586 for (int i = 0; i < N; i++) { 587 Slog.i(TAG, "SurfaceDump: " + sSurfaces.get(i)); 588 } 589 } 590 591 @Override 592 public String toString() { 593 return "Surface " + Integer.toHexString(System.identityHashCode(this)) + " " 594 + mName + " (" + mLayerStack + "): shown=" + mShown + " layer=" + mLayer 595 + " alpha=" + mSurfaceTraceAlpha + " " + mPosition.x + "," + mPosition.y 596 + " " + mSize.x + "x" + mSize.y 597 + " crop=" + mWindowCrop.toShortString(); 598 } 599 } 600 601 Surface createSurfaceLocked() { 602 if (mSurface == null) { 603 if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG, 604 "createSurface " + this + ": mDrawState=DRAW_PENDING"); 605 mDrawState = DRAW_PENDING; 606 if (mWin.mAppToken != null) { 607 mWin.mAppToken.allDrawn = false; 608 } 609 610 mService.makeWindowFreezingScreenIfNeededLocked(mWin); 611 612 int flags = Surface.HIDDEN; 613 final WindowManager.LayoutParams attrs = mWin.mAttrs; 614 615 if ((attrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) { 616 flags |= Surface.SECURE; 617 } 618 if (WindowState.DEBUG_VISIBILITY) Slog.v( 619 TAG, "Creating surface in session " 620 + mSession.mSurfaceSession + " window " + this 621 + " w=" + mWin.mCompatFrame.width() 622 + " h=" + mWin.mCompatFrame.height() + " format=" 623 + attrs.format + " flags=" + flags); 624 625 int w = mWin.mCompatFrame.width(); 626 int h = mWin.mCompatFrame.height(); 627 if ((attrs.flags & LayoutParams.FLAG_SCALED) != 0) { 628 // for a scaled surface, we always want the requested 629 // size. 630 w = mWin.mRequestedWidth; 631 h = mWin.mRequestedHeight; 632 } 633 634 // Something is wrong and SurfaceFlinger will not like this, 635 // try to revert to sane values 636 if (w <= 0) w = 1; 637 if (h <= 0) h = 1; 638 639 mSurfaceShown = false; 640 mSurfaceLayer = 0; 641 mSurfaceAlpha = 0; 642 mSurfaceX = 0; 643 mSurfaceY = 0; 644 mSurfaceW = w; 645 mSurfaceH = h; 646 mWin.mLastSystemDecorRect.set(0, 0, 0, 0); 647 try { 648 final boolean isHwAccelerated = (attrs.flags & 649 WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0; 650 final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format; 651 if (!PixelFormat.formatHasAlpha(attrs.format)) { 652 flags |= Surface.OPAQUE; 653 } 654 if (DEBUG_SURFACE_TRACE) { 655 mSurface = new SurfaceTrace( 656 mSession.mSurfaceSession, 657 attrs.getTitle().toString(), 658 w, h, format, flags); 659 } else { 660 mSurface = new Surface( 661 mSession.mSurfaceSession, 662 attrs.getTitle().toString(), 663 w, h, format, flags); 664 } 665 mWin.mHasSurface = true; 666 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG, 667 " CREATE SURFACE " 668 + mSurface + " IN SESSION " 669 + mSession.mSurfaceSession 670 + ": pid=" + mSession.mPid + " format=" 671 + attrs.format + " flags=0x" 672 + Integer.toHexString(flags) 673 + " / " + this); 674 } catch (Surface.OutOfResourcesException e) { 675 mWin.mHasSurface = false; 676 Slog.w(TAG, "OutOfResourcesException creating surface"); 677 mService.reclaimSomeSurfaceMemoryLocked(this, "create", true); 678 mDrawState = NO_SURFACE; 679 return null; 680 } catch (Exception e) { 681 mWin.mHasSurface = false; 682 Slog.e(TAG, "Exception creating surface", e); 683 mDrawState = NO_SURFACE; 684 return null; 685 } 686 687 if (WindowManagerService.localLOGV) Slog.v( 688 TAG, "Got surface: " + mSurface 689 + ", set left=" + mWin.mFrame.left + " top=" + mWin.mFrame.top 690 + ", animLayer=" + mAnimLayer); 691 if (SHOW_LIGHT_TRANSACTIONS) { 692 Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked"); 693 WindowManagerService.logSurface(mWin, "CREATE pos=(" 694 + mWin.mFrame.left + "," + mWin.mFrame.top + ") (" 695 + mWin.mCompatFrame.width() + "x" + mWin.mCompatFrame.height() 696 + "), layer=" + mAnimLayer + " HIDE", null); 697 } 698 Surface.openTransaction(); 699 try { 700 try { 701 mSurfaceX = mWin.mFrame.left + mWin.mXOffset; 702 mSurfaceY = mWin.mFrame.top + mWin.mYOffset; 703 mSurface.setPosition(mSurfaceX, mSurfaceY); 704 mSurfaceLayer = mAnimLayer; 705 mSurface.setLayerStack(mLayerStack); 706 mSurface.setLayer(mAnimLayer); 707 mSurface.setAlpha(0); 708 mSurfaceShown = false; 709 } catch (RuntimeException e) { 710 Slog.w(TAG, "Error creating surface in " + w, e); 711 mService.reclaimSomeSurfaceMemoryLocked(this, "create-init", true); 712 } 713 mLastHidden = true; 714 } finally { 715 Surface.closeTransaction(); 716 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 717 "<<< CLOSE TRANSACTION createSurfaceLocked"); 718 } 719 if (WindowManagerService.localLOGV) Slog.v( 720 TAG, "Created surface " + this); 721 } 722 return mSurface; 723 } 724 725 void destroySurfaceLocked() { 726 if (mWin.mAppToken != null && mWin == mWin.mAppToken.startingWindow) { 727 mWin.mAppToken.startingDisplayed = false; 728 } 729 730 if (mSurface != null) { 731 732 int i = mWin.mChildWindows.size(); 733 while (i > 0) { 734 i--; 735 WindowState c = mWin.mChildWindows.get(i); 736 c.mAttachedHidden = true; 737 } 738 739 try { 740 if (DEBUG_VISIBILITY) { 741 RuntimeException e = null; 742 if (!WindowManagerService.HIDE_STACK_CRAWLS) { 743 e = new RuntimeException(); 744 e.fillInStackTrace(); 745 } 746 Slog.w(TAG, "Window " + this + " destroying surface " 747 + mSurface + ", session " + mSession, e); 748 } 749 if (mSurfaceDestroyDeferred) { 750 if (mSurface != null && mPendingDestroySurface != mSurface) { 751 if (mPendingDestroySurface != null) { 752 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { 753 RuntimeException e = null; 754 if (!WindowManagerService.HIDE_STACK_CRAWLS) { 755 e = new RuntimeException(); 756 e.fillInStackTrace(); 757 } 758 WindowManagerService.logSurface(mWin, "DESTROY PENDING", e); 759 } 760 mPendingDestroySurface.destroy(); 761 } 762 mPendingDestroySurface = mSurface; 763 } 764 } else { 765 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { 766 RuntimeException e = null; 767 if (!WindowManagerService.HIDE_STACK_CRAWLS) { 768 e = new RuntimeException(); 769 e.fillInStackTrace(); 770 } 771 WindowManagerService.logSurface(mWin, "DESTROY", e); 772 } 773 mSurface.destroy(); 774 } 775 mAnimator.hideWallpapersLocked(mWin); 776 } catch (RuntimeException e) { 777 Slog.w(TAG, "Exception thrown when destroying Window " + this 778 + " surface " + mSurface + " session " + mSession 779 + ": " + e.toString()); 780 } 781 782 mSurfaceShown = false; 783 mSurface = null; 784 mWin.mHasSurface =false; 785 mDrawState = NO_SURFACE; 786 } 787 } 788 789 void destroyDeferredSurfaceLocked() { 790 try { 791 if (mPendingDestroySurface != null) { 792 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { 793 RuntimeException e = null; 794 if (!WindowManagerService.HIDE_STACK_CRAWLS) { 795 e = new RuntimeException(); 796 e.fillInStackTrace(); 797 } 798 WindowManagerService.logSurface(mWin, "DESTROY PENDING", e); 799 } 800 mPendingDestroySurface.destroy(); 801 mAnimator.hideWallpapersLocked(mWin); 802 } 803 } catch (RuntimeException e) { 804 Slog.w(TAG, "Exception thrown when destroying Window " 805 + this + " surface " + mPendingDestroySurface 806 + " session " + mSession + ": " + e.toString()); 807 } 808 mSurfaceDestroyDeferred = false; 809 mPendingDestroySurface = null; 810 } 811 812 void computeShownFrameLocked() { 813 final boolean selfTransformation = mHasLocalTransformation; 814 Transformation attachedTransformation = 815 (mAttachedWinAnimator != null && mAttachedWinAnimator.mHasLocalTransformation) 816 ? mAttachedWinAnimator.mTransformation : null; 817 Transformation appTransformation = (mAppAnimator != null && mAppAnimator.hasTransformation) 818 ? mAppAnimator.transformation : null; 819 820 // Wallpapers are animated based on the "real" window they 821 // are currently targeting. 822 if (mIsWallpaper && mAnimator.mLowerWallpaperTarget == null 823 && mAnimator.mWallpaperTarget != null) { 824 final WindowStateAnimator wallpaperAnimator = mAnimator.mWallpaperTarget.mWinAnimator; 825 if (wallpaperAnimator.mHasLocalTransformation && 826 wallpaperAnimator.mAnimation != null && 827 !wallpaperAnimator.mAnimation.getDetachWallpaper()) { 828 attachedTransformation = wallpaperAnimator.mTransformation; 829 if (WindowManagerService.DEBUG_WALLPAPER && attachedTransformation != null) { 830 Slog.v(TAG, "WP target attached xform: " + attachedTransformation); 831 } 832 } 833 final AppWindowAnimator wpAppAnimator = mAnimator.mWpAppAnimator; 834 if (wpAppAnimator != null && wpAppAnimator.hasTransformation 835 && wpAppAnimator.animation != null 836 && !wpAppAnimator.animation.getDetachWallpaper()) { 837 appTransformation = wpAppAnimator.transformation; 838 if (WindowManagerService.DEBUG_WALLPAPER && appTransformation != null) { 839 Slog.v(TAG, "WP target app xform: " + appTransformation); 840 } 841 } 842 } 843 844 final boolean screenAnimation = mService.mAnimator.mScreenRotationAnimation != null 845 && mService.mAnimator.mScreenRotationAnimation.isAnimating(); 846 if (selfTransformation || attachedTransformation != null 847 || appTransformation != null || screenAnimation) { 848 // cache often used attributes locally 849 final Rect frame = mWin.mFrame; 850 final float tmpFloats[] = mService.mTmpFloats; 851 final Matrix tmpMatrix = mWin.mTmpMatrix; 852 853 // Compute the desired transformation. 854 if (screenAnimation) { 855 // If we are doing a screen animation, the global rotation 856 // applied to windows can result in windows that are carefully 857 // aligned with each other to slightly separate, allowing you 858 // to see what is behind them. An unsightly mess. This... 859 // thing... magically makes it call good: scale each window 860 // slightly (two pixels larger in each dimension, from the 861 // window's center). 862 final float w = frame.width(); 863 final float h = frame.height(); 864 if (w>=1 && h>=1) { 865 tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2); 866 } else { 867 tmpMatrix.reset(); 868 } 869 } else { 870 tmpMatrix.reset(); 871 } 872 tmpMatrix.postScale(mWin.mGlobalScale, mWin.mGlobalScale); 873 if (selfTransformation) { 874 tmpMatrix.postConcat(mTransformation.getMatrix()); 875 } 876 tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset); 877 if (attachedTransformation != null) { 878 tmpMatrix.postConcat(attachedTransformation.getMatrix()); 879 } 880 if (appTransformation != null) { 881 tmpMatrix.postConcat(appTransformation.getMatrix()); 882 } 883 if (mAnimator.mUniverseBackground != null) { 884 tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix()); 885 } 886 if (screenAnimation) { 887 tmpMatrix.postConcat( 888 mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getMatrix()); 889 } 890 891 // "convert" it into SurfaceFlinger's format 892 // (a 2x2 matrix + an offset) 893 // Here we must not transform the position of the surface 894 // since it is already included in the transformation. 895 //Slog.i(TAG, "Transform: " + matrix); 896 897 mHaveMatrix = true; 898 tmpMatrix.getValues(tmpFloats); 899 mDsDx = tmpFloats[Matrix.MSCALE_X]; 900 mDtDx = tmpFloats[Matrix.MSKEW_Y]; 901 mDsDy = tmpFloats[Matrix.MSKEW_X]; 902 mDtDy = tmpFloats[Matrix.MSCALE_Y]; 903 float x = tmpFloats[Matrix.MTRANS_X]; 904 float y = tmpFloats[Matrix.MTRANS_Y]; 905 int w = frame.width(); 906 int h = frame.height(); 907 mWin.mShownFrame.set(x, y, x+w, y+h); 908 909 // Now set the alpha... but because our current hardware 910 // can't do alpha transformation on a non-opaque surface, 911 // turn it off if we are running an animation that is also 912 // transforming since it is more important to have that 913 // animation be smooth. 914 mShownAlpha = mAlpha; 915 if (!mService.mLimitedAlphaCompositing 916 || (!PixelFormat.formatHasAlpha(mWin.mAttrs.format) 917 || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy) 918 && x == frame.left && y == frame.top))) { 919 //Slog.i(TAG, "Applying alpha transform"); 920 if (selfTransformation) { 921 mShownAlpha *= mTransformation.getAlpha(); 922 } 923 if (attachedTransformation != null) { 924 mShownAlpha *= attachedTransformation.getAlpha(); 925 } 926 if (appTransformation != null) { 927 mShownAlpha *= appTransformation.getAlpha(); 928 } 929 if (mAnimator.mUniverseBackground != null) { 930 mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha(); 931 } 932 if (screenAnimation) { 933 mShownAlpha *= 934 mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getAlpha(); 935 } 936 } else { 937 //Slog.i(TAG, "Not applying alpha transform"); 938 } 939 940 if ((DEBUG_SURFACE_TRACE || WindowManagerService.localLOGV) && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v( 941 TAG, "computeShownFrameLocked: Animating " + this + 942 " mAlpha=" + mAlpha + 943 " self=" + (selfTransformation ? mTransformation.getAlpha() : "null") + 944 " attached=" + (attachedTransformation == null ? "null" : attachedTransformation.getAlpha()) + 945 " app=" + (appTransformation == null ? "null" : appTransformation.getAlpha()) + 946 " screen=" + (screenAnimation ? mService.mAnimator.mScreenRotationAnimation.getEnterTransformation().getAlpha() 947 : "null")); 948 return; 949 } else if (mIsWallpaper && 950 (mAnimator.mPendingActions & WindowAnimator.WALLPAPER_ACTION_PENDING) != 0) { 951 return; 952 } 953 954 if (WindowManagerService.localLOGV) Slog.v( 955 TAG, "computeShownFrameLocked: " + this + 956 " not attached, mAlpha=" + mAlpha); 957 if (mAnimator.mUniverseBackground != null && 958 mWin.mAttrs.type != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND 959 && mWin.mBaseLayer < mAnimator.mAboveUniverseLayer) { 960 final Rect frame = mWin.mFrame; 961 final float tmpFloats[] = mService.mTmpFloats; 962 final Matrix tmpMatrix = mWin.mTmpMatrix; 963 tmpMatrix.setScale(mWin.mGlobalScale, mWin.mGlobalScale); 964 tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset); 965 tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix()); 966 tmpMatrix.getValues(tmpFloats); 967 mHaveMatrix = true; 968 mDsDx = tmpFloats[Matrix.MSCALE_X]; 969 mDtDx = tmpFloats[Matrix.MSKEW_Y]; 970 mDsDy = tmpFloats[Matrix.MSKEW_X]; 971 mDtDy = tmpFloats[Matrix.MSCALE_Y]; 972 float x = tmpFloats[Matrix.MTRANS_X]; 973 float y = tmpFloats[Matrix.MTRANS_Y]; 974 int w = frame.width(); 975 int h = frame.height(); 976 mWin.mShownFrame.set(x, y, x+w, y+h); 977 mShownAlpha = mAlpha * mAnimator.mUniverseBackground.mUniverseTransform.getAlpha(); 978 } else { 979 mWin.mShownFrame.set(mWin.mFrame); 980 if (mWin.mXOffset != 0 || mWin.mYOffset != 0) { 981 mWin.mShownFrame.offset(mWin.mXOffset, mWin.mYOffset); 982 } 983 mShownAlpha = mAlpha; 984 mHaveMatrix = false; 985 mDsDx = mWin.mGlobalScale; 986 mDtDx = 0; 987 mDsDy = 0; 988 mDtDy = mWin.mGlobalScale; 989 } 990 } 991 992 void applyDecorRect(final Rect decorRect) { 993 final WindowState w = mWin; 994 // Compute the offset of the window in relation to the decor rect. 995 final int offX = w.mXOffset + w.mFrame.left; 996 final int offY = w.mYOffset + w.mFrame.top; 997 // Initialize the decor rect to the entire frame. 998 w.mSystemDecorRect.set(0, 0, w.mFrame.width(), w.mFrame.height()); 999 // Intersect with the decor rect, offsetted by window position. 1000 w.mSystemDecorRect.intersect(decorRect.left-offX, decorRect.top-offY, 1001 decorRect.right-offX, decorRect.bottom-offY); 1002 // If size compatibility is being applied to the window, the 1003 // surface is scaled relative to the screen. Also apply this 1004 // scaling to the crop rect. We aren't using the standard rect 1005 // scale function because we want to round things to make the crop 1006 // always round to a larger rect to ensure we don't crop too 1007 // much and hide part of the window that should be seen. 1008 if (w.mEnforceSizeCompat && w.mInvGlobalScale != 1.0f) { 1009 final float scale = w.mInvGlobalScale; 1010 w.mSystemDecorRect.left = (int) (w.mSystemDecorRect.left * scale - 0.5f); 1011 w.mSystemDecorRect.top = (int) (w.mSystemDecorRect.top * scale - 0.5f); 1012 w.mSystemDecorRect.right = (int) ((w.mSystemDecorRect.right+1) * scale - 0.5f); 1013 w.mSystemDecorRect.bottom = (int) ((w.mSystemDecorRect.bottom+1) * scale - 0.5f); 1014 } 1015 } 1016 1017 void updateSurfaceWindowCrop(final boolean recoveringMemory) { 1018 final WindowState w = mWin; 1019 1020 // Need to recompute a new system decor rect each time. 1021 if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) { 1022 // Currently can't do this cropping for scaled windows. We'll 1023 // just keep the crop rect the same as the source surface. 1024 w.mSystemDecorRect.set(0, 0, w.mRequestedWidth, w.mRequestedHeight); 1025 } else if (w.mLayer >= mService.mSystemDecorLayer) { 1026 // Above the decor layer is easy, just use the entire window. 1027 // Unless we have a universe background... in which case all the 1028 // windows need to be cropped by the screen, so they don't cover 1029 // the universe background. 1030 if (mAnimator.mUniverseBackground == null) { 1031 w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), 1032 w.mCompatFrame.height()); 1033 } else { 1034 applyDecorRect(mService.mScreenRect); 1035 } 1036 } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND) { 1037 // The universe background isn't cropped. 1038 w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), 1039 w.mCompatFrame.height()); 1040 } else { 1041 applyDecorRect(mService.mSystemDecorRect); 1042 } 1043 1044 if (!w.mSystemDecorRect.equals(w.mLastSystemDecorRect)) { 1045 w.mLastSystemDecorRect.set(w.mSystemDecorRect); 1046 try { 1047 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, 1048 "CROP " + w.mSystemDecorRect.toShortString(), null); 1049 mSurface.setWindowCrop(w.mSystemDecorRect); 1050 } catch (RuntimeException e) { 1051 Slog.w(TAG, "Error setting crop surface of " + w 1052 + " crop=" + w.mSystemDecorRect.toShortString(), e); 1053 if (!recoveringMemory) { 1054 mService.reclaimSomeSurfaceMemoryLocked(this, "crop", true); 1055 } 1056 } 1057 } 1058 } 1059 1060 void setSurfaceBoundaries(final boolean recoveringMemory) { 1061 final WindowState w = mWin; 1062 int width, height; 1063 if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) { 1064 // for a scaled surface, we just want to use 1065 // the requested size. 1066 width = w.mRequestedWidth; 1067 height = w.mRequestedHeight; 1068 } else { 1069 width = w.mCompatFrame.width(); 1070 height = w.mCompatFrame.height(); 1071 } 1072 1073 if (width < 1) { 1074 width = 1; 1075 } 1076 if (height < 1) { 1077 height = 1; 1078 } 1079 final boolean surfaceResized = mSurfaceW != width || mSurfaceH != height; 1080 if (surfaceResized) { 1081 mSurfaceW = width; 1082 mSurfaceH = height; 1083 } 1084 1085 final float left = w.mShownFrame.left; 1086 final float top = w.mShownFrame.top; 1087 if (mSurfaceX != left || mSurfaceY != top) { 1088 try { 1089 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, 1090 "POS " + left + ", " + top, null); 1091 mSurfaceX = left; 1092 mSurfaceY = top; 1093 mSurface.setPosition(left, top); 1094 } catch (RuntimeException e) { 1095 Slog.w(TAG, "Error positioning surface of " + w 1096 + " pos=(" + left 1097 + "," + top + ")", e); 1098 if (!recoveringMemory) { 1099 mService.reclaimSomeSurfaceMemoryLocked(this, "position", true); 1100 } 1101 } 1102 } 1103 1104 if (surfaceResized) { 1105 try { 1106 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, 1107 "SIZE " + width + "x" + height, null); 1108 mSurfaceResized = true; 1109 mSurface.setSize(width, height); 1110 final int displayId = w.mDisplayContent.getDisplayId(); 1111 mAnimator.setPendingLayoutChanges(displayId, 1112 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); 1113 if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) { 1114 final DisplayInfo displayInfo = mWin.mDisplayContent.getDisplayInfo(); 1115 mService.startDimming(this, w.mExiting ? 0 : w.mAttrs.dimAmount, 1116 displayInfo.appWidth, displayInfo.appHeight); 1117 } 1118 } catch (RuntimeException e) { 1119 // If something goes wrong with the surface (such 1120 // as running out of memory), don't take down the 1121 // entire system. 1122 Slog.e(TAG, "Error resizing surface of " + w 1123 + " size=(" + width + "x" + height + ")", e); 1124 if (!recoveringMemory) { 1125 mService.reclaimSomeSurfaceMemoryLocked(this, "size", true); 1126 } 1127 } 1128 } 1129 1130 updateSurfaceWindowCrop(recoveringMemory); 1131 } 1132 1133 public void prepareSurfaceLocked(final boolean recoveringMemory) { 1134 final WindowState w = mWin; 1135 if (mSurface == null) { 1136 if (w.mOrientationChanging) { 1137 if (DEBUG_ORIENTATION) { 1138 Slog.v(TAG, "Orientation change skips hidden " + w); 1139 } 1140 w.mOrientationChanging = false; 1141 } 1142 return; 1143 } 1144 1145 boolean displayed = false; 1146 1147 computeShownFrameLocked(); 1148 1149 setSurfaceBoundaries(recoveringMemory); 1150 1151 if (mIsWallpaper && !mWin.mWallpaperVisible) { 1152 // Wallpaper is no longer visible and there is no wp target => hide it. 1153 hide(); 1154 } else if (w.mAttachedHidden || !w.isReadyForDisplay()) { 1155 hide(); 1156 mAnimator.hideWallpapersLocked(w); 1157 1158 // If we are waiting for this window to handle an 1159 // orientation change, well, it is hidden, so 1160 // doesn't really matter. Note that this does 1161 // introduce a potential glitch if the window 1162 // becomes unhidden before it has drawn for the 1163 // new orientation. 1164 if (w.mOrientationChanging) { 1165 w.mOrientationChanging = false; 1166 if (DEBUG_ORIENTATION) Slog.v(TAG, 1167 "Orientation change skips hidden " + w); 1168 } 1169 } else if (mLastLayer != mAnimLayer 1170 || mLastAlpha != mShownAlpha 1171 || mLastDsDx != mDsDx 1172 || mLastDtDx != mDtDx 1173 || mLastDsDy != mDsDy 1174 || mLastDtDy != mDtDy 1175 || w.mLastHScale != w.mHScale 1176 || w.mLastVScale != w.mVScale 1177 || mLastHidden) { 1178 displayed = true; 1179 mLastAlpha = mShownAlpha; 1180 mLastLayer = mAnimLayer; 1181 mLastDsDx = mDsDx; 1182 mLastDtDx = mDtDx; 1183 mLastDsDy = mDsDy; 1184 mLastDtDy = mDtDy; 1185 w.mLastHScale = w.mHScale; 1186 w.mLastVScale = w.mVScale; 1187 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, 1188 "alpha=" + mShownAlpha + " layer=" + mAnimLayer 1189 + " matrix=[" + (mDsDx*w.mHScale) 1190 + "," + (mDtDx*w.mVScale) 1191 + "][" + (mDsDy*w.mHScale) 1192 + "," + (mDtDy*w.mVScale) + "]", null); 1193 if (mSurface != null) { 1194 try { 1195 mSurfaceAlpha = mShownAlpha; 1196 mSurface.setAlpha(mShownAlpha); 1197 mSurfaceLayer = mAnimLayer; 1198 mSurface.setLayer(mAnimLayer); 1199 mSurface.setMatrix( 1200 mDsDx*w.mHScale, mDtDx*w.mVScale, 1201 mDsDy*w.mHScale, mDtDy*w.mVScale); 1202 1203 if (mLastHidden && mDrawState == HAS_DRAWN) { 1204 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, 1205 "SHOW (performLayout)", null); 1206 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w 1207 + " during relayout"); 1208 if (showSurfaceRobustlyLocked()) { 1209 mLastHidden = false; 1210 if (mIsWallpaper) { 1211 mService.dispatchWallpaperVisibility(w, true); 1212 } 1213 } else { 1214 w.mOrientationChanging = false; 1215 } 1216 } 1217 if (mSurface != null) { 1218 w.mToken.hasVisible = true; 1219 } 1220 } catch (RuntimeException e) { 1221 Slog.w(TAG, "Error updating surface in " + w, e); 1222 if (!recoveringMemory) { 1223 mService.reclaimSomeSurfaceMemoryLocked(this, "update", true); 1224 } 1225 } 1226 } 1227 } else { 1228 if (DEBUG_ANIM && isAnimating()) { 1229 Slog.v(TAG, "prepareSurface: No changes in animation for " + this); 1230 } 1231 displayed = true; 1232 } 1233 1234 if (displayed) { 1235 if (w.mOrientationChanging) { 1236 if (!w.isDrawnLw()) { 1237 mAnimator.mBulkUpdateParams &= ~SET_ORIENTATION_CHANGE_COMPLETE; 1238 if (DEBUG_ORIENTATION) Slog.v(TAG, 1239 "Orientation continue waiting for draw in " + w); 1240 } else { 1241 w.mOrientationChanging = false; 1242 if (DEBUG_ORIENTATION) Slog.v(TAG, "Orientation change complete in " + w); 1243 } 1244 } 1245 w.mToken.hasVisible = true; 1246 } 1247 } 1248 1249 void setTransparentRegionHint(final Region region) { 1250 if (mSurface == null) { 1251 Slog.w(TAG, "setTransparentRegionHint: null mSurface after mHasSurface true"); 1252 return; 1253 } 1254 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 1255 ">>> OPEN TRANSACTION setTransparentRegion"); 1256 Surface.openTransaction(); 1257 try { 1258 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, 1259 "transparentRegionHint=" + region, null); 1260 mSurface.setTransparentRegionHint(region); 1261 } finally { 1262 Surface.closeTransaction(); 1263 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 1264 "<<< CLOSE TRANSACTION setTransparentRegion"); 1265 } 1266 } 1267 1268 void setWallpaperOffset(int left, int top) { 1269 mSurfaceX = left; 1270 mSurfaceY = top; 1271 if (mAnimating) { 1272 // If this window (or its app token) is animating, then the position 1273 // of the surface will be re-computed on the next animation frame. 1274 // We can't poke it directly here because it depends on whatever 1275 // transformation is being applied by the animation. 1276 return; 1277 } 1278 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 1279 ">>> OPEN TRANSACTION setWallpaperOffset"); 1280 Surface.openTransaction(); 1281 try { 1282 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, 1283 "POS " + left + ", " + top, null); 1284 mSurface.setPosition(mWin.mFrame.left + left, mWin.mFrame.top + top); 1285 updateSurfaceWindowCrop(false); 1286 } catch (RuntimeException e) { 1287 Slog.w(TAG, "Error positioning surface of " + mWin 1288 + " pos=(" + left + "," + top + ")", e); 1289 } finally { 1290 Surface.closeTransaction(); 1291 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, 1292 "<<< CLOSE TRANSACTION setWallpaperOffset"); 1293 } 1294 } 1295 1296 // This must be called while inside a transaction. 1297 boolean performShowLocked() { 1298 if (mWin.isOtherUsersAppWindow()) { 1299 Slog.w(TAG, "Current user " + mService.mCurrentUserId + " trying to display " 1300 + this + ", type " + mWin.mAttrs.type + ", belonging to " + mWin.mOwnerUid); 1301 return false; 1302 } 1303 if (DEBUG_VISIBILITY || (DEBUG_STARTING_WINDOW && 1304 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING)) { 1305 RuntimeException e = null; 1306 if (!WindowManagerService.HIDE_STACK_CRAWLS) { 1307 e = new RuntimeException(); 1308 e.fillInStackTrace(); 1309 } 1310 Slog.v(TAG, "performShow on " + this 1311 + ": mDrawState=" + mDrawState + " readyForDisplay=" 1312 + mWin.isReadyForDisplayIgnoringKeyguard() 1313 + " starting=" + (mWin.mAttrs.type == TYPE_APPLICATION_STARTING) 1314 + " during animation: policyVis=" + mWin.mPolicyVisibility 1315 + " attHidden=" + mWin.mAttachedHidden 1316 + " tok.hiddenRequested=" 1317 + (mWin.mAppToken != null ? mWin.mAppToken.hiddenRequested : false) 1318 + " tok.hidden=" 1319 + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false) 1320 + " animating=" + mAnimating 1321 + " tok animating=" 1322 + (mAppAnimator != null ? mAppAnimator.animating : false), e); 1323 } 1324 if (mDrawState == READY_TO_SHOW && mWin.isReadyForDisplayIgnoringKeyguard()) { 1325 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) 1326 WindowManagerService.logSurface(mWin, "SHOW (performShowLocked)", null); 1327 if (DEBUG_VISIBILITY || (DEBUG_STARTING_WINDOW && 1328 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING)) { 1329 Slog.v(TAG, "Showing " + this 1330 + " during animation: policyVis=" + mWin.mPolicyVisibility 1331 + " attHidden=" + mWin.mAttachedHidden 1332 + " tok.hiddenRequested=" 1333 + (mWin.mAppToken != null ? mWin.mAppToken.hiddenRequested : false) 1334 + " tok.hidden=" 1335 + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false) 1336 + " animating=" + mAnimating 1337 + " tok animating=" 1338 + (mAppAnimator != null ? mAppAnimator.animating : false)); 1339 } 1340 1341 mService.enableScreenIfNeededLocked(); 1342 1343 applyEnterAnimationLocked(); 1344 1345 // Force the show in the next prepareSurfaceLocked() call. 1346 mLastAlpha = -1; 1347 if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) 1348 Slog.v(TAG, "performShowLocked: mDrawState=HAS_DRAWN in " + this); 1349 mDrawState = HAS_DRAWN; 1350 mService.updateLayoutToAnimationLocked(); 1351 1352 int i = mWin.mChildWindows.size(); 1353 while (i > 0) { 1354 i--; 1355 WindowState c = mWin.mChildWindows.get(i); 1356 if (c.mAttachedHidden) { 1357 c.mAttachedHidden = false; 1358 if (c.mWinAnimator.mSurface != null) { 1359 c.mWinAnimator.performShowLocked(); 1360 // It hadn't been shown, which means layout not 1361 // performed on it, so now we want to make sure to 1362 // do a layout. If called from within the transaction 1363 // loop, this will cause it to restart with a new 1364 // layout. 1365 mService.mLayoutNeeded = true; 1366 } 1367 } 1368 } 1369 1370 if (mWin.mAttrs.type != TYPE_APPLICATION_STARTING 1371 && mWin.mAppToken != null) { 1372 mWin.mAppToken.firstWindowDrawn = true; 1373 1374 if (mWin.mAppToken.startingData != null) { 1375 if (WindowManagerService.DEBUG_STARTING_WINDOW || 1376 WindowManagerService.DEBUG_ANIM) Slog.v(TAG, 1377 "Finish starting " + mWin.mToken 1378 + ": first real window is shown, no animation"); 1379 // If this initial window is animating, stop it -- we 1380 // will do an animation to reveal it from behind the 1381 // starting window, so there is no need for it to also 1382 // be doing its own stuff. 1383 clearAnimation(); 1384 mService.mFinishedStarting.add(mWin.mAppToken); 1385 mService.mH.sendEmptyMessage(H.FINISHED_STARTING); 1386 } 1387 mWin.mAppToken.updateReportedVisibilityLocked(); 1388 } 1389 1390 return true; 1391 } 1392 1393 return false; 1394 } 1395 1396 /** 1397 * Have the surface flinger show a surface, robustly dealing with 1398 * error conditions. In particular, if there is not enough memory 1399 * to show the surface, then we will try to get rid of other surfaces 1400 * in order to succeed. 1401 * 1402 * @return Returns true if the surface was successfully shown. 1403 */ 1404 boolean showSurfaceRobustlyLocked() { 1405 try { 1406 if (mSurface != null) { 1407 mSurfaceShown = true; 1408 mSurface.show(); 1409 if (mWin.mTurnOnScreen) { 1410 if (DEBUG_VISIBILITY) Slog.v(TAG, 1411 "Show surface turning screen on: " + mWin); 1412 mWin.mTurnOnScreen = false; 1413 mAnimator.mBulkUpdateParams |= SET_TURN_ON_SCREEN; 1414 } 1415 } 1416 return true; 1417 } catch (RuntimeException e) { 1418 Slog.w(TAG, "Failure showing surface " + mSurface + " in " + mWin, e); 1419 } 1420 1421 mService.reclaimSomeSurfaceMemoryLocked(this, "show", true); 1422 1423 return false; 1424 } 1425 1426 void applyEnterAnimationLocked() { 1427 final int transit; 1428 if (mEnterAnimationPending) { 1429 mEnterAnimationPending = false; 1430 transit = WindowManagerPolicy.TRANSIT_ENTER; 1431 } else { 1432 transit = WindowManagerPolicy.TRANSIT_SHOW; 1433 } 1434 1435 applyAnimationLocked(transit, true); 1436 } 1437 1438 // TODO(cmautner): Move back to WindowState? 1439 /** 1440 * Choose the correct animation and set it to the passed WindowState. 1441 * @param transit If WindowManagerPolicy.TRANSIT_PREVIEW_DONE and the app window has been drawn 1442 * then the animation will be app_starting_exit. Any other value loads the animation from 1443 * the switch statement below. 1444 * @param isEntrance The animation type the last time this was called. Used to keep from 1445 * loading the same animation twice. 1446 * @return true if an animation has been loaded. 1447 */ 1448 boolean applyAnimationLocked(int transit, boolean isEntrance) { 1449 if (mLocalAnimating && mAnimationIsEntrance == isEntrance) { 1450 // If we are trying to apply an animation, but already running 1451 // an animation of the same type, then just leave that one alone. 1452 return true; 1453 } 1454 1455 // Only apply an animation if the display isn't frozen. If it is 1456 // frozen, there is no reason to animate and it can cause strange 1457 // artifacts when we unfreeze the display if some different animation 1458 // is running. 1459 if (mService.okToDisplay()) { 1460 int anim = mPolicy.selectAnimationLw(mWin, transit); 1461 int attr = -1; 1462 Animation a = null; 1463 if (anim != 0) { 1464 a = AnimationUtils.loadAnimation(mContext, anim); 1465 } else { 1466 switch (transit) { 1467 case WindowManagerPolicy.TRANSIT_ENTER: 1468 attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation; 1469 break; 1470 case WindowManagerPolicy.TRANSIT_EXIT: 1471 attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation; 1472 break; 1473 case WindowManagerPolicy.TRANSIT_SHOW: 1474 attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation; 1475 break; 1476 case WindowManagerPolicy.TRANSIT_HIDE: 1477 attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation; 1478 break; 1479 } 1480 if (attr >= 0) { 1481 a = mService.loadAnimation(mWin.mAttrs, attr); 1482 } 1483 } 1484 if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG, 1485 "applyAnimation: win=" + this 1486 + " anim=" + anim + " attr=0x" + Integer.toHexString(attr) 1487 + " a=" + a 1488 + " mAnimation=" + mAnimation 1489 + " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3)); 1490 if (a != null) { 1491 if (WindowManagerService.DEBUG_ANIM) { 1492 RuntimeException e = null; 1493 if (!WindowManagerService.HIDE_STACK_CRAWLS) { 1494 e = new RuntimeException(); 1495 e.fillInStackTrace(); 1496 } 1497 Slog.v(TAG, "Loaded animation " + a + " for " + this, e); 1498 } 1499 setAnimation(a); 1500 mAnimationIsEntrance = isEntrance; 1501 } 1502 } else { 1503 clearAnimation(); 1504 } 1505 1506 return mAnimation != null; 1507 } 1508 1509 public void dump(PrintWriter pw, String prefix, boolean dumpAll) { 1510 if (mAnimating || mLocalAnimating || mAnimationIsEntrance 1511 || mAnimation != null) { 1512 pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating); 1513 pw.print(" mLocalAnimating="); pw.print(mLocalAnimating); 1514 pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance); 1515 pw.print(" mAnimation="); pw.println(mAnimation); 1516 } 1517 if (mHasTransformation || mHasLocalTransformation) { 1518 pw.print(prefix); pw.print("XForm: has="); 1519 pw.print(mHasTransformation); 1520 pw.print(" hasLocal="); pw.print(mHasLocalTransformation); 1521 pw.print(" "); mTransformation.printShortString(pw); 1522 pw.println(); 1523 } 1524 if (mSurface != null) { 1525 if (dumpAll) { 1526 pw.print(prefix); pw.print("mSurface="); pw.println(mSurface); 1527 pw.print(prefix); pw.print("mDrawState="); 1528 pw.print(drawStateToString(mDrawState)); 1529 pw.print(" mLastHidden="); pw.println(mLastHidden); 1530 } 1531 pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown); 1532 pw.print(" layer="); pw.print(mSurfaceLayer); 1533 pw.print(" alpha="); pw.print(mSurfaceAlpha); 1534 pw.print(" rect=("); pw.print(mSurfaceX); 1535 pw.print(","); pw.print(mSurfaceY); 1536 pw.print(") "); pw.print(mSurfaceW); 1537 pw.print(" x "); pw.println(mSurfaceH); 1538 } 1539 if (mPendingDestroySurface != null) { 1540 pw.print(prefix); pw.print("mPendingDestroySurface="); 1541 pw.println(mPendingDestroySurface); 1542 } 1543 if (mSurfaceResized || mSurfaceDestroyDeferred) { 1544 pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized); 1545 pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred); 1546 } 1547 if (mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND) { 1548 pw.print(prefix); pw.print("mUniverseTransform="); 1549 mUniverseTransform.printShortString(pw); 1550 pw.println(); 1551 } 1552 if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) { 1553 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha); 1554 pw.print(" mAlpha="); pw.print(mAlpha); 1555 pw.print(" mLastAlpha="); pw.println(mLastAlpha); 1556 } 1557 if (mHaveMatrix || mWin.mGlobalScale != 1) { 1558 pw.print(prefix); pw.print("mGlobalScale="); pw.print(mWin.mGlobalScale); 1559 pw.print(" mDsDx="); pw.print(mDsDx); 1560 pw.print(" mDtDx="); pw.print(mDtDx); 1561 pw.print(" mDsDy="); pw.print(mDsDy); 1562 pw.print(" mDtDy="); pw.println(mDtDy); 1563 } 1564 } 1565 1566 @Override 1567 public String toString() { 1568 StringBuffer sb = new StringBuffer("WindowStateAnimator ("); 1569 sb.append(mWin.mLastTitle + "): "); 1570 sb.append("mSurface " + mSurface); 1571 sb.append(", mAnimation " + mAnimation); 1572 return sb.toString(); 1573 } 1574} 1575