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