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