blob: 63ae98e444a5d542c8711a80649d0a5bded3d84c [file] [log] [blame]
Craig Mautnerc2c0a612014-02-20 20:25:41 -08001/*
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 */
Craig Mautner59431632012-04-04 11:56:44 -070016
17package com.android.server.wm;
18
19import android.graphics.Matrix;
20import android.util.Slog;
Dianne Hackborna57c6952013-03-29 14:46:40 -070021import android.util.TimeUtils;
Craig Mautnera91f9e22012-09-14 16:22:08 -070022import android.view.Display;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080023import android.view.SurfaceControl;
Craig Mautner59431632012-04-04 11:56:44 -070024import android.view.WindowManagerPolicy;
25import android.view.animation.Animation;
26import android.view.animation.Transformation;
27
28import java.io.PrintWriter;
Craig Mautner322e4032012-07-13 13:35:20 -070029import java.util.ArrayList;
Craig Mautner59431632012-04-04 11:56:44 -070030
Craig Mautner59431632012-04-04 11:56:44 -070031public class AppWindowAnimator {
Craig Mautnerfbf378c2012-04-23 17:24:21 -070032 static final String TAG = "AppWindowAnimator";
Craig Mautner59431632012-04-04 11:56:44 -070033
34 final AppWindowToken mAppToken;
35 final WindowManagerService mService;
36 final WindowAnimator mAnimator;
37
38 boolean animating;
39 Animation animation;
Craig Mautner59431632012-04-04 11:56:44 -070040 boolean hasTransformation;
41 final Transformation transformation = new Transformation();
42
43 // Have we been asked to have this token keep the screen frozen?
44 // Protect with mAnimator.
45 boolean freezingScreen;
46
Dianne Hackborna57c6952013-03-29 14:46:40 -070047 /**
48 * How long we last kept the screen frozen.
49 */
50 int lastFreezeDuration;
51
Craig Mautner59431632012-04-04 11:56:44 -070052 // Offset to the window of all layers in the token, for use by
53 // AppWindowToken animations.
54 int animLayerAdjustment;
55
Craig Mautner6fbda632012-07-03 09:26:39 -070056 // Propagated from AppWindowToken.allDrawn, to determine when
57 // the state changes.
58 boolean allDrawn;
59
Craig Mautner59431632012-04-04 11:56:44 -070060 // Special surface for thumbnail animation.
Mathias Agopian3866f0d2013-02-11 22:08:48 -080061 SurfaceControl thumbnail;
Craig Mautner59431632012-04-04 11:56:44 -070062 int thumbnailTransactionSeq;
63 int thumbnailX;
64 int thumbnailY;
65 int thumbnailLayer;
66 Animation thumbnailAnimation;
67 final Transformation thumbnailTransformation = new Transformation();
68
Craig Mautner322e4032012-07-13 13:35:20 -070069 /** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */
Craig Mautnerbea12bd2012-08-20 10:18:34 -070070 ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<WindowStateAnimator>();
Craig Mautner322e4032012-07-13 13:35:20 -070071
Craig Mautnerfbf378c2012-04-23 17:24:21 -070072 static final Animation sDummyAnimation = new DummyAnimation();
73
Craig Mautner322e4032012-07-13 13:35:20 -070074 public AppWindowAnimator(final AppWindowToken atoken) {
Craig Mautner59431632012-04-04 11:56:44 -070075 mAppToken = atoken;
Craig Mautner322e4032012-07-13 13:35:20 -070076 mService = atoken.service;
77 mAnimator = atoken.mAnimator;
Craig Mautner59431632012-04-04 11:56:44 -070078 }
79
Craig Mautner9339c402012-11-30 11:23:56 -080080 public void setAnimation(Animation anim, int width, int height) {
Craig Mautner72669d12012-12-18 17:23:54 -080081 if (WindowManagerService.localLOGV) Slog.v(TAG, "Setting animation in " + mAppToken
82 + ": " + anim + " wxh=" + width + "x" + height
83 + " isVisible=" + mAppToken.isVisible());
Craig Mautner59431632012-04-04 11:56:44 -070084 animation = anim;
85 animating = false;
Craig Mautner9339c402012-11-30 11:23:56 -080086 if (!anim.isInitialized()) {
87 anim.initialize(width, height, width, height);
88 }
Craig Mautner59431632012-04-04 11:56:44 -070089 anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
Dianne Hackborneb94fa72014-06-03 17:48:12 -070090 anim.scaleCurrentDuration(mService.getTransitionAnimationScaleLocked());
Craig Mautner59431632012-04-04 11:56:44 -070091 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();
Craig Mautner72669d12012-12-18 17:23:54 -0800105 transformation.setAlpha(mAppToken.isVisible() ? 1 : 0);
Craig Mautner59431632012-04-04 11:56:44 -0700106 hasTransformation = true;
107 }
108
109 public void setDummyAnimation() {
Craig Mautner72669d12012-12-18 17:23:54 -0800110 if (WindowManagerService.localLOGV) Slog.v(TAG, "Setting dummy animation in " + mAppToken
111 + " isVisible=" + mAppToken.isVisible());
Craig Mautner1d961d42012-05-27 12:02:11 -0700112 animation = sDummyAnimation;
Craig Mautner94ef9df2012-05-02 17:08:39 -0700113 hasTransformation = true;
114 transformation.clear();
Craig Mautner72669d12012-12-18 17:23:54 -0800115 transformation.setAlpha(mAppToken.isVisible() ? 1 : 0);
Craig Mautner59431632012-04-04 11:56:44 -0700116 }
117
118 public void clearAnimation() {
119 if (animation != null) {
120 animation = null;
121 animating = true;
Craig Mautner59431632012-04-04 11:56:44 -0700122 }
123 clearThumbnail();
Craig Mautner7636dfb2012-11-16 15:24:11 -0800124 if (mAppToken.deferClearAllDrawn) {
125 mAppToken.allDrawn = false;
126 mAppToken.deferClearAllDrawn = false;
127 }
Craig Mautner59431632012-04-04 11:56:44 -0700128 }
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 }
Craig Mautnerfbf378c2012-04-23 17:24:21 -0700148 if (WindowManagerService.DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": "
Craig Mautner59431632012-04-04 11:56:44 -0700149 + winAnimator.mAnimLayer);
150 if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) {
151 mService.setInputMethodAnimLayerAdjustment(adj);
152 }
Craig Mautner96868332012-12-04 14:29:11 -0800153 if (w == mService.mWallpaperTarget && mService.mLowerWallpaperTarget == null) {
Craig Mautner59431632012-04-04 11:56:44 -0700154 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);
Craig Mautnera91f9e22012-09-14 16:22:08 -0700163
164 ScreenRotationAnimation screenRotationAnimation =
165 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
166 final boolean screenAnimation = screenRotationAnimation != null
167 && screenRotationAnimation.isAnimating();
Craig Mautner59431632012-04-04 11:56:44 -0700168 if (screenAnimation) {
Craig Mautnera91f9e22012-09-14 16:22:08 -0700169 thumbnailTransformation.postCompose(screenRotationAnimation.getEnterTransformation());
Craig Mautner59431632012-04-04 11:56:44 -0700170 }
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);
Craig Mautner9e809442012-06-22 17:13:04 -0700200 if (false && WindowManagerService.DEBUG_ANIM) Slog.v(
Craig Mautner8a197a42012-04-24 16:59:36 -0700201 TAG, "Stepped animation in " + mAppToken + ": more=" + more + ", xform=" + transformation);
Craig Mautner59431632012-04-04 11:56:44 -0700202 if (!more) {
203 animation = null;
204 clearThumbnail();
205 if (WindowManagerService.DEBUG_ANIM) Slog.v(
Craig Mautner8a197a42012-04-24 16:59:36 -0700206 TAG, "Finished animation in " + mAppToken + " @ " + currentTime);
Craig Mautner59431632012-04-04 11:56:44 -0700207 }
208 hasTransformation = more;
209 return more;
210 }
211
212 // This must be called while inside a transaction.
Craig Mautner9339c402012-11-30 11:23:56 -0800213 boolean stepAnimationLocked(long currentTime) {
Craig Mautner59431632012-04-04 11:56:44 -0700214 if (mService.okToDisplay()) {
215 // We will run animations as long as the display isn't frozen.
216
Craig Mautnerfbf378c2012-04-23 17:24:21 -0700217 if (animation == sDummyAnimation) {
Craig Mautner59431632012-04-04 11:56:44 -0700218 // 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(
Craig Mautner8a197a42012-04-24 16:59:36 -0700229 TAG, "Starting animation in " + mAppToken +
Dianne Hackborneb94fa72014-06-03 17:48:12 -0700230 " @ " + currentTime + " scale="
231 + mService.getTransitionAnimationScaleLocked()
Craig Mautner59431632012-04-04 11:56:44 -0700232 + " allDrawn=" + mAppToken.allDrawn + " animating=" + animating);
Craig Mautner59431632012-04-04 11:56:44 -0700233 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
Craig Mautner3de422f2012-04-06 18:04:13 -0700258 if (!animating && animation == null) {
Craig Mautner59431632012-04-04 11:56:44 -0700259 return false;
260 }
261
Craig Mautner76a71652012-09-03 23:23:58 -0700262 mAnimator.setAppLayoutChanges(this, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
263 "AppWindowToken");
Craig Mautner59431632012-04-04 11:56:44 -0700264
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(
Craig Mautner8a197a42012-04-24 16:59:36 -0700277 TAG, "Animation done in " + mAppToken
Craig Mautner59431632012-04-04 11:56:44 -0700278 + ": reportedVisible=" + mAppToken.reportedVisible);
279
280 transformation.clear();
281
Craig Mautner322e4032012-07-13 13:35:20 -0700282 final int N = mAllAppWinAnimators.size();
Craig Mautner59431632012-04-04 11:56:44 -0700283 for (int i=0; i<N; i++) {
Craig Mautner322e4032012-07-13 13:35:20 -0700284 mAllAppWinAnimators.get(i).finishExit();
Craig Mautner59431632012-04-04 11:56:44 -0700285 }
286 mAppToken.updateReportedVisibilityLocked();
287
288 return false;
289 }
290
Craig Mautnerbec53f72012-04-05 11:49:05 -0700291 boolean showAllWindowsLocked() {
292 boolean isAnimating = false;
Craig Mautner322e4032012-07-13 13:35:20 -0700293 final int NW = mAllAppWinAnimators.size();
Craig Mautnerbec53f72012-04-05 11:49:05 -0700294 for (int i=0; i<NW; i++) {
Craig Mautner322e4032012-07-13 13:35:20 -0700295 WindowStateAnimator winAnimator = mAllAppWinAnimators.get(i);
Craig Mautnerfbf378c2012-04-23 17:24:21 -0700296 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
Craig Mautnerbec53f72012-04-05 11:49:05 -0700297 "performing show on: " + winAnimator);
298 winAnimator.performShowLocked();
299 isAnimating |= winAnimator.isAnimating();
300 }
301 return isAnimating;
302 }
303
Dianne Hackborn529e7442012-11-01 14:22:28 -0700304 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);
Dianne Hackborna57c6952013-03-29 14:46:40 -0700310 if (lastFreezeDuration != 0) {
311 pw.print(prefix); pw.print("lastFreezeDuration=");
312 TimeUtils.formatDuration(lastFreezeDuration, pw); pw.println();
313 }
Craig Mautner59431632012-04-04 11:56:44 -0700314 if (animating || animation != null) {
Craig Mautner9339c402012-11-30 11:23:56 -0800315 pw.print(prefix); pw.print("animating="); pw.println(animating);
Dianne Hackborn529e7442012-11-01 14:22:28 -0700316 pw.print(prefix); pw.print("animation="); pw.println(animation);
Craig Mautner59431632012-04-04 11:56:44 -0700317 }
318 if (hasTransformation) {
319 pw.print(prefix); pw.print("XForm: ");
320 transformation.printShortString(pw);
321 pw.println();
322 }
Craig Mautner59431632012-04-04 11:56:44 -0700323 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 }
Dianne Hackborn529e7442012-11-01 14:22:28 -0700332 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 }
Craig Mautner59431632012-04-04 11:56:44 -0700337 }
Craig Mautnerfbf378c2012-04-23 17:24:21 -0700338
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
Craig Mautner59431632012-04-04 11:56:44 -0700349}