blob: f41eed53cbca9736f88e3b81161560590d5b4d0a [file] [log] [blame]
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001/*
2 * Copyright (C) 2016 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
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080019import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
20import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
21import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
22
23import android.animation.Animator;
24import android.animation.ValueAnimator;
Winson Chungbaa7b722017-03-03 21:33:44 -080025import android.content.Context;
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080026import android.graphics.Rect;
Wale Ogunwale2ba71292016-05-05 09:16:47 -070027import android.os.Handler;
Robert Carrf9aa2a92016-04-26 14:22:19 -070028import android.os.IBinder;
Wale Ogunwale5658e4b2016-02-12 12:22:19 -080029import android.os.Debug;
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080030import android.util.ArrayMap;
31import android.util.Slog;
Winson Chungbaa7b722017-03-03 21:33:44 -080032import android.view.animation.AnimationUtils;
33import android.view.animation.Interpolator;
Robert Carrf9aa2a92016-04-26 14:22:19 -070034import android.view.WindowManagerInternal;
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080035
Winson Chung19953ca2017-04-11 11:19:23 -070036import com.android.internal.annotations.VisibleForTesting;
37
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080038/**
39 * Enables animating bounds of objects.
40 *
41 * In multi-window world bounds of both stack and tasks can change. When we need these bounds to
42 * change smoothly and not require the app to relaunch (e.g. because it handles resizes and
43 * relaunching it would cause poorer experience), these class provides a way to directly animate
44 * the bounds of the resized object.
45 *
46 * The object that is resized needs to implement {@link AnimateBoundsUser} interface.
Wale Ogunwale2ba71292016-05-05 09:16:47 -070047 *
48 * NOTE: All calls to methods in this class should be done on the UI thread
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080049 */
50public class BoundsAnimationController {
Wale Ogunwale5658e4b2016-02-12 12:22:19 -080051 private static final boolean DEBUG_LOCAL = false;
52 private static final boolean DEBUG = DEBUG_LOCAL || DEBUG_ANIM;
53 private static final String TAG = TAG_WITH_CLASS_NAME || DEBUG_LOCAL
54 ? "BoundsAnimationController" : TAG_WM;
Wale Ogunwalece144522016-02-05 22:51:01 -080055 private static final int DEBUG_ANIMATION_SLOW_DOWN_FACTOR = 1;
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080056
Winson Chungbaa7b722017-03-03 21:33:44 -080057 private static final int DEFAULT_TRANSITION_DURATION = 425;
58
Wale Ogunwalece144522016-02-05 22:51:01 -080059 // Only accessed on UI thread.
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080060 private ArrayMap<AnimateBoundsUser, BoundsAnimator> mRunningAnimations = new ArrayMap<>();
61
Wale Ogunwale2ba71292016-05-05 09:16:47 -070062 private final class AppTransitionNotifier
63 extends WindowManagerInternal.AppTransitionListener implements Runnable {
Robert Carrf9aa2a92016-04-26 14:22:19 -070064
Wale Ogunwale2ba71292016-05-05 09:16:47 -070065 public void onAppTransitionCancelledLocked() {
Winson Chung87e5d552017-04-05 11:49:38 -070066 if (DEBUG) Slog.d(TAG, "onAppTransitionCancelledLocked:"
67 + " mFinishAnimationAfterTransition=" + mFinishAnimationAfterTransition);
Wale Ogunwale2ba71292016-05-05 09:16:47 -070068 animationFinished();
69 }
70 public void onAppTransitionFinishedLocked(IBinder token) {
Winson Chung87e5d552017-04-05 11:49:38 -070071 if (DEBUG) Slog.d(TAG, "onAppTransitionFinishedLocked:"
72 + " mFinishAnimationAfterTransition=" + mFinishAnimationAfterTransition);
Wale Ogunwale2ba71292016-05-05 09:16:47 -070073 animationFinished();
74 }
75 private void animationFinished() {
76 if (mFinishAnimationAfterTransition) {
77 mHandler.removeCallbacks(this);
Winson Chung87e5d552017-04-05 11:49:38 -070078 // This might end up calling into activity manager which will be bad since we have
79 // the window manager lock held at this point. Post a message to take care of the
80 // processing so we don't deadlock.
Wale Ogunwale2ba71292016-05-05 09:16:47 -070081 mHandler.post(this);
82 }
83 }
84
85 @Override
86 public void run() {
87 for (int i = 0; i < mRunningAnimations.size(); i++) {
88 final BoundsAnimator b = mRunningAnimations.valueAt(i);
89 b.onAnimationEnd(null);
90 }
91 }
92 }
93
94 private final Handler mHandler;
Robert Carrf9aa2a92016-04-26 14:22:19 -070095 private final AppTransition mAppTransition;
Wale Ogunwale2ba71292016-05-05 09:16:47 -070096 private final AppTransitionNotifier mAppTransitionNotifier = new AppTransitionNotifier();
Winson Chungbaa7b722017-03-03 21:33:44 -080097 private final Interpolator mFastOutSlowInInterpolator;
Robert Carrf9aa2a92016-04-26 14:22:19 -070098 private boolean mFinishAnimationAfterTransition = false;
99
Winson Chungbaa7b722017-03-03 21:33:44 -0800100 BoundsAnimationController(Context context, AppTransition transition, Handler handler) {
Wale Ogunwale2ba71292016-05-05 09:16:47 -0700101 mHandler = handler;
Robert Carrf9aa2a92016-04-26 14:22:19 -0700102 mAppTransition = transition;
103 mAppTransition.registerListenerLocked(mAppTransitionNotifier);
Winson Chungbaa7b722017-03-03 21:33:44 -0800104 mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
105 com.android.internal.R.interpolator.fast_out_slow_in);
Robert Carrf9aa2a92016-04-26 14:22:19 -0700106 }
107
Winson Chung19953ca2017-04-11 11:19:23 -0700108 @VisibleForTesting
109 final class BoundsAnimator extends ValueAnimator
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800110 implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener {
111 private final AnimateBoundsUser mTarget;
Winson Chung84a38342016-11-08 16:15:10 -0800112 private final Rect mFrom = new Rect();
113 private final Rect mTo = new Rect();
Robert Carr0d00c2e2016-02-29 17:45:02 -0800114 private final Rect mTmpRect = new Rect();
115 private final Rect mTmpTaskBounds = new Rect();
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -0800116 private final boolean mMoveToFullScreen;
Wale Ogunwalece144522016-02-05 22:51:01 -0800117 // True if this this animation was cancelled and will be replaced the another animation from
118 // the same {@link #AnimateBoundsUser} target.
Winson Chung19953ca2017-04-11 11:19:23 -0700119 private boolean mSkipFinalResize;
Winson Chung5af42fc2017-03-24 17:11:33 -0700120 // True if this animation replaced a previous animation of the same
Wale Ogunwalece144522016-02-05 22:51:01 -0800121 // {@link #AnimateBoundsUser} target.
Winson Chung5af42fc2017-03-24 17:11:33 -0700122 private final boolean mSkipAnimationStart;
Winson Chung19953ca2017-04-11 11:19:23 -0700123 // True if this animation was cancelled by the user, not as a part of a replacing animation
124 private boolean mSkipAnimationEnd;
Winson Chung5af42fc2017-03-24 17:11:33 -0700125 // True if this animation is not replacing a previous animation, or if the previous
126 // animation is animating to a different fullscreen state than the current animation.
127 // We use this to ensure that we always provide a consistent set/order of callbacks when we
128 // transition to/from PiP.
129 private final boolean mAnimatingToNewFullscreenState;
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800130
Robert Carr0d00c2e2016-02-29 17:45:02 -0800131 // Depending on whether we are animating from
132 // a smaller to a larger size
133 private final int mFrozenTaskWidth;
134 private final int mFrozenTaskHeight;
135
Winson Chung08f81892017-03-02 15:40:51 -0800136 BoundsAnimator(AnimateBoundsUser target, Rect from, Rect to, boolean moveToFullScreen,
Winson Chung5af42fc2017-03-24 17:11:33 -0700137 boolean replacingExistingAnimation, boolean animatingToNewFullscreenState) {
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800138 super();
139 mTarget = target;
Winson Chung84a38342016-11-08 16:15:10 -0800140 mFrom.set(from);
141 mTo.set(to);
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -0800142 mMoveToFullScreen = moveToFullScreen;
Winson Chung5af42fc2017-03-24 17:11:33 -0700143 mSkipAnimationStart = replacingExistingAnimation;
144 mAnimatingToNewFullscreenState = animatingToNewFullscreenState;
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800145 addUpdateListener(this);
146 addListener(this);
Robert Carr0d00c2e2016-02-29 17:45:02 -0800147
148 // If we are animating from smaller to larger, we want to change the task bounds
149 // to their final size immediately so we can use scaling to make the window
150 // larger. Likewise if we are going from bigger to smaller, we want to wait until
151 // the end so we don't have to upscale from the smaller finished size.
152 if (animatingToLargerSize()) {
153 mFrozenTaskWidth = mTo.width();
154 mFrozenTaskHeight = mTo.height();
155 } else {
156 mFrozenTaskWidth = mFrom.width();
157 mFrozenTaskHeight = mFrom.height();
158 }
159 }
160
Winson Chung5af42fc2017-03-24 17:11:33 -0700161 @Override
162 public void onAnimationStart(Animator animation) {
163 if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
164 + " mSkipAnimationStart=" + mSkipAnimationStart);
165 mFinishAnimationAfterTransition = false;
166 mTmpRect.set(mFrom.left, mFrom.top, mFrom.left + mFrozenTaskWidth,
167 mFrom.top + mFrozenTaskHeight);
168
169 // Ensure that we have prepared the target for animation before
170 // we trigger any size changes, so it can swap surfaces
171 // in to appropriate modes, or do as it wishes otherwise.
172 if (!mSkipAnimationStart) {
173 mTarget.onAnimationStart(mMoveToFullScreen);
Robert Carr0d00c2e2016-02-29 17:45:02 -0800174 }
Winson Chung5af42fc2017-03-24 17:11:33 -0700175
176 // If we are animating to a new fullscreen state (either to/from fullscreen), then
177 // notify the target of the change with the new frozen task bounds
Winson Chung47900652017-04-06 18:44:25 -0700178 if (mAnimatingToNewFullscreenState && mMoveToFullScreen) {
179 mTarget.updatePictureInPictureMode(null);
Winson Chung5af42fc2017-03-24 17:11:33 -0700180 }
181
182 // Immediately update the task bounds if they have to become larger, but preserve
183 // the starting position so we don't jump at the beginning of the animation.
184 if (animatingToLargerSize()) {
185 mTarget.setPinnedStackSize(mFrom, mTmpRect);
186 }
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800187 }
188
189 @Override
190 public void onAnimationUpdate(ValueAnimator animation) {
191 final float value = (Float) animation.getAnimatedValue();
192 final float remains = 1 - value;
Wale Ogunwalece144522016-02-05 22:51:01 -0800193 mTmpRect.left = (int) (mFrom.left * remains + mTo.left * value + 0.5f);
194 mTmpRect.top = (int) (mFrom.top * remains + mTo.top * value + 0.5f);
195 mTmpRect.right = (int) (mFrom.right * remains + mTo.right * value + 0.5f);
196 mTmpRect.bottom = (int) (mFrom.bottom * remains + mTo.bottom * value + 0.5f);
Wale Ogunwale5658e4b2016-02-12 12:22:19 -0800197 if (DEBUG) Slog.d(TAG, "animateUpdate: mTarget=" + mTarget + " mBounds="
198 + mTmpRect + " from=" + mFrom + " mTo=" + mTo + " value=" + value
199 + " remains=" + remains);
Robert Carr0d00c2e2016-02-29 17:45:02 -0800200
Robert Carrc7294602016-05-13 11:32:05 -0700201 mTmpTaskBounds.set(mTmpRect.left, mTmpRect.top,
202 mTmpRect.left + mFrozenTaskWidth, mTmpRect.top + mFrozenTaskHeight);
Robert Carr0d00c2e2016-02-29 17:45:02 -0800203
Robert Carrc7294602016-05-13 11:32:05 -0700204 if (!mTarget.setPinnedStackSize(mTmpRect, mTmpTaskBounds)) {
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800205 // Whoops, the target doesn't feel like animating anymore. Let's immediately finish
206 // any further animation.
Winson Chung87e5d552017-04-05 11:49:38 -0700207 if (DEBUG) Slog.d(TAG, "animateUpdate: cancelled");
Winson Chung19953ca2017-04-11 11:19:23 -0700208
209 // Since we are cancelling immediately without a replacement animation, send the
210 // animation end to maintain callback parity, but also skip any further resizes
211 prepareCancel(false /* skipAnimationEnd */, true /* skipFinalResize */);
212 cancel();
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800213 }
214 }
215
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800216 @Override
217 public void onAnimationEnd(Animator animation) {
Wale Ogunwale5658e4b2016-02-12 12:22:19 -0800218 if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget
Winson Chung5af42fc2017-03-24 17:11:33 -0700219 + " mMoveToFullScreen=" + mMoveToFullScreen
Winson Chung19953ca2017-04-11 11:19:23 -0700220 + " mSkipFinalResize=" + mSkipFinalResize
Winson Chung87e5d552017-04-05 11:49:38 -0700221 + " mFinishAnimationAfterTransition=" + mFinishAnimationAfterTransition
222 + " mAppTransitionIsRunning=" + mAppTransition.isRunning());
Jaewan Kimb0033642016-04-22 18:41:37 +0900223
Robert Carrf9aa2a92016-04-26 14:22:19 -0700224 // There could be another animation running. For example in the
225 // move to fullscreen case, recents will also be closing while the
226 // previous task will be taking its place in the fullscreen stack.
227 // we have to ensure this is completed before we finish the animation
228 // and take our place in the fullscreen stack.
229 if (mAppTransition.isRunning() && !mFinishAnimationAfterTransition) {
230 mFinishAnimationAfterTransition = true;
231 return;
232 }
233
Winson Chung19953ca2017-04-11 11:19:23 -0700234 if (!mSkipFinalResize) {
235 // If not cancelled, resize the pinned stack to the final size. All calls to
236 // setPinnedStackSize() must be done between onAnimationStart() and onAnimationEnd()
237 mTarget.setPinnedStackSize(mTo, null);
238 }
239
Robert Carrc7294602016-05-13 11:32:05 -0700240 finishAnimation();
241
Winson Chung19953ca2017-04-11 11:19:23 -0700242 if (mMoveToFullScreen && !mSkipFinalResize) {
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -0800243 mTarget.moveToFullscreen();
244 }
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800245 }
246
247 @Override
248 public void onAnimationCancel(Animator animation) {
249 finishAnimation();
250 }
251
Winson Chung19953ca2017-04-11 11:19:23 -0700252 public void prepareCancel(boolean skipAnimationEnd, boolean skipFinalResize) {
253 if (DEBUG) Slog.d(TAG, "prepareCancel: skipAnimationEnd=" + skipAnimationEnd
254 + " skipFinalResize=" + skipFinalResize);
255 mSkipAnimationEnd = skipAnimationEnd;
256 mSkipFinalResize = skipFinalResize;
257 }
258
Wale Ogunwalece144522016-02-05 22:51:01 -0800259 @Override
260 public void cancel() {
Winson Chung19953ca2017-04-11 11:19:23 -0700261 if (DEBUG) Slog.d(TAG, "cancel: mTarget=" + mTarget);
Wale Ogunwalece144522016-02-05 22:51:01 -0800262 super.cancel();
263 }
264
Wale Ogunwale5658e4b2016-02-12 12:22:19 -0800265 /** Returns true if the animation target is the same as the input bounds. */
Winson Chung5af42fc2017-03-24 17:11:33 -0700266 boolean isAnimatingTo(Rect bounds) {
Wale Ogunwale5658e4b2016-02-12 12:22:19 -0800267 return mTo.equals(bounds);
268 }
269
Winson Chung5af42fc2017-03-24 17:11:33 -0700270 private boolean animatingToLargerSize() {
271 if (mFrom.width() * mFrom.height() > mTo.width() * mTo.height()) {
272 return false;
273 }
274 return true;
275 }
276
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800277 private void finishAnimation() {
Wale Ogunwale5658e4b2016-02-12 12:22:19 -0800278 if (DEBUG) Slog.d(TAG, "finishAnimation: mTarget=" + mTarget
279 + " callers" + Debug.getCallers(2));
Winson Chung5af42fc2017-03-24 17:11:33 -0700280 if (!mSkipAnimationEnd) {
Wale Ogunwalece144522016-02-05 22:51:01 -0800281 mTarget.onAnimationEnd();
282 }
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800283 removeListener(this);
284 removeUpdateListener(this);
285 mRunningAnimations.remove(mTarget);
286 }
287
288 @Override
289 public void onAnimationRepeat(Animator animation) {
Winson Chung5af42fc2017-03-24 17:11:33 -0700290 // Do nothing
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800291 }
292 }
293
294 public interface AnimateBoundsUser {
295 /**
Winson Chung19953ca2017-04-11 11:19:23 -0700296 * Sets the size of the target (without any intermediate steps, like scheduling animation)
297 * but freezes the bounds of any tasks in the target at taskBounds,
Winson Chung5af42fc2017-03-24 17:11:33 -0700298 * to allow for more flexibility during resizing. Only works for the pinned stack at the
299 * moment.
Winson Chung19953ca2017-04-11 11:19:23 -0700300 *
301 * @return Whether the target should continue to be animated and this call was successful.
302 * If false, the animation will be cancelled because the user has determined that the
303 * animation is now invalid and not required. In such a case, the cancel will trigger the
304 * animation end callback as well, but will not send any further size changes.
Robert Carr0d00c2e2016-02-29 17:45:02 -0800305 */
306 boolean setPinnedStackSize(Rect bounds, Rect taskBounds);
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800307
Winson Chung5af42fc2017-03-24 17:11:33 -0700308 /**
309 * Callback for the target to inform it that the animation has started, so it can do some
310 * necessary preparation.
311 */
Robert Carr7e4c90e2017-02-15 19:52:38 -0800312 void onAnimationStart(boolean toFullscreen);
Wale Ogunwalece144522016-02-05 22:51:01 -0800313
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800314 /**
Winson Chung5af42fc2017-03-24 17:11:33 -0700315 * Callback for the target to inform it that the animation is going to a new fullscreen
316 * state and should update the picture-in-picture mode accordingly.
317 *
318 * @param targetStackBounds the target stack bounds we are animating to, can be null if
319 * we are animating to fullscreen
320 */
321 void updatePictureInPictureMode(Rect targetStackBounds);
322
323 /**
Wale Ogunwalece144522016-02-05 22:51:01 -0800324 * Callback for the target to inform it that the animation has ended, so it can do some
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800325 * necessary cleanup.
326 */
Wale Ogunwalece144522016-02-05 22:51:01 -0800327 void onAnimationEnd();
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -0800328
Winson Chung19953ca2017-04-11 11:19:23 -0700329 /**
330 * Callback for the target to inform it to reparent to the fullscreen stack.
331 */
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -0800332 void moveToFullscreen();
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800333 }
334
Winson Chung19953ca2017-04-11 11:19:23 -0700335 public void animateBounds(final AnimateBoundsUser target, Rect from, Rect to,
336 int animationDuration, boolean moveToFullscreen) {
337 animateBoundsImpl(target, from, to, animationDuration, moveToFullscreen);
338 }
339
340 @VisibleForTesting
341 BoundsAnimator animateBoundsImpl(final AnimateBoundsUser target, Rect from, Rect to,
342 int animationDuration, boolean moveToFullscreen) {
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800343 final BoundsAnimator existing = mRunningAnimations.get(target);
Wale Ogunwalece144522016-02-05 22:51:01 -0800344 final boolean replacing = existing != null;
Winson Chung5af42fc2017-03-24 17:11:33 -0700345 final boolean animatingToNewFullscreenState = (existing == null) ||
346 (existing.mMoveToFullScreen != moveToFullscreen);
Wale Ogunwale5658e4b2016-02-12 12:22:19 -0800347
348 if (DEBUG) Slog.d(TAG, "animateBounds: target=" + target + " from=" + from + " to=" + to
Winson Chung5af42fc2017-03-24 17:11:33 -0700349 + " moveToFullscreen=" + moveToFullscreen + " replacing=" + replacing
350 + " animatingToNewFullscreenState=" + animatingToNewFullscreenState);
Wale Ogunwale5658e4b2016-02-12 12:22:19 -0800351
Wale Ogunwalece144522016-02-05 22:51:01 -0800352 if (replacing) {
Wale Ogunwale5658e4b2016-02-12 12:22:19 -0800353 if (existing.isAnimatingTo(to)) {
Winson Chung19953ca2017-04-11 11:19:23 -0700354 // Just let the current animation complete if it has the same destination as the
Wale Ogunwale5658e4b2016-02-12 12:22:19 -0800355 // one we are trying to start.
356 if (DEBUG) Slog.d(TAG, "animateBounds: same destination as existing=" + existing
357 + " ignoring...");
Winson Chung19953ca2017-04-11 11:19:23 -0700358 return existing;
Wale Ogunwale5658e4b2016-02-12 12:22:19 -0800359 }
Winson Chung19953ca2017-04-11 11:19:23 -0700360 // Since we are replacing, we skip both animation start and end callbacks, and don't
361 // animate to the final bounds when cancelling
362 existing.prepareCancel(true /* skipAnimationEnd */, true /* skipFinalResize */);
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800363 existing.cancel();
364 }
Winson Chung5af42fc2017-03-24 17:11:33 -0700365 final BoundsAnimator animator = new BoundsAnimator(target, from, to, moveToFullscreen,
366 replacing, animatingToNewFullscreenState);
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800367 mRunningAnimations.put(target, animator);
368 animator.setFloatValues(0f, 1f);
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -0700369 animator.setDuration((animationDuration != -1 ? animationDuration
Winson Chungbaa7b722017-03-03 21:33:44 -0800370 : DEFAULT_TRANSITION_DURATION) * DEBUG_ANIMATION_SLOW_DOWN_FACTOR);
371 animator.setInterpolator(mFastOutSlowInInterpolator);
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800372 animator.start();
Winson Chung19953ca2017-04-11 11:19:23 -0700373 return animator;
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800374 }
375}