AppWindowAnimator.java revision eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3a
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2014 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server.wm; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport android.graphics.Matrix; 209ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport android.util.Slog; 219ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport android.util.TimeUtils; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Display; 239ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport android.view.SurfaceControl; 249ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport android.view.WindowManagerPolicy; 259ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport android.view.animation.Animation; 269ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport android.view.animation.Transformation; 279ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkey 289ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport java.io.PrintWriter; 299ecfee03fa188aebfbd9778b4e020323903495eeJeff Sharkeyimport java.util.ArrayList; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class AppWindowAnimator { 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final String TAG = "AppWindowAnimator"; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final AppWindowToken mAppToken; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final WindowManagerService mService; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final WindowAnimator mAnimator; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean animating; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Animation animation; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean hasTransformation; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Transformation transformation = new Transformation(); 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Have we been asked to have this token keep the screen frozen? 44 // Protect with mAnimator. 45 boolean freezingScreen; 46 47 /** 48 * How long we last kept the screen frozen. 49 */ 50 int lastFreezeDuration; 51 52 // Offset to the window of all layers in the token, for use by 53 // AppWindowToken animations. 54 int animLayerAdjustment; 55 56 // Propagated from AppWindowToken.allDrawn, to determine when 57 // the state changes. 58 boolean allDrawn; 59 60 // Special surface for thumbnail animation. 61 SurfaceControl thumbnail; 62 int thumbnailTransactionSeq; 63 int thumbnailX; 64 int thumbnailY; 65 int thumbnailLayer; 66 Animation thumbnailAnimation; 67 final Transformation thumbnailTransformation = new Transformation(); 68 69 /** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */ 70 ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<WindowStateAnimator>(); 71 72 static final Animation sDummyAnimation = new DummyAnimation(); 73 74 public AppWindowAnimator(final AppWindowToken atoken) { 75 mAppToken = atoken; 76 mService = atoken.service; 77 mAnimator = atoken.mAnimator; 78 } 79 80 public void setAnimation(Animation anim, int width, int height) { 81 if (WindowManagerService.localLOGV) Slog.v(TAG, "Setting animation in " + mAppToken 82 + ": " + anim + " wxh=" + width + "x" + height 83 + " isVisible=" + mAppToken.isVisible()); 84 animation = anim; 85 animating = false; 86 if (!anim.isInitialized()) { 87 anim.initialize(width, height, width, height); 88 } 89 anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION); 90 anim.scaleCurrentDuration(mService.getTransitionAnimationScaleLocked()); 91 int zorder = anim.getZAdjustment(); 92 int adj = 0; 93 if (zorder == Animation.ZORDER_TOP) { 94 adj = WindowManagerService.TYPE_LAYER_OFFSET; 95 } else if (zorder == Animation.ZORDER_BOTTOM) { 96 adj = -WindowManagerService.TYPE_LAYER_OFFSET; 97 } 98 99 if (animLayerAdjustment != adj) { 100 animLayerAdjustment = adj; 101 updateLayers(); 102 } 103 // Start out animation gone if window is gone, or visible if window is visible. 104 transformation.clear(); 105 transformation.setAlpha(mAppToken.isVisible() ? 1 : 0); 106 hasTransformation = true; 107 } 108 109 public void setDummyAnimation() { 110 if (WindowManagerService.localLOGV) Slog.v(TAG, "Setting dummy animation in " + mAppToken 111 + " isVisible=" + mAppToken.isVisible()); 112 animation = sDummyAnimation; 113 hasTransformation = true; 114 transformation.clear(); 115 transformation.setAlpha(mAppToken.isVisible() ? 1 : 0); 116 } 117 118 public void clearAnimation() { 119 if (animation != null) { 120 animation = null; 121 animating = true; 122 } 123 clearThumbnail(); 124 if (mAppToken.deferClearAllDrawn) { 125 mAppToken.allDrawn = false; 126 mAppToken.deferClearAllDrawn = false; 127 } 128 } 129 130 public void clearThumbnail() { 131 if (thumbnail != null) { 132 thumbnail.destroy(); 133 thumbnail = null; 134 } 135 } 136 137 void updateLayers() { 138 final int N = mAppToken.allAppWindows.size(); 139 final int adj = animLayerAdjustment; 140 thumbnailLayer = -1; 141 for (int i=0; i<N; i++) { 142 final WindowState w = mAppToken.allAppWindows.get(i); 143 final WindowStateAnimator winAnimator = w.mWinAnimator; 144 winAnimator.mAnimLayer = w.mLayer + adj; 145 if (winAnimator.mAnimLayer > thumbnailLayer) { 146 thumbnailLayer = winAnimator.mAnimLayer; 147 } 148 if (WindowManagerService.DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": " 149 + winAnimator.mAnimLayer); 150 if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) { 151 mService.setInputMethodAnimLayerAdjustment(adj); 152 } 153 if (w == mService.mWallpaperTarget && mService.mLowerWallpaperTarget == null) { 154 mService.setWallpaperAnimLayerAdjustmentLocked(adj); 155 } 156 } 157 } 158 159 private void stepThumbnailAnimation(long currentTime) { 160 thumbnailTransformation.clear(); 161 thumbnailAnimation.getTransformation(currentTime, thumbnailTransformation); 162 thumbnailTransformation.getMatrix().preTranslate(thumbnailX, thumbnailY); 163 164 ScreenRotationAnimation screenRotationAnimation = 165 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); 166 final boolean screenAnimation = screenRotationAnimation != null 167 && screenRotationAnimation.isAnimating(); 168 if (screenAnimation) { 169 thumbnailTransformation.postCompose(screenRotationAnimation.getEnterTransformation()); 170 } 171 // cache often used attributes locally 172 final float tmpFloats[] = mService.mTmpFloats; 173 thumbnailTransformation.getMatrix().getValues(tmpFloats); 174 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, 175 "thumbnail", "POS " + tmpFloats[Matrix.MTRANS_X] 176 + ", " + tmpFloats[Matrix.MTRANS_Y], null); 177 thumbnail.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]); 178 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, 179 "thumbnail", "alpha=" + thumbnailTransformation.getAlpha() 180 + " layer=" + thumbnailLayer 181 + " matrix=[" + tmpFloats[Matrix.MSCALE_X] 182 + "," + tmpFloats[Matrix.MSKEW_Y] 183 + "][" + tmpFloats[Matrix.MSKEW_X] 184 + "," + tmpFloats[Matrix.MSCALE_Y] + "]", null); 185 thumbnail.setAlpha(thumbnailTransformation.getAlpha()); 186 // The thumbnail is layered below the window immediately above this 187 // token's anim layer. 188 thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER 189 - WindowManagerService.LAYER_OFFSET_THUMBNAIL); 190 thumbnail.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y], 191 tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]); 192 } 193 194 private boolean stepAnimation(long currentTime) { 195 if (animation == null) { 196 return false; 197 } 198 transformation.clear(); 199 final boolean more = animation.getTransformation(currentTime, transformation); 200 if (false && WindowManagerService.DEBUG_ANIM) Slog.v( 201 TAG, "Stepped animation in " + mAppToken + ": more=" + more + ", xform=" + transformation); 202 if (!more) { 203 animation = null; 204 clearThumbnail(); 205 if (WindowManagerService.DEBUG_ANIM) Slog.v( 206 TAG, "Finished animation in " + mAppToken + " @ " + currentTime); 207 } 208 hasTransformation = more; 209 return more; 210 } 211 212 // This must be called while inside a transaction. 213 boolean stepAnimationLocked(long currentTime) { 214 if (mService.okToDisplay()) { 215 // We will run animations as long as the display isn't frozen. 216 217 if (animation == sDummyAnimation) { 218 // This guy is going to animate, but not yet. For now count 219 // it as not animating for purposes of scheduling transactions; 220 // when it is really time to animate, this will be set to 221 // a real animation and the next call will execute normally. 222 return false; 223 } 224 225 if ((mAppToken.allDrawn || animating || mAppToken.startingDisplayed) 226 && animation != null) { 227 if (!animating) { 228 if (WindowManagerService.DEBUG_ANIM) Slog.v( 229 TAG, "Starting animation in " + mAppToken + 230 " @ " + currentTime + " scale=" 231 + mService.getTransitionAnimationScaleLocked() 232 + " allDrawn=" + mAppToken.allDrawn + " animating=" + animating); 233 animation.setStartTime(currentTime); 234 animating = true; 235 if (thumbnail != null) { 236 thumbnail.show(); 237 thumbnailAnimation.setStartTime(currentTime); 238 } 239 } 240 if (stepAnimation(currentTime)) { 241 // animation isn't over, step any thumbnail and that's 242 // it for now. 243 if (thumbnail != null) { 244 stepThumbnailAnimation(currentTime); 245 } 246 return true; 247 } 248 } 249 } else if (animation != null) { 250 // If the display is frozen, and there is a pending animation, 251 // clear it and make sure we run the cleanup code. 252 animating = true; 253 animation = null; 254 } 255 256 hasTransformation = false; 257 258 if (!animating && animation == null) { 259 return false; 260 } 261 262 mAnimator.setAppLayoutChanges(this, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM, 263 "AppWindowToken"); 264 265 clearAnimation(); 266 animating = false; 267 if (animLayerAdjustment != 0) { 268 animLayerAdjustment = 0; 269 updateLayers(); 270 } 271 if (mService.mInputMethodTarget != null 272 && mService.mInputMethodTarget.mAppToken == mAppToken) { 273 mService.moveInputMethodWindowsIfNeededLocked(true); 274 } 275 276 if (WindowManagerService.DEBUG_ANIM) Slog.v( 277 TAG, "Animation done in " + mAppToken 278 + ": reportedVisible=" + mAppToken.reportedVisible); 279 280 transformation.clear(); 281 282 final int N = mAllAppWinAnimators.size(); 283 for (int i=0; i<N; i++) { 284 mAllAppWinAnimators.get(i).finishExit(); 285 } 286 mAppToken.updateReportedVisibilityLocked(); 287 288 return false; 289 } 290 291 boolean showAllWindowsLocked() { 292 boolean isAnimating = false; 293 final int NW = mAllAppWinAnimators.size(); 294 for (int i=0; i<NW; i++) { 295 WindowStateAnimator winAnimator = mAllAppWinAnimators.get(i); 296 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, 297 "performing show on: " + winAnimator); 298 winAnimator.performShowLocked(); 299 isAnimating |= winAnimator.isAnimating(); 300 } 301 return isAnimating; 302 } 303 304 void dump(PrintWriter pw, String prefix, boolean dumpAll) { 305 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken); 306 pw.print(prefix); pw.print("mAnimator="); pw.println(mAnimator); 307 pw.print(prefix); pw.print("freezingScreen="); pw.print(freezingScreen); 308 pw.print(" allDrawn="); pw.print(allDrawn); 309 pw.print(" animLayerAdjustment="); pw.println(animLayerAdjustment); 310 if (lastFreezeDuration != 0) { 311 pw.print(prefix); pw.print("lastFreezeDuration="); 312 TimeUtils.formatDuration(lastFreezeDuration, pw); pw.println(); 313 } 314 if (animating || animation != null) { 315 pw.print(prefix); pw.print("animating="); pw.println(animating); 316 pw.print(prefix); pw.print("animation="); pw.println(animation); 317 } 318 if (hasTransformation) { 319 pw.print(prefix); pw.print("XForm: "); 320 transformation.printShortString(pw); 321 pw.println(); 322 } 323 if (thumbnail != null) { 324 pw.print(prefix); pw.print("thumbnail="); pw.print(thumbnail); 325 pw.print(" x="); pw.print(thumbnailX); 326 pw.print(" y="); pw.print(thumbnailY); 327 pw.print(" layer="); pw.println(thumbnailLayer); 328 pw.print(prefix); pw.print("thumbnailAnimation="); pw.println(thumbnailAnimation); 329 pw.print(prefix); pw.print("thumbnailTransformation="); 330 pw.println(thumbnailTransformation.toShortString()); 331 } 332 for (int i=0; i<mAllAppWinAnimators.size(); i++) { 333 WindowStateAnimator wanim = mAllAppWinAnimators.get(i); 334 pw.print(prefix); pw.print("App Win Anim #"); pw.print(i); 335 pw.print(": "); pw.println(wanim); 336 } 337 } 338 339 // This is an animation that does nothing: it just immediately finishes 340 // itself every time it is called. It is used as a stub animation in cases 341 // where we want to synchronize multiple things that may be animating. 342 static final class DummyAnimation extends Animation { 343 @Override 344 public boolean getTransformation(long currentTime, Transformation outTransformation) { 345 return false; 346 } 347 } 348 349} 350