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