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