blob: 6293dc647df148922d8f1bf3376101297f05be4d [file] [log] [blame]
Craig Mautner59431632012-04-04 11:56:44 -07001// Copyright 2012 Google Inc. All Rights Reserved.
2
3package com.android.server.wm;
4
5import android.graphics.Matrix;
6import android.util.Slog;
Dianne Hackborna57c6952013-03-29 14:46:40 -07007import android.util.TimeUtils;
Craig Mautnera91f9e22012-09-14 16:22:08 -07008import android.view.Display;
Craig Mautner59431632012-04-04 11:56:44 -07009import android.view.Surface;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080010import android.view.SurfaceControl;
Craig Mautner59431632012-04-04 11:56:44 -070011import android.view.WindowManagerPolicy;
12import android.view.animation.Animation;
13import android.view.animation.Transformation;
14
15import java.io.PrintWriter;
Craig Mautner322e4032012-07-13 13:35:20 -070016import java.util.ArrayList;
Craig Mautner59431632012-04-04 11:56:44 -070017
Craig Mautner59431632012-04-04 11:56:44 -070018public class AppWindowAnimator {
Craig Mautnerfbf378c2012-04-23 17:24:21 -070019 static final String TAG = "AppWindowAnimator";
Craig Mautner59431632012-04-04 11:56:44 -070020
21 final AppWindowToken mAppToken;
22 final WindowManagerService mService;
23 final WindowAnimator mAnimator;
24
25 boolean animating;
26 Animation animation;
Craig Mautner59431632012-04-04 11:56:44 -070027 boolean hasTransformation;
28 final Transformation transformation = new Transformation();
29
30 // Have we been asked to have this token keep the screen frozen?
31 // Protect with mAnimator.
32 boolean freezingScreen;
33
Dianne Hackborna57c6952013-03-29 14:46:40 -070034 /**
35 * How long we last kept the screen frozen.
36 */
37 int lastFreezeDuration;
38
Craig Mautner59431632012-04-04 11:56:44 -070039 // Offset to the window of all layers in the token, for use by
40 // AppWindowToken animations.
41 int animLayerAdjustment;
42
Craig Mautner6fbda632012-07-03 09:26:39 -070043 // Propagated from AppWindowToken.allDrawn, to determine when
44 // the state changes.
45 boolean allDrawn;
46
Craig Mautner59431632012-04-04 11:56:44 -070047 // Special surface for thumbnail animation.
Mathias Agopian3866f0d2013-02-11 22:08:48 -080048 SurfaceControl thumbnail;
Craig Mautner59431632012-04-04 11:56:44 -070049 int thumbnailTransactionSeq;
50 int thumbnailX;
51 int thumbnailY;
52 int thumbnailLayer;
53 Animation thumbnailAnimation;
54 final Transformation thumbnailTransformation = new Transformation();
55
Craig Mautner322e4032012-07-13 13:35:20 -070056 /** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */
Craig Mautnerbea12bd2012-08-20 10:18:34 -070057 ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<WindowStateAnimator>();
Craig Mautner322e4032012-07-13 13:35:20 -070058
Craig Mautnerfbf378c2012-04-23 17:24:21 -070059 static final Animation sDummyAnimation = new DummyAnimation();
60
Craig Mautner322e4032012-07-13 13:35:20 -070061 public AppWindowAnimator(final AppWindowToken atoken) {
Craig Mautner59431632012-04-04 11:56:44 -070062 mAppToken = atoken;
Craig Mautner322e4032012-07-13 13:35:20 -070063 mService = atoken.service;
64 mAnimator = atoken.mAnimator;
Craig Mautner59431632012-04-04 11:56:44 -070065 }
66
Craig Mautner9339c402012-11-30 11:23:56 -080067 public void setAnimation(Animation anim, int width, int height) {
Craig Mautner72669d12012-12-18 17:23:54 -080068 if (WindowManagerService.localLOGV) Slog.v(TAG, "Setting animation in " + mAppToken
69 + ": " + anim + " wxh=" + width + "x" + height
70 + " isVisible=" + mAppToken.isVisible());
Craig Mautner59431632012-04-04 11:56:44 -070071 animation = anim;
72 animating = false;
Craig Mautner9339c402012-11-30 11:23:56 -080073 if (!anim.isInitialized()) {
74 anim.initialize(width, height, width, height);
75 }
Craig Mautner59431632012-04-04 11:56:44 -070076 anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
77 anim.scaleCurrentDuration(mService.mTransitionAnimationScale);
78 int zorder = anim.getZAdjustment();
79 int adj = 0;
80 if (zorder == Animation.ZORDER_TOP) {
81 adj = WindowManagerService.TYPE_LAYER_OFFSET;
82 } else if (zorder == Animation.ZORDER_BOTTOM) {
83 adj = -WindowManagerService.TYPE_LAYER_OFFSET;
84 }
85
86 if (animLayerAdjustment != adj) {
87 animLayerAdjustment = adj;
88 updateLayers();
89 }
90 // Start out animation gone if window is gone, or visible if window is visible.
91 transformation.clear();
Craig Mautner72669d12012-12-18 17:23:54 -080092 transformation.setAlpha(mAppToken.isVisible() ? 1 : 0);
Craig Mautner59431632012-04-04 11:56:44 -070093 hasTransformation = true;
94 }
95
96 public void setDummyAnimation() {
Craig Mautner72669d12012-12-18 17:23:54 -080097 if (WindowManagerService.localLOGV) Slog.v(TAG, "Setting dummy animation in " + mAppToken
98 + " isVisible=" + mAppToken.isVisible());
Craig Mautner1d961d42012-05-27 12:02:11 -070099 animation = sDummyAnimation;
Craig Mautner94ef9df2012-05-02 17:08:39 -0700100 hasTransformation = true;
101 transformation.clear();
Craig Mautner72669d12012-12-18 17:23:54 -0800102 transformation.setAlpha(mAppToken.isVisible() ? 1 : 0);
Craig Mautner59431632012-04-04 11:56:44 -0700103 }
104
105 public void clearAnimation() {
106 if (animation != null) {
107 animation = null;
108 animating = true;
Craig Mautner59431632012-04-04 11:56:44 -0700109 }
110 clearThumbnail();
Craig Mautner7636dfb2012-11-16 15:24:11 -0800111 if (mAppToken.deferClearAllDrawn) {
112 mAppToken.allDrawn = false;
113 mAppToken.deferClearAllDrawn = false;
114 }
Craig Mautner59431632012-04-04 11:56:44 -0700115 }
116
117 public void clearThumbnail() {
118 if (thumbnail != null) {
119 thumbnail.destroy();
120 thumbnail = null;
121 }
122 }
123
124 void updateLayers() {
125 final int N = mAppToken.allAppWindows.size();
126 final int adj = animLayerAdjustment;
127 thumbnailLayer = -1;
128 for (int i=0; i<N; i++) {
129 final WindowState w = mAppToken.allAppWindows.get(i);
130 final WindowStateAnimator winAnimator = w.mWinAnimator;
131 winAnimator.mAnimLayer = w.mLayer + adj;
132 if (winAnimator.mAnimLayer > thumbnailLayer) {
133 thumbnailLayer = winAnimator.mAnimLayer;
134 }
Craig Mautnerfbf378c2012-04-23 17:24:21 -0700135 if (WindowManagerService.DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": "
Craig Mautner59431632012-04-04 11:56:44 -0700136 + winAnimator.mAnimLayer);
137 if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) {
138 mService.setInputMethodAnimLayerAdjustment(adj);
139 }
Craig Mautner96868332012-12-04 14:29:11 -0800140 if (w == mService.mWallpaperTarget && mService.mLowerWallpaperTarget == null) {
Craig Mautner59431632012-04-04 11:56:44 -0700141 mService.setWallpaperAnimLayerAdjustmentLocked(adj);
142 }
143 }
144 }
145
146 private void stepThumbnailAnimation(long currentTime) {
147 thumbnailTransformation.clear();
148 thumbnailAnimation.getTransformation(currentTime, thumbnailTransformation);
149 thumbnailTransformation.getMatrix().preTranslate(thumbnailX, thumbnailY);
Craig Mautnera91f9e22012-09-14 16:22:08 -0700150
151 ScreenRotationAnimation screenRotationAnimation =
152 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
153 final boolean screenAnimation = screenRotationAnimation != null
154 && screenRotationAnimation.isAnimating();
Craig Mautner59431632012-04-04 11:56:44 -0700155 if (screenAnimation) {
Craig Mautnera91f9e22012-09-14 16:22:08 -0700156 thumbnailTransformation.postCompose(screenRotationAnimation.getEnterTransformation());
Craig Mautner59431632012-04-04 11:56:44 -0700157 }
158 // cache often used attributes locally
159 final float tmpFloats[] = mService.mTmpFloats;
160 thumbnailTransformation.getMatrix().getValues(tmpFloats);
161 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
162 "thumbnail", "POS " + tmpFloats[Matrix.MTRANS_X]
163 + ", " + tmpFloats[Matrix.MTRANS_Y], null);
164 thumbnail.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]);
165 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
166 "thumbnail", "alpha=" + thumbnailTransformation.getAlpha()
167 + " layer=" + thumbnailLayer
168 + " matrix=[" + tmpFloats[Matrix.MSCALE_X]
169 + "," + tmpFloats[Matrix.MSKEW_Y]
170 + "][" + tmpFloats[Matrix.MSKEW_X]
171 + "," + tmpFloats[Matrix.MSCALE_Y] + "]", null);
172 thumbnail.setAlpha(thumbnailTransformation.getAlpha());
173 // The thumbnail is layered below the window immediately above this
174 // token's anim layer.
175 thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER
176 - WindowManagerService.LAYER_OFFSET_THUMBNAIL);
177 thumbnail.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y],
178 tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]);
179 }
180
181 private boolean stepAnimation(long currentTime) {
182 if (animation == null) {
183 return false;
184 }
185 transformation.clear();
186 final boolean more = animation.getTransformation(currentTime, transformation);
Craig Mautner9e809442012-06-22 17:13:04 -0700187 if (false && WindowManagerService.DEBUG_ANIM) Slog.v(
Craig Mautner8a197a42012-04-24 16:59:36 -0700188 TAG, "Stepped animation in " + mAppToken + ": more=" + more + ", xform=" + transformation);
Craig Mautner59431632012-04-04 11:56:44 -0700189 if (!more) {
190 animation = null;
191 clearThumbnail();
192 if (WindowManagerService.DEBUG_ANIM) Slog.v(
Craig Mautner8a197a42012-04-24 16:59:36 -0700193 TAG, "Finished animation in " + mAppToken + " @ " + currentTime);
Craig Mautner59431632012-04-04 11:56:44 -0700194 }
195 hasTransformation = more;
196 return more;
197 }
198
199 // This must be called while inside a transaction.
Craig Mautner9339c402012-11-30 11:23:56 -0800200 boolean stepAnimationLocked(long currentTime) {
Craig Mautner59431632012-04-04 11:56:44 -0700201 if (mService.okToDisplay()) {
202 // We will run animations as long as the display isn't frozen.
203
Craig Mautnerfbf378c2012-04-23 17:24:21 -0700204 if (animation == sDummyAnimation) {
Craig Mautner59431632012-04-04 11:56:44 -0700205 // This guy is going to animate, but not yet. For now count
206 // it as not animating for purposes of scheduling transactions;
207 // when it is really time to animate, this will be set to
208 // a real animation and the next call will execute normally.
209 return false;
210 }
211
212 if ((mAppToken.allDrawn || animating || mAppToken.startingDisplayed)
213 && animation != null) {
214 if (!animating) {
215 if (WindowManagerService.DEBUG_ANIM) Slog.v(
Craig Mautner8a197a42012-04-24 16:59:36 -0700216 TAG, "Starting animation in " + mAppToken +
Craig Mautner9339c402012-11-30 11:23:56 -0800217 " @ " + currentTime + " scale=" + mService.mTransitionAnimationScale
Craig Mautner59431632012-04-04 11:56:44 -0700218 + " allDrawn=" + mAppToken.allDrawn + " animating=" + animating);
Craig Mautner59431632012-04-04 11:56:44 -0700219 animation.setStartTime(currentTime);
220 animating = true;
221 if (thumbnail != null) {
222 thumbnail.show();
223 thumbnailAnimation.setStartTime(currentTime);
224 }
225 }
226 if (stepAnimation(currentTime)) {
227 // animation isn't over, step any thumbnail and that's
228 // it for now.
229 if (thumbnail != null) {
230 stepThumbnailAnimation(currentTime);
231 }
232 return true;
233 }
234 }
235 } else if (animation != null) {
236 // If the display is frozen, and there is a pending animation,
237 // clear it and make sure we run the cleanup code.
238 animating = true;
239 animation = null;
240 }
241
242 hasTransformation = false;
243
Craig Mautner3de422f2012-04-06 18:04:13 -0700244 if (!animating && animation == null) {
Craig Mautner59431632012-04-04 11:56:44 -0700245 return false;
246 }
247
Craig Mautner76a71652012-09-03 23:23:58 -0700248 mAnimator.setAppLayoutChanges(this, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
249 "AppWindowToken");
Craig Mautner59431632012-04-04 11:56:44 -0700250
251 clearAnimation();
252 animating = false;
253 if (animLayerAdjustment != 0) {
254 animLayerAdjustment = 0;
255 updateLayers();
256 }
257 if (mService.mInputMethodTarget != null
258 && mService.mInputMethodTarget.mAppToken == mAppToken) {
259 mService.moveInputMethodWindowsIfNeededLocked(true);
260 }
261
262 if (WindowManagerService.DEBUG_ANIM) Slog.v(
Craig Mautner8a197a42012-04-24 16:59:36 -0700263 TAG, "Animation done in " + mAppToken
Craig Mautner59431632012-04-04 11:56:44 -0700264 + ": reportedVisible=" + mAppToken.reportedVisible);
265
266 transformation.clear();
267
Craig Mautner322e4032012-07-13 13:35:20 -0700268 final int N = mAllAppWinAnimators.size();
Craig Mautner59431632012-04-04 11:56:44 -0700269 for (int i=0; i<N; i++) {
Craig Mautner322e4032012-07-13 13:35:20 -0700270 mAllAppWinAnimators.get(i).finishExit();
Craig Mautner59431632012-04-04 11:56:44 -0700271 }
272 mAppToken.updateReportedVisibilityLocked();
273
274 return false;
275 }
276
Craig Mautnerbec53f72012-04-05 11:49:05 -0700277 boolean showAllWindowsLocked() {
278 boolean isAnimating = false;
Craig Mautner322e4032012-07-13 13:35:20 -0700279 final int NW = mAllAppWinAnimators.size();
Craig Mautnerbec53f72012-04-05 11:49:05 -0700280 for (int i=0; i<NW; i++) {
Craig Mautner322e4032012-07-13 13:35:20 -0700281 WindowStateAnimator winAnimator = mAllAppWinAnimators.get(i);
Craig Mautnerfbf378c2012-04-23 17:24:21 -0700282 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
Craig Mautnerbec53f72012-04-05 11:49:05 -0700283 "performing show on: " + winAnimator);
284 winAnimator.performShowLocked();
285 isAnimating |= winAnimator.isAnimating();
286 }
287 return isAnimating;
288 }
289
Dianne Hackborn529e7442012-11-01 14:22:28 -0700290 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
291 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
292 pw.print(prefix); pw.print("mAnimator="); pw.println(mAnimator);
293 pw.print(prefix); pw.print("freezingScreen="); pw.print(freezingScreen);
294 pw.print(" allDrawn="); pw.print(allDrawn);
295 pw.print(" animLayerAdjustment="); pw.println(animLayerAdjustment);
Dianne Hackborna57c6952013-03-29 14:46:40 -0700296 if (lastFreezeDuration != 0) {
297 pw.print(prefix); pw.print("lastFreezeDuration=");
298 TimeUtils.formatDuration(lastFreezeDuration, pw); pw.println();
299 }
Craig Mautner59431632012-04-04 11:56:44 -0700300 if (animating || animation != null) {
Craig Mautner9339c402012-11-30 11:23:56 -0800301 pw.print(prefix); pw.print("animating="); pw.println(animating);
Dianne Hackborn529e7442012-11-01 14:22:28 -0700302 pw.print(prefix); pw.print("animation="); pw.println(animation);
Craig Mautner59431632012-04-04 11:56:44 -0700303 }
304 if (hasTransformation) {
305 pw.print(prefix); pw.print("XForm: ");
306 transformation.printShortString(pw);
307 pw.println();
308 }
Craig Mautner59431632012-04-04 11:56:44 -0700309 if (thumbnail != null) {
310 pw.print(prefix); pw.print("thumbnail="); pw.print(thumbnail);
311 pw.print(" x="); pw.print(thumbnailX);
312 pw.print(" y="); pw.print(thumbnailY);
313 pw.print(" layer="); pw.println(thumbnailLayer);
314 pw.print(prefix); pw.print("thumbnailAnimation="); pw.println(thumbnailAnimation);
315 pw.print(prefix); pw.print("thumbnailTransformation=");
316 pw.println(thumbnailTransformation.toShortString());
317 }
Dianne Hackborn529e7442012-11-01 14:22:28 -0700318 for (int i=0; i<mAllAppWinAnimators.size(); i++) {
319 WindowStateAnimator wanim = mAllAppWinAnimators.get(i);
320 pw.print(prefix); pw.print("App Win Anim #"); pw.print(i);
321 pw.print(": "); pw.println(wanim);
322 }
Craig Mautner59431632012-04-04 11:56:44 -0700323 }
Craig Mautnerfbf378c2012-04-23 17:24:21 -0700324
325 // This is an animation that does nothing: it just immediately finishes
326 // itself every time it is called. It is used as a stub animation in cases
327 // where we want to synchronize multiple things that may be animating.
328 static final class DummyAnimation extends Animation {
329 @Override
330 public boolean getTransformation(long currentTime, Transformation outTransformation) {
331 return false;
332 }
333 }
334
Craig Mautner59431632012-04-04 11:56:44 -0700335}