blob: 18e32c0683d6478bbf0f5ec7de8f06402a278634 [file] [log] [blame]
Jorim Jaggi21c39a72017-10-20 15:47:51 +02001/*
2 * Copyright (C) 2017 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
Yi Jin6c6e9ca2018-03-20 16:53:35 -070019import static com.android.server.wm.SurfaceAnimatorProto.ANIMATION_ADAPTER;
20import static com.android.server.wm.SurfaceAnimatorProto.ANIMATION_START_DELAYED;
21import static com.android.server.wm.SurfaceAnimatorProto.LEASH;
Vishnu Naird454442d2018-11-13 13:51:01 -080022import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
23import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
24import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Jorim Jaggi21c39a72017-10-20 15:47:51 +020025
Issei Suzuki8b995df2020-01-08 12:23:04 +010026import android.annotation.IntDef;
Jorim Jaggi21c39a72017-10-20 15:47:51 +020027import android.annotation.NonNull;
28import android.annotation.Nullable;
29import android.util.Slog;
Vishnu Nair04ab4392018-01-10 11:00:06 -080030import android.util.proto.ProtoOutputStream;
Jorim Jaggi21c39a72017-10-20 15:47:51 +020031import android.view.SurfaceControl;
32import android.view.SurfaceControl.Transaction;
33
Jorim Jaggi980c9de2017-11-17 01:41:37 +010034import com.android.internal.annotations.VisibleForTesting;
35
Jorim Jaggi21c39a72017-10-20 15:47:51 +020036import java.io.PrintWriter;
Issei Suzuki8b995df2020-01-08 12:23:04 +010037import java.lang.annotation.Retention;
38import java.lang.annotation.RetentionPolicy;
Vishnu Nair5e3e2ea2020-03-16 11:30:34 -070039import java.util.function.Supplier;
Jorim Jaggi21c39a72017-10-20 15:47:51 +020040
41/**
42 * A class that can run animations on objects that have a set of child surfaces. We do this by
43 * reparenting all child surfaces of an object onto a new surface, called the "Leash". The Leash
44 * gets attached in the surface hierarchy where the the children were attached to. We then hand off
45 * the Leash to the component handling the animation, which is specified by the
46 * {@link AnimationAdapter}. When the animation is done animating, our callback to finish the
47 * animation will be invoked, at which we reparent the children back to the original parent.
48 */
49class SurfaceAnimator {
50
51 private static final String TAG = TAG_WITH_CLASS_NAME ? "SurfaceAnimator" : TAG_WM;
Winson Chung7e895da2020-02-03 13:28:44 -080052
Jorim Jaggi21c39a72017-10-20 15:47:51 +020053 private final WindowManagerService mService;
54 private AnimationAdapter mAnimation;
Issei Suzuki8b995df2020-01-08 12:23:04 +010055 private @AnimationType int mAnimationType;
Jorim Jaggi980c9de2017-11-17 01:41:37 +010056
57 @VisibleForTesting
58 SurfaceControl mLeash;
lumarkf6f34942019-04-29 16:56:50 +080059 @VisibleForTesting
60 final Animatable mAnimatable;
Jorim Jaggi21c39a72017-10-20 15:47:51 +020061 private final OnAnimationFinishedCallback mInnerAnimationFinishedCallback;
chaviwf20bd222018-02-01 16:06:52 -080062 @VisibleForTesting
Vadim Caen9745f972019-09-17 19:16:14 +020063 @Nullable
Issei Suzuki8b995df2020-01-08 12:23:04 +010064 final OnAnimationFinishedCallback mStaticAnimationFinishedCallback;
Issei Suzuki2f541842020-01-09 20:18:29 +010065 @Nullable
Issei Suzuki8b995df2020-01-08 12:23:04 +010066 private OnAnimationFinishedCallback mAnimationFinishedCallback;
Jorim Jaggi21c39a72017-10-20 15:47:51 +020067 private boolean mAnimationStartDelayed;
68
69 /**
70 * @param animatable The object to animate.
Issei Suzuki8b995df2020-01-08 12:23:04 +010071 * @param staticAnimationFinishedCallback Callback to invoke when an animation has finished
72 * running.
Jorim Jaggi21c39a72017-10-20 15:47:51 +020073 */
Issei Suzuki8b995df2020-01-08 12:23:04 +010074 SurfaceAnimator(Animatable animatable,
75 @Nullable OnAnimationFinishedCallback staticAnimationFinishedCallback,
Chavi Weingartenb736e322018-02-23 00:27:54 +000076 WindowManagerService service) {
Jorim Jaggi21c39a72017-10-20 15:47:51 +020077 mAnimatable = animatable;
78 mService = service;
Issei Suzuki8b995df2020-01-08 12:23:04 +010079 mStaticAnimationFinishedCallback = staticAnimationFinishedCallback;
80 mInnerAnimationFinishedCallback = getFinishedCallback(staticAnimationFinishedCallback);
Jorim Jaggi21c39a72017-10-20 15:47:51 +020081 }
82
Winson Chunge2d72172018-01-25 17:46:20 +000083 private OnAnimationFinishedCallback getFinishedCallback(
Issei Suzuki8b995df2020-01-08 12:23:04 +010084 @Nullable OnAnimationFinishedCallback staticAnimationFinishedCallback) {
85 return (type, anim) -> {
Wale Ogunwaledb485de2018-10-29 09:47:07 -070086 synchronized (mService.mGlobalLock) {
Jorim Jaggi980c9de2017-11-17 01:41:37 +010087 final SurfaceAnimator target = mService.mAnimationTransferMap.remove(anim);
88 if (target != null) {
Issei Suzuki8b995df2020-01-08 12:23:04 +010089 target.mInnerAnimationFinishedCallback.onAnimationFinished(type, anim);
Jorim Jaggi980c9de2017-11-17 01:41:37 +010090 return;
91 }
Jorim Jaggi21c39a72017-10-20 15:47:51 +020092
Chavi Weingartenb736e322018-02-23 00:27:54 +000093 if (anim != mAnimation) {
94 return;
95 }
Jorim Jaggi6de61012018-03-19 14:53:23 +010096 final Runnable resetAndInvokeFinish = () -> {
Riddle Hsu1d5856c2019-03-26 22:56:53 +080097 // We need to check again if the animation has been replaced with a new
98 // animation because the animatable may defer to finish.
99 if (anim != mAnimation) {
100 return;
101 }
Issei Suzuki8b995df2020-01-08 12:23:04 +0100102 final OnAnimationFinishedCallback animationFinishCallback =
103 mAnimationFinishedCallback;
Jorim Jaggi6de61012018-03-19 14:53:23 +0100104 reset(mAnimatable.getPendingTransaction(), true /* destroyLeash */);
Issei Suzuki8b995df2020-01-08 12:23:04 +0100105 if (staticAnimationFinishedCallback != null) {
106 staticAnimationFinishedCallback.onAnimationFinished(type, anim);
Jorim Jaggi6de61012018-03-19 14:53:23 +0100107 }
Issei Suzuki2f541842020-01-09 20:18:29 +0100108 if (animationFinishCallback != null) {
Issei Suzuki8b995df2020-01-08 12:23:04 +0100109 animationFinishCallback.onAnimationFinished(type, anim);
Issei Suzuki2f541842020-01-09 20:18:29 +0100110 }
Jorim Jaggi6de61012018-03-19 14:53:23 +0100111 };
112 if (!mAnimatable.shouldDeferAnimationFinish(resetAndInvokeFinish)) {
113 resetAndInvokeFinish.run();
Chavi Weingartenb736e322018-02-23 00:27:54 +0000114 }
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200115 }
116 };
117 }
118
119 /**
120 * Starts an animation.
121 *
122 * @param anim The object that bridges the controller, {@link SurfaceAnimator}, with the
123 * component responsible for running the animation. It runs the animation with
124 * {@link AnimationAdapter#startAnimation} once the hierarchy with
125 * the Leash has been set up.
126 * @param hidden Whether the container holding the child surfaces is currently visible or not.
127 * This is important as it will start with the leash hidden or visible before
128 * handing it to the component that is responsible to run the animation.
Issei Suzuki2f541842020-01-09 20:18:29 +0100129 * @param animationFinishedCallback The callback being triggered when the animation finishes.
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200130 */
Issei Suzuki2f541842020-01-09 20:18:29 +0100131 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
Issei Suzuki8b995df2020-01-08 12:23:04 +0100132 @AnimationType int type,
Evan Rosky55bddd82020-01-29 13:07:18 -0800133 @Nullable OnAnimationFinishedCallback animationFinishedCallback,
134 @Nullable SurfaceFreezer freezer) {
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100135 cancelAnimation(t, true /* restarting */, true /* forwardCancel */);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200136 mAnimation = anim;
Issei Suzuki8b995df2020-01-08 12:23:04 +0100137 mAnimationType = type;
Issei Suzuki2f541842020-01-09 20:18:29 +0100138 mAnimationFinishedCallback = animationFinishedCallback;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100139 final SurfaceControl surface = mAnimatable.getSurfaceControl();
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200140 if (surface == null) {
141 Slog.w(TAG, "Unable to start animation, surface is null or no children.");
142 cancelAnimation();
143 return;
144 }
Evan Rosky55bddd82020-01-29 13:07:18 -0800145 mLeash = freezer != null ? freezer.takeLeashForAnimation() : null;
146 if (mLeash == null) {
Winson Chung7e895da2020-02-03 13:28:44 -0800147 mLeash = createAnimationLeash(mAnimatable, surface, t, type,
Evan Rosky55bddd82020-01-29 13:07:18 -0800148 mAnimatable.getSurfaceWidth(), mAnimatable.getSurfaceHeight(), 0 /* x */,
Vishnu Nair5e3e2ea2020-03-16 11:30:34 -0700149 0 /* y */, hidden, mService.mTransactionFactory);
Evan Rosky55bddd82020-01-29 13:07:18 -0800150 mAnimatable.onAnimationLeashCreated(t, mLeash);
151 }
152 mAnimatable.onLeashAnimationStarting(t, mLeash);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200153 if (mAnimationStartDelayed) {
154 if (DEBUG_ANIM) Slog.i(TAG, "Animation start delayed");
155 return;
156 }
Issei Suzuki8b995df2020-01-08 12:23:04 +0100157 mAnimation.startAnimation(mLeash, t, type, mInnerAnimationFinishedCallback);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200158 }
159
Issei Suzuki8b995df2020-01-08 12:23:04 +0100160 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
Evan Rosky55bddd82020-01-29 13:07:18 -0800161 @AnimationType int type,
162 @Nullable OnAnimationFinishedCallback animationFinishedCallback) {
163 startAnimation(t, anim, hidden, type, animationFinishedCallback, null /* freezer */);
164 }
165
166 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
Issei Suzuki8b995df2020-01-08 12:23:04 +0100167 @AnimationType int type) {
168 startAnimation(t, anim, hidden, type, null /* animationFinishedCallback */);
Issei Suzuki2f541842020-01-09 20:18:29 +0100169 }
170
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200171 /**
172 * Begins with delaying all animations to start. Any subsequent call to {@link #startAnimation}
173 * will not start the animation until {@link #endDelayingAnimationStart} is called. When an
174 * animation start is being delayed, the animator is considered animating already.
175 */
176 void startDelayingAnimationStart() {
177
178 // We only allow delaying animation start we are not currently animating
179 if (!isAnimating()) {
180 mAnimationStartDelayed = true;
181 }
182 }
183
184 /**
185 * See {@link #startDelayingAnimationStart}.
186 */
187 void endDelayingAnimationStart() {
188 final boolean delayed = mAnimationStartDelayed;
189 mAnimationStartDelayed = false;
190 if (delayed && mAnimation != null) {
191 mAnimation.startAnimation(mLeash, mAnimatable.getPendingTransaction(),
Issei Suzuki8b995df2020-01-08 12:23:04 +0100192 mAnimationType, mInnerAnimationFinishedCallback);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200193 mAnimatable.commitPendingTransaction();
194 }
195 }
196
197 /**
198 * @return Whether we are currently running an animation, or we have a pending animation that
199 * is waiting to be started with {@link #endDelayingAnimationStart}
200 */
201 boolean isAnimating() {
202 return mAnimation != null;
203 }
204
chaviw9177c772020-03-24 11:35:22 -0700205 @AnimationType
206 int getAnimationType() {
207 return mAnimationType;
208 }
209
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200210 /**
211 * @return The current animation spec if we are running an animation, or {@code null} otherwise.
212 */
213 AnimationAdapter getAnimation() {
214 return mAnimation;
215 }
216
217 /**
218 * Cancels any currently running animation.
219 */
220 void cancelAnimation() {
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100221 cancelAnimation(mAnimatable.getPendingTransaction(), false /* restarting */,
222 true /* forwardCancel */);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200223 mAnimatable.commitPendingTransaction();
224 }
225
226 /**
227 * Sets the layer of the surface.
228 * <p>
229 * When the layer of the surface needs to be adjusted, we need to set it on the leash if the
230 * surface is reparented to the leash. This method takes care of that.
231 */
232 void setLayer(Transaction t, int layer) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100233 t.setLayer(mLeash != null ? mLeash : mAnimatable.getSurfaceControl(), layer);
234 }
235
236 /**
237 * Sets the surface to be relatively layered.
238 *
239 * @see #setLayer
240 */
241 void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
242 t.setRelativeLayer(mLeash != null ? mLeash : mAnimatable.getSurfaceControl(), relativeTo, layer);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200243 }
244
245 /**
246 * Reparents the surface.
247 *
248 * @see #setLayer
249 */
250 void reparent(Transaction t, SurfaceControl newParent) {
Robert Carr10584fa2019-01-14 15:55:19 -0800251 t.reparent(mLeash != null ? mLeash : mAnimatable.getSurfaceControl(), newParent);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200252 }
253
254 /**
255 * @return True if the surface is attached to the leash; false otherwise.
256 */
257 boolean hasLeash() {
258 return mLeash != null;
259 }
260
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100261 void transferAnimation(SurfaceAnimator from) {
262 if (from.mLeash == null) {
263 return;
264 }
265 final SurfaceControl surface = mAnimatable.getSurfaceControl();
Jorim Jaggi596a1992017-12-29 14:48:02 +0100266 final SurfaceControl parent = mAnimatable.getAnimationLeashParent();
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100267 if (surface == null || parent == null) {
268 Slog.w(TAG, "Unable to transfer animation, surface or parent is null");
269 cancelAnimation();
270 return;
271 }
272 endDelayingAnimationStart();
273 final Transaction t = mAnimatable.getPendingTransaction();
274 cancelAnimation(t, true /* restarting */, true /* forwardCancel */);
275 mLeash = from.mLeash;
276 mAnimation = from.mAnimation;
Issei Suzuki8b995df2020-01-08 12:23:04 +0100277 mAnimationType = from.mAnimationType;
Issei Suzuki2f541842020-01-09 20:18:29 +0100278 mAnimationFinishedCallback = from.mAnimationFinishedCallback;
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100279
280 // Cancel source animation, but don't let animation runner cancel the animation.
281 from.cancelAnimation(t, false /* restarting */, false /* forwardCancel */);
Robert Carr10584fa2019-01-14 15:55:19 -0800282 t.reparent(surface, mLeash);
283 t.reparent(mLeash, parent);
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100284 mAnimatable.onAnimationLeashCreated(t, mLeash);
285 mService.mAnimationTransferMap.put(mAnimation, this);
286 }
287
Jorim Jaggic4d29f22018-03-22 16:30:56 +0100288 boolean isAnimationStartDelayed() {
289 return mAnimationStartDelayed;
290 }
291
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100292 /**
293 * Cancels the animation, and resets the leash.
294 *
295 * @param t The transaction to use for all cancelling surface operations.
296 * @param restarting Whether we are restarting the animation.
297 * @param forwardCancel Whether to forward the cancel signal to the adapter executing the
298 * animation. This will be set to false when just transferring an animation
299 * to another animator.
300 */
301 private void cancelAnimation(Transaction t, boolean restarting, boolean forwardCancel) {
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200302 if (DEBUG_ANIM) Slog.i(TAG, "Cancelling animation restarting=" + restarting);
303 final SurfaceControl leash = mLeash;
304 final AnimationAdapter animation = mAnimation;
Issei Suzuki8b995df2020-01-08 12:23:04 +0100305 final @AnimationType int animationType = mAnimationType;
306 final OnAnimationFinishedCallback animationFinishedCallback = mAnimationFinishedCallback;
Robert Carr4a2d3742019-02-11 12:15:38 -0800307 reset(t, false);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200308 if (animation != null) {
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100309 if (!mAnimationStartDelayed && forwardCancel) {
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200310 animation.onAnimationCancelled(leash);
311 }
Issei Suzuki2f541842020-01-09 20:18:29 +0100312 if (!restarting) {
313 if (mStaticAnimationFinishedCallback != null) {
Issei Suzuki8b995df2020-01-08 12:23:04 +0100314 mStaticAnimationFinishedCallback.onAnimationFinished(animationType, animation);
Issei Suzuki2f541842020-01-09 20:18:29 +0100315 }
316 if (animationFinishedCallback != null) {
Issei Suzuki8b995df2020-01-08 12:23:04 +0100317 animationFinishedCallback.onAnimationFinished(animationType, animation);
Issei Suzuki2f541842020-01-09 20:18:29 +0100318 }
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200319 }
320 }
Robert Carr4a2d3742019-02-11 12:15:38 -0800321
322 if (forwardCancel && leash != null) {
323 t.remove(leash);
324 mService.scheduleAnimationLocked();
325 }
326
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200327 if (!restarting) {
328 mAnimationStartDelayed = false;
329 }
330 }
331
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100332 private void reset(Transaction t, boolean destroyLeash) {
Evan Rosky55bddd82020-01-29 13:07:18 -0800333 mService.mAnimationTransferMap.remove(mAnimation);
334 mAnimation = null;
335 mAnimationFinishedCallback = null;
336 mAnimationType = ANIMATION_TYPE_NONE;
337 if (mLeash == null) {
338 return;
339 }
340 SurfaceControl leash = mLeash;
341 mLeash = null;
342 final boolean scheduleAnim = removeLeash(t, mAnimatable, leash, destroyLeash);
343 if (scheduleAnim) {
344 mService.scheduleAnimationLocked();
345 }
346 }
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200347
Evan Rosky55bddd82020-01-29 13:07:18 -0800348 static boolean removeLeash(Transaction t, Animatable animatable, @NonNull SurfaceControl leash,
349 boolean destroy) {
Chavi Weingartenb736e322018-02-23 00:27:54 +0000350 boolean scheduleAnim = false;
Evan Rosky55bddd82020-01-29 13:07:18 -0800351 final SurfaceControl surface = animatable.getSurfaceControl();
352 final SurfaceControl parent = animatable.getParentSurfaceControl();
Chavi Weingartenb736e322018-02-23 00:27:54 +0000353
lumarkf6f34942019-04-29 16:56:50 +0800354 // If the surface was destroyed or the leash is invalid, we don't care to reparent it back.
355 // Note that we also set this variable to true even if the parent isn't valid anymore, in
356 // order to ensure onAnimationLeashLost still gets called in this case.
Evan Rosky55bddd82020-01-29 13:07:18 -0800357 final boolean reparent = surface != null;
lumarkf6f34942019-04-29 16:56:50 +0800358 if (reparent) {
359 if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to original parent: " + parent);
Robert Carr412f3562019-04-11 13:01:31 -0700360 // We shouldn't really need these isValid checks but we do
361 // b/130364451
lumarkf6f34942019-04-29 16:56:50 +0800362 if (surface.isValid() && parent != null && parent.isValid()) {
Robert Carr412f3562019-04-11 13:01:31 -0700363 t.reparent(surface, parent);
364 scheduleAnim = true;
365 }
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200366 }
Evan Rosky55bddd82020-01-29 13:07:18 -0800367 if (destroy) {
368 t.remove(leash);
Chavi Weingartenb736e322018-02-23 00:27:54 +0000369 scheduleAnim = true;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100370 }
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200371
lumarkf6f34942019-04-29 16:56:50 +0800372 if (reparent) {
373 // Make sure to inform the animatable after the surface was reparented (or reparent
374 // wasn't possible, but we still need to invoke the callback)
Evan Rosky55bddd82020-01-29 13:07:18 -0800375 animatable.onAnimationLeashLost(t);
Chavi Weingartenb736e322018-02-23 00:27:54 +0000376 scheduleAnim = true;
377 }
Evan Rosky55bddd82020-01-29 13:07:18 -0800378 return scheduleAnim;
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200379 }
380
Evan Rosky55bddd82020-01-29 13:07:18 -0800381 static SurfaceControl createAnimationLeash(Animatable animatable, SurfaceControl surface,
Winson Chung7e895da2020-02-03 13:28:44 -0800382 Transaction t, @AnimationType int type, int width, int height, int x, int y,
Vishnu Nair5e3e2ea2020-03-16 11:30:34 -0700383 boolean hidden, Supplier<Transaction> transactionFactory) {
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200384 if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to leash");
Evan Rosky55bddd82020-01-29 13:07:18 -0800385 final SurfaceControl.Builder builder = animatable.makeAnimationLeash()
386 .setParent(animatable.getAnimationLeashParent())
Vishnu Nair4ae4c332020-03-18 12:09:43 -0700387 .setName(surface + " - animation-leash")
388 .setColorLayer();
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200389 final SurfaceControl leash = builder.build();
Vishnu Nair5e3e2ea2020-03-16 11:30:34 -0700390 if (!hidden) {
391 // TODO(b/151665759) Defer reparent calls
392 // We want the leash to be visible immediately but we want to set the effects on
393 // the layer. Since the transaction used in this function may be deferred, we apply
394 // another transaction immediately with the correct visibility and effects.
395 // If this doesn't work, you will can see the 2/3 button nav bar flicker during
396 // seamless rotation.
397 transactionFactory.get().unsetColor(leash).show(leash).apply();
398 }
Vishnu Nair4ae4c332020-03-18 12:09:43 -0700399 t.unsetColor(leash);
Louis Changb92aa022018-11-16 15:46:50 +0800400 t.setWindowCrop(leash, width, height);
Evan Rosky55bddd82020-01-29 13:07:18 -0800401 t.setPosition(leash, x, y);
chaviw516ef792019-07-26 16:11:55 -0700402 t.show(leash);
chaviw516ef792019-07-26 16:11:55 -0700403 t.setAlpha(leash, hidden ? 0 : 1);
Tiger Huang969c6082019-12-24 20:08:57 +0800404
Robert Carr10584fa2019-01-14 15:55:19 -0800405 t.reparent(surface, leash);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200406 return leash;
407 }
408
Vishnu Nair04ab4392018-01-10 11:00:06 -0800409 /**
410 * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link
Yi Jin6c6e9ca2018-03-20 16:53:35 -0700411 * com.android.server.wm.SurfaceAnimatorProto}.
Vishnu Nair04ab4392018-01-10 11:00:06 -0800412 *
413 * @param proto Stream to write the SurfaceAnimator object to.
414 * @param fieldId Field Id of the SurfaceAnimator as defined in the parent message.
415 * @hide
416 */
Jeffrey Huangcb782852019-12-05 11:28:11 -0800417 void dumpDebug(ProtoOutputStream proto, long fieldId) {
Vishnu Nair04ab4392018-01-10 11:00:06 -0800418 final long token = proto.start(fieldId);
Jorim Jaggif75d1612018-02-27 15:05:21 +0100419 if (mAnimation != null) {
Jeffrey Huangcb782852019-12-05 11:28:11 -0800420 mAnimation.dumpDebug(proto, ANIMATION_ADAPTER);
Jorim Jaggif75d1612018-02-27 15:05:21 +0100421 }
Nataniel Borges023ecb52019-01-16 14:15:43 -0800422 if (mLeash != null) {
Jeffrey Huangcb782852019-12-05 11:28:11 -0800423 mLeash.dumpDebug(proto, LEASH);
Vishnu Nair04ab4392018-01-10 11:00:06 -0800424 }
425 proto.write(ANIMATION_START_DELAYED, mAnimationStartDelayed);
426 proto.end(token);
427 }
428
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200429 void dump(PrintWriter pw, String prefix) {
Jorim Jaggif75d1612018-02-27 15:05:21 +0100430 pw.print(prefix); pw.print("mLeash="); pw.print(mLeash);
431 if (mAnimationStartDelayed) {
432 pw.print(" mAnimationStartDelayed="); pw.println(mAnimationStartDelayed);
433 } else {
434 pw.println();
435 }
436 pw.print(prefix); pw.println("Animation:");
437 if (mAnimation != null) {
438 mAnimation.dump(pw, prefix + " ");
439 } else {
440 pw.print(prefix); pw.println("null");
441 }
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200442 }
443
Issei Suzuki8b995df2020-01-08 12:23:04 +0100444
445 /**
446 * No animation is specified.
447 * @hide
448 */
449 static final int ANIMATION_TYPE_NONE = 0;
450
451 /**
452 * Animation for an app transition.
453 * @hide
454 */
455 static final int ANIMATION_TYPE_APP_TRANSITION = 1;
456
457 /**
458 * Animation for screen rotation.
459 * @hide
460 */
chaviw9177c772020-03-24 11:35:22 -0700461 static final int ANIMATION_TYPE_SCREEN_ROTATION = 1 << 1;
Issei Suzuki8b995df2020-01-08 12:23:04 +0100462
463 /**
464 * Animation for dimming.
465 * @hide
466 */
chaviw9177c772020-03-24 11:35:22 -0700467 static final int ANIMATION_TYPE_DIMMER = 1 << 2;
Issei Suzuki8b995df2020-01-08 12:23:04 +0100468
469 /**
470 * Animation for recent apps.
471 * @hide
472 */
chaviw9177c772020-03-24 11:35:22 -0700473 static final int ANIMATION_TYPE_RECENTS = 1 << 3;
Issei Suzuki8b995df2020-01-08 12:23:04 +0100474
475 /**
476 * Animation for a {@link WindowState} without animating the activity.
477 * @hide
478 */
chaviw9177c772020-03-24 11:35:22 -0700479 static final int ANIMATION_TYPE_WINDOW_ANIMATION = 1 << 4;
Issei Suzuki8b995df2020-01-08 12:23:04 +0100480
481 /**
482 * Animation to control insets. This is actually not an animation, but is used to give the
483 * client a leash over the system window causing insets.
484 * @hide
485 */
chaviw9177c772020-03-24 11:35:22 -0700486 static final int ANIMATION_TYPE_INSETS_CONTROL = 1 << 5;
487
488 /**
489 * Bitmask to include all animation types. This is NOT an {@link AnimationType}
490 * @hide
491 */
492 static final int ANIMATION_TYPE_ALL = -1;
Issei Suzuki8b995df2020-01-08 12:23:04 +0100493
494 /**
495 * The type of the animation.
496 * @hide
497 */
498 @IntDef(flag = true, prefix = { "ANIMATION_TYPE_" }, value = {
499 ANIMATION_TYPE_NONE,
500 ANIMATION_TYPE_APP_TRANSITION,
501 ANIMATION_TYPE_SCREEN_ROTATION,
502 ANIMATION_TYPE_DIMMER,
503 ANIMATION_TYPE_RECENTS,
504 ANIMATION_TYPE_WINDOW_ANIMATION,
505 ANIMATION_TYPE_INSETS_CONTROL
506 })
507 @Retention(RetentionPolicy.SOURCE)
508 @interface AnimationType {}
509
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200510 /**
511 * Callback to be passed into {@link AnimationAdapter#startAnimation} to be invoked by the
512 * component that is running the animation when the animation is finished.
513 */
514 interface OnAnimationFinishedCallback {
Issei Suzuki8b995df2020-01-08 12:23:04 +0100515 void onAnimationFinished(@AnimationType int type, AnimationAdapter anim);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200516 }
517
518 /**
519 * Interface to be animated by {@link SurfaceAnimator}.
520 */
521 interface Animatable {
522
523 /**
524 * @return The pending transaction that will be committed in the next frame.
525 */
526 @NonNull Transaction getPendingTransaction();
527
528 /**
529 * Schedules a commit of the pending transaction.
530 */
531 void commitPendingTransaction();
532
533 /**
Evan Rosky55bddd82020-01-29 13:07:18 -0800534 * Called when the animation leash is created. Note that this is also called by
535 * {@link SurfaceFreezer}, so this doesn't mean we're about to start animating.
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200536 *
537 * @param t The transaction to use to apply any necessary changes.
538 * @param leash The leash that was created.
539 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100540 void onAnimationLeashCreated(Transaction t, SurfaceControl leash);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200541
542 /**
Evan Rosky55bddd82020-01-29 13:07:18 -0800543 * Called when the animator is about to start animating the leash.
544 *
545 * @param t The transaction to use to apply any necessary changes.
546 * @param leash The leash that was created.
547 */
548 default void onLeashAnimationStarting(Transaction t, SurfaceControl leash) { }
549
550 /**
lumarkf6f34942019-04-29 16:56:50 +0800551 * Called when the leash is being destroyed, or when the leash is being transferred to
552 * another SurfaceAnimator.
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200553 *
554 * @param t The transaction to use to apply any necessary changes.
555 */
lumarkf6f34942019-04-29 16:56:50 +0800556 void onAnimationLeashLost(Transaction t);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200557
558 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +0100559 * @return A new surface to be used for the animation leash, inserted at the correct
560 * position in the hierarchy.
561 */
562 SurfaceControl.Builder makeAnimationLeash();
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200563
564 /**
Jorim Jaggi596a1992017-12-29 14:48:02 +0100565 * @return The parent that should be used for the animation leash.
566 */
567 @Nullable SurfaceControl getAnimationLeashParent();
568
569 /**
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200570 * @return The surface of the object to be animated.
Robert Carrdea7bf42019-04-04 12:02:51 -0700571 * This SurfaceControl must be valid if non-null.
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200572 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100573 @Nullable SurfaceControl getSurfaceControl();
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200574
575 /**
576 * @return The parent of the surface object to be animated.
Robert Carrdea7bf42019-04-04 12:02:51 -0700577 * This SurfaceControl must be valid if non-null.
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200578 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100579 @Nullable SurfaceControl getParentSurfaceControl();
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200580
581 /**
582 * @return The width of the surface to be animated.
583 */
584 int getSurfaceWidth();
585
586 /**
587 * @return The height of the surface to be animated.
588 */
589 int getSurfaceHeight();
Jorim Jaggi6de61012018-03-19 14:53:23 +0100590
591 /**
592 * Gets called when the animation is about to finish and gives the client the opportunity to
593 * defer finishing the animation, i.e. it keeps the leash around until the client calls
594 * {@link #cancelAnimation}.
595 *
596 * @param endDeferFinishCallback The callback to call when defer finishing should be ended.
597 * @return Whether the client would like to defer the animation finish.
598 */
599 default boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
600 return false;
601 }
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200602 }
603}