AppWindowAnimator.java revision bec53f7066852c1c5877c51fcd8c55840891d866
1// Copyright 2012 Google Inc. All Rights Reserved. 2 3package com.android.server.wm; 4 5import android.graphics.Matrix; 6import android.util.Slog; 7import android.view.Surface; 8import android.view.WindowManagerPolicy; 9import android.view.animation.Animation; 10import android.view.animation.Transformation; 11 12import java.io.PrintWriter; 13 14/** 15 * 16 */ 17public class AppWindowAnimator { 18 19 final AppWindowToken mAppToken; 20 final WindowManagerService mService; 21 final WindowAnimator mAnimator; 22 23 boolean animating; 24 Animation animation; 25 boolean animInitialized; 26 boolean hasTransformation; 27 final Transformation transformation = new Transformation(); 28 29 // Have we been asked to have this token keep the screen frozen? 30 // Protect with mAnimator. 31 boolean freezingScreen; 32 33 // Offset to the window of all layers in the token, for use by 34 // AppWindowToken animations. 35 int animLayerAdjustment; 36 37 // Special surface for thumbnail animation. 38 Surface thumbnail; 39 int thumbnailTransactionSeq; 40 int thumbnailX; 41 int thumbnailY; 42 int thumbnailLayer; 43 Animation thumbnailAnimation; 44 final Transformation thumbnailTransformation = new Transformation(); 45 46 public AppWindowAnimator(final WindowManagerService service, final AppWindowToken atoken) { 47 mService = service; 48 mAppToken = atoken; 49 mAnimator = service.mAnimator; 50 } 51 52 public void setAnimation(Animation anim, boolean initialized) { 53 if (WindowManagerService.localLOGV) Slog.v( 54 WindowManagerService.TAG, "Setting animation in " + this + ": " + anim); 55 animation = anim; 56 animating = false; 57 animInitialized = initialized; 58 anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION); 59 anim.scaleCurrentDuration(mService.mTransitionAnimationScale); 60 int zorder = anim.getZAdjustment(); 61 int adj = 0; 62 if (zorder == Animation.ZORDER_TOP) { 63 adj = WindowManagerService.TYPE_LAYER_OFFSET; 64 } else if (zorder == Animation.ZORDER_BOTTOM) { 65 adj = -WindowManagerService.TYPE_LAYER_OFFSET; 66 } 67 68 if (animLayerAdjustment != adj) { 69 animLayerAdjustment = adj; 70 updateLayers(); 71 } 72 // Start out animation gone if window is gone, or visible if window is visible. 73 transformation.clear(); 74 transformation.setAlpha(mAppToken.reportedVisible ? 1 : 0); 75 hasTransformation = true; 76 } 77 78 public void setDummyAnimation() { 79 if (animation == null) { 80 if (WindowManagerService.localLOGV) Slog.v( 81 WindowManagerService.TAG, "Setting dummy animation in " + this); 82 animation = WindowManagerService.sDummyAnimation; 83 animInitialized = false; 84 } 85 } 86 87 public void clearAnimation() { 88 if (animation != null) { 89 animation = null; 90 animating = true; 91 animInitialized = false; 92 } 93 clearThumbnail(); 94 } 95 96 public void clearThumbnail() { 97 if (thumbnail != null) { 98 thumbnail.destroy(); 99 thumbnail = null; 100 } 101 } 102 103 void updateLayers() { 104 final int N = mAppToken.allAppWindows.size(); 105 final int adj = animLayerAdjustment; 106 thumbnailLayer = -1; 107 for (int i=0; i<N; i++) { 108 final WindowState w = mAppToken.allAppWindows.get(i); 109 final WindowStateAnimator winAnimator = w.mWinAnimator; 110 winAnimator.mAnimLayer = w.mLayer + adj; 111 if (winAnimator.mAnimLayer > thumbnailLayer) { 112 thumbnailLayer = winAnimator.mAnimLayer; 113 } 114 if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Updating layer " + w + ": " 115 + winAnimator.mAnimLayer); 116 if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) { 117 mService.setInputMethodAnimLayerAdjustment(adj); 118 } 119 if (w == mService.mWallpaperTarget && mService.mLowerWallpaperTarget == null) { 120 mService.setWallpaperAnimLayerAdjustmentLocked(adj); 121 } 122 } 123 } 124 125 private void stepThumbnailAnimation(long currentTime) { 126 thumbnailTransformation.clear(); 127 thumbnailAnimation.getTransformation(currentTime, thumbnailTransformation); 128 thumbnailTransformation.getMatrix().preTranslate(thumbnailX, thumbnailY); 129 final boolean screenAnimation = mAnimator.mScreenRotationAnimation != null 130 && mAnimator.mScreenRotationAnimation.isAnimating(); 131 if (screenAnimation) { 132 thumbnailTransformation.postCompose( 133 mAnimator.mScreenRotationAnimation.getEnterTransformation()); 134 } 135 // cache often used attributes locally 136 final float tmpFloats[] = mService.mTmpFloats; 137 thumbnailTransformation.getMatrix().getValues(tmpFloats); 138 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, 139 "thumbnail", "POS " + tmpFloats[Matrix.MTRANS_X] 140 + ", " + tmpFloats[Matrix.MTRANS_Y], null); 141 thumbnail.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]); 142 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, 143 "thumbnail", "alpha=" + thumbnailTransformation.getAlpha() 144 + " layer=" + thumbnailLayer 145 + " matrix=[" + tmpFloats[Matrix.MSCALE_X] 146 + "," + tmpFloats[Matrix.MSKEW_Y] 147 + "][" + tmpFloats[Matrix.MSKEW_X] 148 + "," + tmpFloats[Matrix.MSCALE_Y] + "]", null); 149 thumbnail.setAlpha(thumbnailTransformation.getAlpha()); 150 // The thumbnail is layered below the window immediately above this 151 // token's anim layer. 152 thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER 153 - WindowManagerService.LAYER_OFFSET_THUMBNAIL); 154 thumbnail.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y], 155 tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]); 156 } 157 158 private boolean stepAnimation(long currentTime) { 159 if (animation == null) { 160 return false; 161 } 162 transformation.clear(); 163 final boolean more = animation.getTransformation(currentTime, transformation); 164 if (WindowManagerService.DEBUG_ANIM) Slog.v( 165 WindowManagerService.TAG, "Stepped animation in " + this + 166 ": more=" + more + ", xform=" + transformation); 167 if (!more) { 168 animation = null; 169 clearThumbnail(); 170 if (WindowManagerService.DEBUG_ANIM) Slog.v( 171 WindowManagerService.TAG, "Finished animation in " + this + 172 " @ " + currentTime); 173 } 174 hasTransformation = more; 175 return more; 176 } 177 178 // This must be called while inside a transaction. 179 boolean stepAnimationLocked(long currentTime, int dw, int dh) { 180 if (mService.okToDisplay()) { 181 // We will run animations as long as the display isn't frozen. 182 183 if (animation == WindowManagerService.sDummyAnimation) { 184 // This guy is going to animate, but not yet. For now count 185 // it as not animating for purposes of scheduling transactions; 186 // when it is really time to animate, this will be set to 187 // a real animation and the next call will execute normally. 188 return false; 189 } 190 191 if ((mAppToken.allDrawn || animating || mAppToken.startingDisplayed) 192 && animation != null) { 193 if (!animating) { 194 if (WindowManagerService.DEBUG_ANIM) Slog.v( 195 WindowManagerService.TAG, "Starting animation in " + this + 196 " @ " + currentTime + ": dw=" + dw + " dh=" + dh 197 + " scale=" + mService.mTransitionAnimationScale 198 + " allDrawn=" + mAppToken.allDrawn + " animating=" + animating); 199 if (!animInitialized) { 200 animation.initialize(dw, dh, dw, dh); 201 } 202 animation.setStartTime(currentTime); 203 animating = true; 204 if (thumbnail != null) { 205 thumbnail.show(); 206 thumbnailAnimation.setStartTime(currentTime); 207 } 208 } 209 if (stepAnimation(currentTime)) { 210 // animation isn't over, step any thumbnail and that's 211 // it for now. 212 if (thumbnail != null) { 213 stepThumbnailAnimation(currentTime); 214 } 215 return true; 216 } 217 } 218 } else if (animation != null) { 219 // If the display is frozen, and there is a pending animation, 220 // clear it and make sure we run the cleanup code. 221 animating = true; 222 animation = null; 223 } 224 225 hasTransformation = false; 226 227 if (!animating) { 228 return false; 229 } 230 231 mAnimator.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; 232 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { 233 mService.debugLayoutRepeats("AppWindowToken", mAnimator.mPendingLayoutChanges); 234 } 235 236 clearAnimation(); 237 animating = false; 238 if (animLayerAdjustment != 0) { 239 animLayerAdjustment = 0; 240 updateLayers(); 241 } 242 if (mService.mInputMethodTarget != null 243 && mService.mInputMethodTarget.mAppToken == mAppToken) { 244 mService.moveInputMethodWindowsIfNeededLocked(true); 245 } 246 247 if (WindowManagerService.DEBUG_ANIM) Slog.v( 248 WindowManagerService.TAG, "Animation done in " + this 249 + ": reportedVisible=" + mAppToken.reportedVisible); 250 251 transformation.clear(); 252 253 final int N = mAppToken.windows.size(); 254 for (int i=0; i<N; i++) { 255 mAppToken.windows.get(i).mWinAnimator.finishExit(); 256 } 257 mAppToken.updateReportedVisibilityLocked(); 258 259 return false; 260 } 261 262 boolean showAllWindowsLocked() { 263 boolean isAnimating = false; 264 final int NW = mAppToken.allAppWindows.size(); 265 for (int i=0; i<NW; i++) { 266 WindowStateAnimator winAnimator = mAppToken.allAppWindows.get(i).mWinAnimator; 267 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, 268 "performing show on: " + winAnimator); 269 winAnimator.performShowLocked(); 270 isAnimating |= winAnimator.isAnimating(); 271 } 272 return isAnimating; 273 } 274 275 void dump(PrintWriter pw, String prefix) { 276 if (freezingScreen) { 277 pw.print(prefix); pw.print(" freezingScreen="); pw.println(freezingScreen); 278 } 279 if (animating || animation != null) { 280 pw.print(prefix); pw.print("animating="); pw.print(animating); 281 pw.print(" animation="); pw.println(animation); 282 } 283 if (hasTransformation) { 284 pw.print(prefix); pw.print("XForm: "); 285 transformation.printShortString(pw); 286 pw.println(); 287 } 288 if (animLayerAdjustment != 0) { 289 pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment); 290 } 291 if (thumbnail != null) { 292 pw.print(prefix); pw.print("thumbnail="); pw.print(thumbnail); 293 pw.print(" x="); pw.print(thumbnailX); 294 pw.print(" y="); pw.print(thumbnailY); 295 pw.print(" layer="); pw.println(thumbnailLayer); 296 pw.print(prefix); pw.print("thumbnailAnimation="); pw.println(thumbnailAnimation); 297 pw.print(prefix); pw.print("thumbnailTransformation="); 298 pw.println(thumbnailTransformation.toShortString()); 299 } 300 } 301} 302