blob: ddbbde1eb4218118b348c5e412d4cee000077449 [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
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -070019import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
Jorim Jaggife762342016-10-13 14:33:27 +020020
21import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080022import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080023import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
24import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
25import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
26import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Wale Ogunwale8ebc82a2015-05-13 15:27:12 -070027import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
Jorim Jaggi6a7c90a2016-03-11 15:04:59 +010028import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Wale Ogunwale8ebc82a2015-05-13 15:27:12 -070029
Craig Mautner59431632012-04-04 11:56:44 -070030import android.graphics.Matrix;
31import android.util.Slog;
Dianne Hackborna57c6952013-03-29 14:46:40 -070032import android.util.TimeUtils;
Jorim Jaggic554b772015-06-04 16:07:57 -070033import android.view.Choreographer;
Craig Mautnera91f9e22012-09-14 16:22:08 -070034import android.view.Display;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080035import android.view.SurfaceControl;
Craig Mautner59431632012-04-04 11:56:44 -070036import android.view.animation.Animation;
37import android.view.animation.Transformation;
38
39import java.io.PrintWriter;
Craig Mautner322e4032012-07-13 13:35:20 -070040import java.util.ArrayList;
Craig Mautner59431632012-04-04 11:56:44 -070041
Craig Mautner59431632012-04-04 11:56:44 -070042public class AppWindowAnimator {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080043 static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowAnimator" : TAG_WM;
Craig Mautner59431632012-04-04 11:56:44 -070044
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -080045 private static final int PROLONG_ANIMATION_DISABLED = 0;
46 static final int PROLONG_ANIMATION_AT_END = 1;
47 static final int PROLONG_ANIMATION_AT_START = 2;
48
Craig Mautner59431632012-04-04 11:56:44 -070049 final AppWindowToken mAppToken;
50 final WindowManagerService mService;
51 final WindowAnimator mAnimator;
52
53 boolean animating;
Jorim Jaggi827e0fa2015-05-07 11:41:41 -070054 boolean wasAnimating;
Craig Mautner59431632012-04-04 11:56:44 -070055 Animation animation;
Craig Mautner59431632012-04-04 11:56:44 -070056 boolean hasTransformation;
57 final Transformation transformation = new Transformation();
58
59 // Have we been asked to have this token keep the screen frozen?
60 // Protect with mAnimator.
61 boolean freezingScreen;
62
Dianne Hackborna57c6952013-03-29 14:46:40 -070063 /**
64 * How long we last kept the screen frozen.
65 */
66 int lastFreezeDuration;
67
Craig Mautner59431632012-04-04 11:56:44 -070068 // Offset to the window of all layers in the token, for use by
69 // AppWindowToken animations.
70 int animLayerAdjustment;
71
Craig Mautner6fbda632012-07-03 09:26:39 -070072 // Propagated from AppWindowToken.allDrawn, to determine when
73 // the state changes.
74 boolean allDrawn;
75
Winson Chungab79fce2014-11-04 16:15:22 -080076 // Special surface for thumbnail animation. If deferThumbnailDestruction is enabled, then we
77 // will make sure that the thumbnail is destroyed after the other surface is completed. This
78 // requires that the duration of the two animations are the same.
Mathias Agopian3866f0d2013-02-11 22:08:48 -080079 SurfaceControl thumbnail;
Craig Mautner59431632012-04-04 11:56:44 -070080 int thumbnailTransactionSeq;
Matthew Ng7c706472017-05-05 17:12:18 -070081 // TODO(b/62029108): combine both members into a private one. Create a member function to set
82 // the thumbnail layer to +1 to the highest layer position and replace all setter instances
83 // with this function. Remove all unnecessary calls to both variables in other classes.
Craig Mautner59431632012-04-04 11:56:44 -070084 int thumbnailLayer;
Winson Chunga4ccb862014-08-22 15:26:27 -070085 int thumbnailForceAboveLayer;
Craig Mautner59431632012-04-04 11:56:44 -070086 Animation thumbnailAnimation;
87 final Transformation thumbnailTransformation = new Transformation();
Winson Chunga4ccb862014-08-22 15:26:27 -070088 // This flag indicates that the destruction of the thumbnail surface is synchronized with
Winson Chungab79fce2014-11-04 16:15:22 -080089 // another animation, so defer the destruction of this thumbnail surface for a single frame
90 // after the secondary animation completes.
Winson Chunga4ccb862014-08-22 15:26:27 -070091 boolean deferThumbnailDestruction;
Winson Chungab79fce2014-11-04 16:15:22 -080092 // This flag is set if the animator has deferThumbnailDestruction set and has reached the final
93 // frame of animation. It will extend the animation by one frame and then clean up afterwards.
94 boolean deferFinalFrameCleanup;
Filip Gruszczynski14b4e572015-11-03 15:53:55 -080095 // If true when the animation hits the last frame, it will keep running on that last frame.
96 // This is used to synchronize animation with Recents and we wait for Recents to tell us to
97 // finish or for a new animation be set as fail-safe mechanism.
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -080098 private int mProlongAnimation;
Filip Gruszczynski14b4e572015-11-03 15:53:55 -080099 // Whether the prolong animation can be removed when animation is set. The purpose of this is
100 // that if recents doesn't tell us to remove the prolonged animation, we will get rid of it
101 // when new animation is set.
102 private boolean mClearProlongedAnimation;
Jorim Jaggife762342016-10-13 14:33:27 +0200103 private int mTransit;
104 private int mTransitFlags;
Craig Mautner59431632012-04-04 11:56:44 -0700105
Craig Mautner322e4032012-07-13 13:35:20 -0700106 /** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */
Wale Ogunwale8ebc82a2015-05-13 15:27:12 -0700107 ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<>();
108
109 /** True if the current animation was transferred from another AppWindowAnimator.
110 * See {@link #transferCurrentAnimation}*/
111 boolean usingTransferredAnimation = false;
Craig Mautner322e4032012-07-13 13:35:20 -0700112
Jorim Jaggic554b772015-06-04 16:07:57 -0700113 private boolean mSkipFirstFrame = false;
Jorim Jaggi6a7c90a2016-03-11 15:04:59 +0100114 private int mStackClip = STACK_CLIP_BEFORE_ANIM;
Jorim Jaggic554b772015-06-04 16:07:57 -0700115
Craig Mautnerfbf378c2012-04-23 17:24:21 -0700116 static final Animation sDummyAnimation = new DummyAnimation();
117
Wale Ogunwale2049dbf2016-08-02 21:05:23 -0700118 public AppWindowAnimator(final AppWindowToken atoken, WindowManagerService service) {
Craig Mautner59431632012-04-04 11:56:44 -0700119 mAppToken = atoken;
Wale Ogunwale2049dbf2016-08-02 21:05:23 -0700120 mService = service;
Filip Gruszczynskia590c992015-11-25 16:45:26 -0800121 mAnimator = mService.mAnimator;
Craig Mautner59431632012-04-04 11:56:44 -0700122 }
123
Jorim Jaggife762342016-10-13 14:33:27 +0200124 public void setAnimation(Animation anim, int width, int height, int parentWidth,
125 int parentHeight, boolean skipFirstFrame, int stackClip, int transit,
126 int transitFlags) {
Craig Mautner72669d12012-12-18 17:23:54 -0800127 if (WindowManagerService.localLOGV) Slog.v(TAG, "Setting animation in " + mAppToken
128 + ": " + anim + " wxh=" + width + "x" + height
Wale Ogunwale44f21802016-09-02 12:49:48 -0700129 + " hasContentToDisplay=" + mAppToken.hasContentToDisplay());
Craig Mautner59431632012-04-04 11:56:44 -0700130 animation = anim;
131 animating = false;
Craig Mautner9339c402012-11-30 11:23:56 -0800132 if (!anim.isInitialized()) {
Jorim Jaggife762342016-10-13 14:33:27 +0200133 anim.initialize(width, height, parentWidth, parentHeight);
Craig Mautner9339c402012-11-30 11:23:56 -0800134 }
Craig Mautner59431632012-04-04 11:56:44 -0700135 anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
Dianne Hackborneb94fa72014-06-03 17:48:12 -0700136 anim.scaleCurrentDuration(mService.getTransitionAnimationScaleLocked());
Craig Mautner59431632012-04-04 11:56:44 -0700137 int zorder = anim.getZAdjustment();
138 int adj = 0;
139 if (zorder == Animation.ZORDER_TOP) {
Wale Ogunwale8ebc82a2015-05-13 15:27:12 -0700140 adj = TYPE_LAYER_OFFSET;
Craig Mautner59431632012-04-04 11:56:44 -0700141 } else if (zorder == Animation.ZORDER_BOTTOM) {
Wale Ogunwale8ebc82a2015-05-13 15:27:12 -0700142 adj = -TYPE_LAYER_OFFSET;
Craig Mautner59431632012-04-04 11:56:44 -0700143 }
144
145 if (animLayerAdjustment != adj) {
146 animLayerAdjustment = adj;
147 updateLayers();
148 }
149 // Start out animation gone if window is gone, or visible if window is visible.
150 transformation.clear();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700151 transformation.setAlpha(mAppToken.hasContentToDisplay() ? 1 : 0);
Craig Mautner59431632012-04-04 11:56:44 -0700152 hasTransformation = true;
Jorim Jaggi6a7c90a2016-03-11 15:04:59 +0100153 mStackClip = stackClip;
Craig Mautner1ad99152014-08-28 15:47:13 -0700154
Jorim Jaggife762342016-10-13 14:33:27 +0200155 mSkipFirstFrame = skipFirstFrame;
156 mTransit = transit;
157 mTransitFlags = transitFlags;
Jorim Jaggic554b772015-06-04 16:07:57 -0700158
Wale Ogunwale51362492016-09-08 17:49:17 -0700159 if (!mAppToken.fillsParent()) {
Craig Mautner1ad99152014-08-28 15:47:13 -0700160 anim.setBackgroundColor(0);
161 }
Filip Gruszczynski14b4e572015-11-03 15:53:55 -0800162 if (mClearProlongedAnimation) {
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -0800163 mProlongAnimation = PROLONG_ANIMATION_DISABLED;
Filip Gruszczynski14b4e572015-11-03 15:53:55 -0800164 } else {
165 mClearProlongedAnimation = true;
166 }
Craig Mautner59431632012-04-04 11:56:44 -0700167 }
168
169 public void setDummyAnimation() {
Craig Mautner72669d12012-12-18 17:23:54 -0800170 if (WindowManagerService.localLOGV) Slog.v(TAG, "Setting dummy animation in " + mAppToken
Wale Ogunwale44f21802016-09-02 12:49:48 -0700171 + " hasContentToDisplay=" + mAppToken.hasContentToDisplay());
Craig Mautner1d961d42012-05-27 12:02:11 -0700172 animation = sDummyAnimation;
Craig Mautner94ef9df2012-05-02 17:08:39 -0700173 hasTransformation = true;
174 transformation.clear();
Wale Ogunwale44f21802016-09-02 12:49:48 -0700175 transformation.setAlpha(mAppToken.hasContentToDisplay() ? 1 : 0);
Craig Mautner59431632012-04-04 11:56:44 -0700176 }
177
Chong Zhang65d15d02016-03-14 13:59:32 -0700178 void setNullAnimation() {
179 animation = null;
180 usingTransferredAnimation = false;
181 }
182
Craig Mautner59431632012-04-04 11:56:44 -0700183 public void clearAnimation() {
184 if (animation != null) {
Craig Mautner59431632012-04-04 11:56:44 -0700185 animating = true;
Craig Mautner59431632012-04-04 11:56:44 -0700186 }
Winson Chungab79fce2014-11-04 16:15:22 -0800187 clearThumbnail();
Chong Zhang65d15d02016-03-14 13:59:32 -0700188 setNullAnimation();
Craig Mautner7636dfb2012-11-16 15:24:11 -0800189 if (mAppToken.deferClearAllDrawn) {
Chong Zhang92147042016-05-09 12:47:11 -0700190 mAppToken.clearAllDrawn();
Craig Mautner7636dfb2012-11-16 15:24:11 -0800191 }
Jorim Jaggi6a7c90a2016-03-11 15:04:59 +0100192 mStackClip = STACK_CLIP_BEFORE_ANIM;
Jorim Jaggife762342016-10-13 14:33:27 +0200193 mTransit = TRANSIT_UNSET;
194 mTransitFlags = 0;
Craig Mautner59431632012-04-04 11:56:44 -0700195 }
196
Jorim Jaggi37875612015-02-19 21:05:31 +0100197 public boolean isAnimating() {
198 return animation != null || mAppToken.inPendingTransaction;
199 }
200
Jorim Jaggic0c93242017-08-04 16:05:02 +0200201 /**
202 * @return whether an animation is about to start, i.e. the animation is set already but we
203 * haven't processed the first frame yet.
204 */
205 boolean isAnimationStarting() {
206 return animation != null && !animating;
207 }
208
Jorim Jaggife762342016-10-13 14:33:27 +0200209 public int getTransit() {
210 return mTransit;
211 }
212
213 int getTransitFlags() {
214 return mTransitFlags;
215 }
216
Craig Mautner59431632012-04-04 11:56:44 -0700217 public void clearThumbnail() {
218 if (thumbnail != null) {
Jorim Jaggi3dac63a2016-03-01 12:37:07 +0100219 thumbnail.hide();
220 mService.mWindowPlacerLocked.destroyAfterTransaction(thumbnail);
Craig Mautner59431632012-04-04 11:56:44 -0700221 thumbnail = null;
222 }
Winson Chungab79fce2014-11-04 16:15:22 -0800223 deferThumbnailDestruction = false;
Winson Chunga4ccb862014-08-22 15:26:27 -0700224 }
225
Jorim Jaggi6a7c90a2016-03-11 15:04:59 +0100226 int getStackClip() {
227 return mStackClip;
228 }
229
Wale Ogunwale8ebc82a2015-05-13 15:27:12 -0700230 void transferCurrentAnimation(
231 AppWindowAnimator toAppAnimator, WindowStateAnimator transferWinAnimator) {
232
233 if (animation != null) {
234 toAppAnimator.animation = animation;
Wale Ogunwale8ebc82a2015-05-13 15:27:12 -0700235 toAppAnimator.animating = animating;
236 toAppAnimator.animLayerAdjustment = animLayerAdjustment;
Chong Zhang65d15d02016-03-14 13:59:32 -0700237 setNullAnimation();
Wale Ogunwale8ebc82a2015-05-13 15:27:12 -0700238 animLayerAdjustment = 0;
239 toAppAnimator.updateLayers();
240 updateLayers();
241 toAppAnimator.usingTransferredAnimation = true;
Jorim Jaggife762342016-10-13 14:33:27 +0200242 toAppAnimator.mTransit = mTransit;
Wale Ogunwale8ebc82a2015-05-13 15:27:12 -0700243 }
244 if (transferWinAnimator != null) {
245 mAllAppWinAnimators.remove(transferWinAnimator);
246 toAppAnimator.mAllAppWinAnimators.add(transferWinAnimator);
Chong Zhang8e062652016-04-29 15:58:45 -0700247 toAppAnimator.hasTransformation = transferWinAnimator.mAppAnimator.hasTransformation;
248 if (toAppAnimator.hasTransformation) {
249 toAppAnimator.transformation.set(transferWinAnimator.mAppAnimator.transformation);
250 } else {
251 toAppAnimator.transformation.clear();
252 }
Wale Ogunwale8ebc82a2015-05-13 15:27:12 -0700253 transferWinAnimator.mAppAnimator = toAppAnimator;
254 }
255 }
256
Robert Carrdee1b3f2017-02-27 11:33:33 -0800257 private void updateLayers() {
258 mAppToken.getDisplayContent().assignWindowLayers(false /* relayoutNeeded */);
259 thumbnailLayer = mAppToken.getHighestAnimLayer();
Craig Mautner59431632012-04-04 11:56:44 -0700260 }
261
262 private void stepThumbnailAnimation(long currentTime) {
263 thumbnailTransformation.clear();
Filip Gruszczynski564a8f62015-11-20 11:25:23 -0800264 final long animationFrameTime = getAnimationFrameTime(thumbnailAnimation, currentTime);
265 thumbnailAnimation.getTransformation(animationFrameTime, thumbnailTransformation);
Craig Mautnera91f9e22012-09-14 16:22:08 -0700266
267 ScreenRotationAnimation screenRotationAnimation =
268 mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
269 final boolean screenAnimation = screenRotationAnimation != null
270 && screenRotationAnimation.isAnimating();
Craig Mautner59431632012-04-04 11:56:44 -0700271 if (screenAnimation) {
Craig Mautnera91f9e22012-09-14 16:22:08 -0700272 thumbnailTransformation.postCompose(screenRotationAnimation.getEnterTransformation());
Craig Mautner59431632012-04-04 11:56:44 -0700273 }
274 // cache often used attributes locally
275 final float tmpFloats[] = mService.mTmpFloats;
276 thumbnailTransformation.getMatrix().getValues(tmpFloats);
Wale Ogunwale8ebc82a2015-05-13 15:27:12 -0700277 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
Craig Mautner59431632012-04-04 11:56:44 -0700278 "thumbnail", "POS " + tmpFloats[Matrix.MTRANS_X]
Filip Gruszczynski198dcbf2016-01-18 10:02:00 -0800279 + ", " + tmpFloats[Matrix.MTRANS_Y]);
Craig Mautner59431632012-04-04 11:56:44 -0700280 thumbnail.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]);
Wale Ogunwale8ebc82a2015-05-13 15:27:12 -0700281 if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
Craig Mautner59431632012-04-04 11:56:44 -0700282 "thumbnail", "alpha=" + thumbnailTransformation.getAlpha()
283 + " layer=" + thumbnailLayer
284 + " matrix=[" + tmpFloats[Matrix.MSCALE_X]
285 + "," + tmpFloats[Matrix.MSKEW_Y]
286 + "][" + tmpFloats[Matrix.MSKEW_X]
Filip Gruszczynski198dcbf2016-01-18 10:02:00 -0800287 + "," + tmpFloats[Matrix.MSCALE_Y] + "]");
Craig Mautner59431632012-04-04 11:56:44 -0700288 thumbnail.setAlpha(thumbnailTransformation.getAlpha());
Winson Chunga4ccb862014-08-22 15:26:27 -0700289 if (thumbnailForceAboveLayer > 0) {
290 thumbnail.setLayer(thumbnailForceAboveLayer + 1);
291 } else {
292 // The thumbnail is layered below the window immediately above this
293 // token's anim layer.
294 thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER
295 - WindowManagerService.LAYER_OFFSET_THUMBNAIL);
296 }
Craig Mautner59431632012-04-04 11:56:44 -0700297 thumbnail.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y],
298 tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]);
Jorim Jaggide63d442016-03-14 14:56:56 +0100299 thumbnail.setWindowCrop(thumbnailTransformation.getClipRect());
Craig Mautner59431632012-04-04 11:56:44 -0700300 }
301
Filip Gruszczynski564a8f62015-11-20 11:25:23 -0800302 /**
303 * Sometimes we need to synchronize the first frame of animation with some external event, e.g.
304 * Recents hiding some of its content. To achieve this, we prolong the start of the animaiton
305 * and keep producing the first frame of the animation.
306 */
307 private long getAnimationFrameTime(Animation animation, long currentTime) {
308 if (mProlongAnimation == PROLONG_ANIMATION_AT_START) {
309 animation.setStartTime(currentTime);
310 return currentTime + 1;
311 }
312 return currentTime;
313 }
314
Craig Mautner59431632012-04-04 11:56:44 -0700315 private boolean stepAnimation(long currentTime) {
316 if (animation == null) {
317 return false;
318 }
319 transformation.clear();
Filip Gruszczynski564a8f62015-11-20 11:25:23 -0800320 final long animationFrameTime = getAnimationFrameTime(animation, currentTime);
321 boolean hasMoreFrames = animation.getTransformation(animationFrameTime, transformation);
Winson Chungab79fce2014-11-04 16:15:22 -0800322 if (!hasMoreFrames) {
323 if (deferThumbnailDestruction && !deferFinalFrameCleanup) {
324 // We are deferring the thumbnail destruction, so extend the animation for one more
325 // (dummy) frame before we clean up
326 deferFinalFrameCleanup = true;
327 hasMoreFrames = true;
328 } else {
Wale Ogunwale8ebc82a2015-05-13 15:27:12 -0700329 if (false && DEBUG_ANIM) Slog.v(TAG,
330 "Stepped animation in " + mAppToken + ": more=" + hasMoreFrames +
Filip Gruszczynski14b4e572015-11-03 15:53:55 -0800331 ", xform=" + transformation + ", mProlongAnimation=" + mProlongAnimation);
Winson Chungab79fce2014-11-04 16:15:22 -0800332 deferFinalFrameCleanup = false;
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -0800333 if (mProlongAnimation == PROLONG_ANIMATION_AT_END) {
Filip Gruszczynski14b4e572015-11-03 15:53:55 -0800334 hasMoreFrames = true;
335 } else {
Chong Zhang65d15d02016-03-14 13:59:32 -0700336 setNullAnimation();
Filip Gruszczynski564a8f62015-11-20 11:25:23 -0800337 clearThumbnail();
338 if (DEBUG_ANIM) Slog.v(TAG, "Finished animation in " + mAppToken + " @ "
339 + currentTime);
Filip Gruszczynski14b4e572015-11-03 15:53:55 -0800340 }
Winson Chunga4ccb862014-08-22 15:26:27 -0700341 }
Craig Mautner59431632012-04-04 11:56:44 -0700342 }
Winson Chungab79fce2014-11-04 16:15:22 -0800343 hasTransformation = hasMoreFrames;
344 return hasMoreFrames;
Craig Mautner59431632012-04-04 11:56:44 -0700345 }
346
Jorim Jaggic554b772015-06-04 16:07:57 -0700347 private long getStartTimeCorrection() {
348 if (mSkipFirstFrame) {
349
350 // If the transition is an animation in which the first frame doesn't change the screen
351 // contents at all, we can just skip it and start at the second frame. So we shift the
352 // start time of the animation forward by minus the frame duration.
353 return -Choreographer.getInstance().getFrameIntervalNanos() / TimeUtils.NANOS_PER_MS;
354 } else {
355 return 0;
356 }
357 }
358
Craig Mautner59431632012-04-04 11:56:44 -0700359 // This must be called while inside a transaction.
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700360 boolean stepAnimationLocked(long currentTime) {
Adrian Roose94c15c2017-05-09 13:17:54 -0700361 if (mService.okToAnimate()) {
Craig Mautner59431632012-04-04 11:56:44 -0700362 // We will run animations as long as the display isn't frozen.
363
Craig Mautnerfbf378c2012-04-23 17:24:21 -0700364 if (animation == sDummyAnimation) {
Craig Mautner59431632012-04-04 11:56:44 -0700365 // This guy is going to animate, but not yet. For now count
366 // it as not animating for purposes of scheduling transactions;
367 // when it is really time to animate, this will be set to
368 // a real animation and the next call will execute normally.
369 return false;
370 }
371
Chong Zhangbfc2f8f2016-01-29 15:50:34 -0800372 if ((mAppToken.allDrawn || animating || mAppToken.startingDisplayed)
Craig Mautner59431632012-04-04 11:56:44 -0700373 && animation != null) {
374 if (!animating) {
Wale Ogunwale8ebc82a2015-05-13 15:27:12 -0700375 if (DEBUG_ANIM) Slog.v(TAG,
376 "Starting animation in " + mAppToken +
Dianne Hackborneb94fa72014-06-03 17:48:12 -0700377 " @ " + currentTime + " scale="
378 + mService.getTransitionAnimationScaleLocked()
Craig Mautner59431632012-04-04 11:56:44 -0700379 + " allDrawn=" + mAppToken.allDrawn + " animating=" + animating);
Jorim Jaggic554b772015-06-04 16:07:57 -0700380 long correction = getStartTimeCorrection();
381 animation.setStartTime(currentTime + correction);
Craig Mautner59431632012-04-04 11:56:44 -0700382 animating = true;
383 if (thumbnail != null) {
384 thumbnail.show();
Jorim Jaggic554b772015-06-04 16:07:57 -0700385 thumbnailAnimation.setStartTime(currentTime + correction);
Craig Mautner59431632012-04-04 11:56:44 -0700386 }
Jorim Jaggic554b772015-06-04 16:07:57 -0700387 mSkipFirstFrame = false;
Craig Mautner59431632012-04-04 11:56:44 -0700388 }
389 if (stepAnimation(currentTime)) {
390 // animation isn't over, step any thumbnail and that's
391 // it for now.
392 if (thumbnail != null) {
393 stepThumbnailAnimation(currentTime);
394 }
395 return true;
396 }
397 }
398 } else if (animation != null) {
399 // If the display is frozen, and there is a pending animation,
400 // clear it and make sure we run the cleanup code.
401 animating = true;
402 animation = null;
403 }
404
405 hasTransformation = false;
406
Craig Mautner3de422f2012-04-06 18:04:13 -0700407 if (!animating && animation == null) {
Craig Mautner59431632012-04-04 11:56:44 -0700408 return false;
409 }
410
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700411 mAppToken.setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "AppWindowToken");
Craig Mautner59431632012-04-04 11:56:44 -0700412
413 clearAnimation();
414 animating = false;
415 if (animLayerAdjustment != 0) {
416 animLayerAdjustment = 0;
417 updateLayers();
418 }
419 if (mService.mInputMethodTarget != null
420 && mService.mInputMethodTarget.mAppToken == mAppToken) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000421 mAppToken.getDisplayContent().computeImeTarget(true /* updateImeTarget */);
Craig Mautner59431632012-04-04 11:56:44 -0700422 }
423
Wale Ogunwale15ead902016-09-02 14:30:11 -0700424 if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + mAppToken
Jorim Jaggidc9385a2017-05-13 02:00:31 +0200425 + ": reportedVisible=" + mAppToken.reportedVisible
426 + " okToDisplay=" + mService.okToDisplay()
Adrian Roose94c15c2017-05-09 13:17:54 -0700427 + " okToAnimate=" + mService.okToAnimate()
Jorim Jaggidc9385a2017-05-13 02:00:31 +0200428 + " startingDisplayed=" + mAppToken.startingDisplayed);
Craig Mautner59431632012-04-04 11:56:44 -0700429
430 transformation.clear();
431
Wale Ogunwaleec533f62014-12-05 09:03:48 -0800432 final int numAllAppWinAnimators = mAllAppWinAnimators.size();
433 for (int i = 0; i < numAllAppWinAnimators; i++) {
Wale Ogunwaleadde52e2016-07-16 13:11:55 -0700434 mAllAppWinAnimators.get(i).mWin.onExitAnimationDone();
Craig Mautner59431632012-04-04 11:56:44 -0700435 }
Wale Ogunwalea48eadb2015-05-14 17:43:12 -0700436 mService.mAppTransition.notifyAppTransitionFinishedLocked(mAppToken.token);
Craig Mautner59431632012-04-04 11:56:44 -0700437 return false;
438 }
439
Filip Gruszczynski974eb3d2015-10-23 17:33:11 -0700440 // This must be called while inside a transaction.
Craig Mautnerbec53f72012-04-05 11:49:05 -0700441 boolean showAllWindowsLocked() {
442 boolean isAnimating = false;
Craig Mautner322e4032012-07-13 13:35:20 -0700443 final int NW = mAllAppWinAnimators.size();
Craig Mautnerbec53f72012-04-05 11:49:05 -0700444 for (int i=0; i<NW; i++) {
Craig Mautner322e4032012-07-13 13:35:20 -0700445 WindowStateAnimator winAnimator = mAllAppWinAnimators.get(i);
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800446 if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + winAnimator);
Wale Ogunwale9d147902016-07-16 11:58:55 -0700447 winAnimator.mWin.performShowLocked();
Jorim Jaggi5c80c412016-04-19 20:03:47 -0700448 isAnimating |= winAnimator.isAnimationSet();
Craig Mautnerbec53f72012-04-05 11:49:05 -0700449 }
450 return isAnimating;
451 }
452
Dianne Hackborn529e7442012-11-01 14:22:28 -0700453 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
454 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
455 pw.print(prefix); pw.print("mAnimator="); pw.println(mAnimator);
456 pw.print(prefix); pw.print("freezingScreen="); pw.print(freezingScreen);
457 pw.print(" allDrawn="); pw.print(allDrawn);
458 pw.print(" animLayerAdjustment="); pw.println(animLayerAdjustment);
Dianne Hackborna57c6952013-03-29 14:46:40 -0700459 if (lastFreezeDuration != 0) {
460 pw.print(prefix); pw.print("lastFreezeDuration=");
461 TimeUtils.formatDuration(lastFreezeDuration, pw); pw.println();
462 }
Craig Mautner59431632012-04-04 11:56:44 -0700463 if (animating || animation != null) {
Craig Mautner9339c402012-11-30 11:23:56 -0800464 pw.print(prefix); pw.print("animating="); pw.println(animating);
Dianne Hackborn529e7442012-11-01 14:22:28 -0700465 pw.print(prefix); pw.print("animation="); pw.println(animation);
Jorim Jaggife762342016-10-13 14:33:27 +0200466 pw.print(prefix); pw.print("mTransit="); pw.println(mTransit);
467 pw.print(prefix); pw.print("mTransitFlags="); pw.println(mTransitFlags);
Craig Mautner59431632012-04-04 11:56:44 -0700468 }
469 if (hasTransformation) {
470 pw.print(prefix); pw.print("XForm: ");
471 transformation.printShortString(pw);
472 pw.println();
473 }
Craig Mautner59431632012-04-04 11:56:44 -0700474 if (thumbnail != null) {
475 pw.print(prefix); pw.print("thumbnail="); pw.print(thumbnail);
Craig Mautner59431632012-04-04 11:56:44 -0700476 pw.print(" layer="); pw.println(thumbnailLayer);
477 pw.print(prefix); pw.print("thumbnailAnimation="); pw.println(thumbnailAnimation);
478 pw.print(prefix); pw.print("thumbnailTransformation=");
479 pw.println(thumbnailTransformation.toShortString());
480 }
Dianne Hackborn529e7442012-11-01 14:22:28 -0700481 for (int i=0; i<mAllAppWinAnimators.size(); i++) {
482 WindowStateAnimator wanim = mAllAppWinAnimators.get(i);
483 pw.print(prefix); pw.print("App Win Anim #"); pw.print(i);
484 pw.print(": "); pw.println(wanim);
485 }
Craig Mautner59431632012-04-04 11:56:44 -0700486 }
Craig Mautnerfbf378c2012-04-23 17:24:21 -0700487
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -0800488 void startProlongAnimation(int prolongType) {
489 mProlongAnimation = prolongType;
Filip Gruszczynski14b4e572015-11-03 15:53:55 -0800490 mClearProlongedAnimation = false;
491 }
492
493 void endProlongedAnimation() {
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -0800494 mProlongAnimation = PROLONG_ANIMATION_DISABLED;
Filip Gruszczynski14b4e572015-11-03 15:53:55 -0800495 }
496
Craig Mautnerfbf378c2012-04-23 17:24:21 -0700497 // This is an animation that does nothing: it just immediately finishes
498 // itself every time it is called. It is used as a stub animation in cases
499 // where we want to synchronize multiple things that may be animating.
500 static final class DummyAnimation extends Animation {
501 @Override
502 public boolean getTransformation(long currentTime, Transformation outTransformation) {
503 return false;
504 }
505 }
506
Craig Mautner59431632012-04-04 11:56:44 -0700507}