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