blob: aa817fd38b251199b35f58b76b8a1a93a6edc655 [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
205 /**
206 * @return The current animation spec if we are running an animation, or {@code null} otherwise.
207 */
208 AnimationAdapter getAnimation() {
209 return mAnimation;
210 }
211
212 /**
213 * Cancels any currently running animation.
214 */
215 void cancelAnimation() {
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100216 cancelAnimation(mAnimatable.getPendingTransaction(), false /* restarting */,
217 true /* forwardCancel */);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200218 mAnimatable.commitPendingTransaction();
219 }
220
221 /**
222 * Sets the layer of the surface.
223 * <p>
224 * When the layer of the surface needs to be adjusted, we need to set it on the leash if the
225 * surface is reparented to the leash. This method takes care of that.
226 */
227 void setLayer(Transaction t, int layer) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100228 t.setLayer(mLeash != null ? mLeash : mAnimatable.getSurfaceControl(), layer);
229 }
230
231 /**
232 * Sets the surface to be relatively layered.
233 *
234 * @see #setLayer
235 */
236 void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
237 t.setRelativeLayer(mLeash != null ? mLeash : mAnimatable.getSurfaceControl(), relativeTo, layer);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200238 }
239
240 /**
241 * Reparents the surface.
242 *
243 * @see #setLayer
244 */
245 void reparent(Transaction t, SurfaceControl newParent) {
Robert Carr10584fa2019-01-14 15:55:19 -0800246 t.reparent(mLeash != null ? mLeash : mAnimatable.getSurfaceControl(), newParent);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200247 }
248
249 /**
250 * @return True if the surface is attached to the leash; false otherwise.
251 */
252 boolean hasLeash() {
253 return mLeash != null;
254 }
255
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100256 void transferAnimation(SurfaceAnimator from) {
257 if (from.mLeash == null) {
258 return;
259 }
260 final SurfaceControl surface = mAnimatable.getSurfaceControl();
Jorim Jaggi596a1992017-12-29 14:48:02 +0100261 final SurfaceControl parent = mAnimatable.getAnimationLeashParent();
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100262 if (surface == null || parent == null) {
263 Slog.w(TAG, "Unable to transfer animation, surface or parent is null");
264 cancelAnimation();
265 return;
266 }
267 endDelayingAnimationStart();
268 final Transaction t = mAnimatable.getPendingTransaction();
269 cancelAnimation(t, true /* restarting */, true /* forwardCancel */);
270 mLeash = from.mLeash;
271 mAnimation = from.mAnimation;
Issei Suzuki8b995df2020-01-08 12:23:04 +0100272 mAnimationType = from.mAnimationType;
Issei Suzuki2f541842020-01-09 20:18:29 +0100273 mAnimationFinishedCallback = from.mAnimationFinishedCallback;
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100274
275 // Cancel source animation, but don't let animation runner cancel the animation.
276 from.cancelAnimation(t, false /* restarting */, false /* forwardCancel */);
Robert Carr10584fa2019-01-14 15:55:19 -0800277 t.reparent(surface, mLeash);
278 t.reparent(mLeash, parent);
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100279 mAnimatable.onAnimationLeashCreated(t, mLeash);
280 mService.mAnimationTransferMap.put(mAnimation, this);
281 }
282
Jorim Jaggic4d29f22018-03-22 16:30:56 +0100283 boolean isAnimationStartDelayed() {
284 return mAnimationStartDelayed;
285 }
286
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100287 /**
288 * Cancels the animation, and resets the leash.
289 *
290 * @param t The transaction to use for all cancelling surface operations.
291 * @param restarting Whether we are restarting the animation.
292 * @param forwardCancel Whether to forward the cancel signal to the adapter executing the
293 * animation. This will be set to false when just transferring an animation
294 * to another animator.
295 */
296 private void cancelAnimation(Transaction t, boolean restarting, boolean forwardCancel) {
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200297 if (DEBUG_ANIM) Slog.i(TAG, "Cancelling animation restarting=" + restarting);
298 final SurfaceControl leash = mLeash;
299 final AnimationAdapter animation = mAnimation;
Issei Suzuki8b995df2020-01-08 12:23:04 +0100300 final @AnimationType int animationType = mAnimationType;
301 final OnAnimationFinishedCallback animationFinishedCallback = mAnimationFinishedCallback;
Robert Carr4a2d3742019-02-11 12:15:38 -0800302 reset(t, false);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200303 if (animation != null) {
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100304 if (!mAnimationStartDelayed && forwardCancel) {
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200305 animation.onAnimationCancelled(leash);
306 }
Issei Suzuki2f541842020-01-09 20:18:29 +0100307 if (!restarting) {
308 if (mStaticAnimationFinishedCallback != null) {
Issei Suzuki8b995df2020-01-08 12:23:04 +0100309 mStaticAnimationFinishedCallback.onAnimationFinished(animationType, animation);
Issei Suzuki2f541842020-01-09 20:18:29 +0100310 }
311 if (animationFinishedCallback != null) {
Issei Suzuki8b995df2020-01-08 12:23:04 +0100312 animationFinishedCallback.onAnimationFinished(animationType, animation);
Issei Suzuki2f541842020-01-09 20:18:29 +0100313 }
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200314 }
315 }
Robert Carr4a2d3742019-02-11 12:15:38 -0800316
317 if (forwardCancel && leash != null) {
318 t.remove(leash);
319 mService.scheduleAnimationLocked();
320 }
321
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200322 if (!restarting) {
323 mAnimationStartDelayed = false;
324 }
325 }
326
Jorim Jaggi980c9de2017-11-17 01:41:37 +0100327 private void reset(Transaction t, boolean destroyLeash) {
Evan Rosky55bddd82020-01-29 13:07:18 -0800328 mService.mAnimationTransferMap.remove(mAnimation);
329 mAnimation = null;
330 mAnimationFinishedCallback = null;
331 mAnimationType = ANIMATION_TYPE_NONE;
332 if (mLeash == null) {
333 return;
334 }
335 SurfaceControl leash = mLeash;
336 mLeash = null;
337 final boolean scheduleAnim = removeLeash(t, mAnimatable, leash, destroyLeash);
338 if (scheduleAnim) {
339 mService.scheduleAnimationLocked();
340 }
341 }
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200342
Evan Rosky55bddd82020-01-29 13:07:18 -0800343 static boolean removeLeash(Transaction t, Animatable animatable, @NonNull SurfaceControl leash,
344 boolean destroy) {
Chavi Weingartenb736e322018-02-23 00:27:54 +0000345 boolean scheduleAnim = false;
Evan Rosky55bddd82020-01-29 13:07:18 -0800346 final SurfaceControl surface = animatable.getSurfaceControl();
347 final SurfaceControl parent = animatable.getParentSurfaceControl();
Chavi Weingartenb736e322018-02-23 00:27:54 +0000348
lumarkf6f34942019-04-29 16:56:50 +0800349 // If the surface was destroyed or the leash is invalid, we don't care to reparent it back.
350 // Note that we also set this variable to true even if the parent isn't valid anymore, in
351 // order to ensure onAnimationLeashLost still gets called in this case.
Evan Rosky55bddd82020-01-29 13:07:18 -0800352 final boolean reparent = surface != null;
lumarkf6f34942019-04-29 16:56:50 +0800353 if (reparent) {
354 if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to original parent: " + parent);
Robert Carr412f3562019-04-11 13:01:31 -0700355 // We shouldn't really need these isValid checks but we do
356 // b/130364451
lumarkf6f34942019-04-29 16:56:50 +0800357 if (surface.isValid() && parent != null && parent.isValid()) {
Robert Carr412f3562019-04-11 13:01:31 -0700358 t.reparent(surface, parent);
359 scheduleAnim = true;
360 }
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200361 }
Evan Rosky55bddd82020-01-29 13:07:18 -0800362 if (destroy) {
363 t.remove(leash);
Chavi Weingartenb736e322018-02-23 00:27:54 +0000364 scheduleAnim = true;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100365 }
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200366
lumarkf6f34942019-04-29 16:56:50 +0800367 if (reparent) {
368 // Make sure to inform the animatable after the surface was reparented (or reparent
369 // wasn't possible, but we still need to invoke the callback)
Evan Rosky55bddd82020-01-29 13:07:18 -0800370 animatable.onAnimationLeashLost(t);
Chavi Weingartenb736e322018-02-23 00:27:54 +0000371 scheduleAnim = true;
372 }
Evan Rosky55bddd82020-01-29 13:07:18 -0800373 return scheduleAnim;
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200374 }
375
Evan Rosky55bddd82020-01-29 13:07:18 -0800376 static SurfaceControl createAnimationLeash(Animatable animatable, SurfaceControl surface,
Winson Chung7e895da2020-02-03 13:28:44 -0800377 Transaction t, @AnimationType int type, int width, int height, int x, int y,
Vishnu Nair5e3e2ea2020-03-16 11:30:34 -0700378 boolean hidden, Supplier<Transaction> transactionFactory) {
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200379 if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to leash");
Evan Rosky55bddd82020-01-29 13:07:18 -0800380 final SurfaceControl.Builder builder = animatable.makeAnimationLeash()
381 .setParent(animatable.getAnimationLeashParent())
Vishnu Nair10a09f52020-03-05 14:40:27 -0800382 .setName(surface + " - animation-leash");
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200383 final SurfaceControl leash = builder.build();
Vishnu Nair5e3e2ea2020-03-16 11:30:34 -0700384 if (!hidden) {
385 // TODO(b/151665759) Defer reparent calls
386 // We want the leash to be visible immediately but we want to set the effects on
387 // the layer. Since the transaction used in this function may be deferred, we apply
388 // another transaction immediately with the correct visibility and effects.
389 // If this doesn't work, you will can see the 2/3 button nav bar flicker during
390 // seamless rotation.
391 transactionFactory.get().unsetColor(leash).show(leash).apply();
392 }
Louis Changb92aa022018-11-16 15:46:50 +0800393 t.setWindowCrop(leash, width, height);
Evan Rosky55bddd82020-01-29 13:07:18 -0800394 t.setPosition(leash, x, y);
chaviw516ef792019-07-26 16:11:55 -0700395 t.show(leash);
chaviw516ef792019-07-26 16:11:55 -0700396 t.setAlpha(leash, hidden ? 0 : 1);
Tiger Huang969c6082019-12-24 20:08:57 +0800397
Robert Carr10584fa2019-01-14 15:55:19 -0800398 t.reparent(surface, leash);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200399 return leash;
400 }
401
Vishnu Nair04ab4392018-01-10 11:00:06 -0800402 /**
403 * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link
Yi Jin6c6e9ca2018-03-20 16:53:35 -0700404 * com.android.server.wm.SurfaceAnimatorProto}.
Vishnu Nair04ab4392018-01-10 11:00:06 -0800405 *
406 * @param proto Stream to write the SurfaceAnimator object to.
407 * @param fieldId Field Id of the SurfaceAnimator as defined in the parent message.
408 * @hide
409 */
Jeffrey Huangcb782852019-12-05 11:28:11 -0800410 void dumpDebug(ProtoOutputStream proto, long fieldId) {
Vishnu Nair04ab4392018-01-10 11:00:06 -0800411 final long token = proto.start(fieldId);
Jorim Jaggif75d1612018-02-27 15:05:21 +0100412 if (mAnimation != null) {
Jeffrey Huangcb782852019-12-05 11:28:11 -0800413 mAnimation.dumpDebug(proto, ANIMATION_ADAPTER);
Jorim Jaggif75d1612018-02-27 15:05:21 +0100414 }
Nataniel Borges023ecb52019-01-16 14:15:43 -0800415 if (mLeash != null) {
Jeffrey Huangcb782852019-12-05 11:28:11 -0800416 mLeash.dumpDebug(proto, LEASH);
Vishnu Nair04ab4392018-01-10 11:00:06 -0800417 }
418 proto.write(ANIMATION_START_DELAYED, mAnimationStartDelayed);
419 proto.end(token);
420 }
421
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200422 void dump(PrintWriter pw, String prefix) {
Jorim Jaggif75d1612018-02-27 15:05:21 +0100423 pw.print(prefix); pw.print("mLeash="); pw.print(mLeash);
424 if (mAnimationStartDelayed) {
425 pw.print(" mAnimationStartDelayed="); pw.println(mAnimationStartDelayed);
426 } else {
427 pw.println();
428 }
429 pw.print(prefix); pw.println("Animation:");
430 if (mAnimation != null) {
431 mAnimation.dump(pw, prefix + " ");
432 } else {
433 pw.print(prefix); pw.println("null");
434 }
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200435 }
436
Issei Suzuki8b995df2020-01-08 12:23:04 +0100437
438 /**
439 * No animation is specified.
440 * @hide
441 */
442 static final int ANIMATION_TYPE_NONE = 0;
443
444 /**
445 * Animation for an app transition.
446 * @hide
447 */
448 static final int ANIMATION_TYPE_APP_TRANSITION = 1;
449
450 /**
451 * Animation for screen rotation.
452 * @hide
453 */
454 static final int ANIMATION_TYPE_SCREEN_ROTATION = 2;
455
456 /**
457 * Animation for dimming.
458 * @hide
459 */
460 static final int ANIMATION_TYPE_DIMMER = 3;
461
462 /**
463 * Animation for recent apps.
464 * @hide
465 */
466 static final int ANIMATION_TYPE_RECENTS = 4;
467
468 /**
469 * Animation for a {@link WindowState} without animating the activity.
470 * @hide
471 */
472 static final int ANIMATION_TYPE_WINDOW_ANIMATION = 5;
473
474 /**
475 * Animation to control insets. This is actually not an animation, but is used to give the
476 * client a leash over the system window causing insets.
477 * @hide
478 */
479 static final int ANIMATION_TYPE_INSETS_CONTROL = 6;
480
481 /**
482 * The type of the animation.
483 * @hide
484 */
485 @IntDef(flag = true, prefix = { "ANIMATION_TYPE_" }, value = {
486 ANIMATION_TYPE_NONE,
487 ANIMATION_TYPE_APP_TRANSITION,
488 ANIMATION_TYPE_SCREEN_ROTATION,
489 ANIMATION_TYPE_DIMMER,
490 ANIMATION_TYPE_RECENTS,
491 ANIMATION_TYPE_WINDOW_ANIMATION,
492 ANIMATION_TYPE_INSETS_CONTROL
493 })
494 @Retention(RetentionPolicy.SOURCE)
495 @interface AnimationType {}
496
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200497 /**
498 * Callback to be passed into {@link AnimationAdapter#startAnimation} to be invoked by the
499 * component that is running the animation when the animation is finished.
500 */
501 interface OnAnimationFinishedCallback {
Issei Suzuki8b995df2020-01-08 12:23:04 +0100502 void onAnimationFinished(@AnimationType int type, AnimationAdapter anim);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200503 }
504
505 /**
506 * Interface to be animated by {@link SurfaceAnimator}.
507 */
508 interface Animatable {
509
510 /**
511 * @return The pending transaction that will be committed in the next frame.
512 */
513 @NonNull Transaction getPendingTransaction();
514
515 /**
516 * Schedules a commit of the pending transaction.
517 */
518 void commitPendingTransaction();
519
520 /**
Evan Rosky55bddd82020-01-29 13:07:18 -0800521 * Called when the animation leash is created. Note that this is also called by
522 * {@link SurfaceFreezer}, so this doesn't mean we're about to start animating.
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200523 *
524 * @param t The transaction to use to apply any necessary changes.
525 * @param leash The leash that was created.
526 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100527 void onAnimationLeashCreated(Transaction t, SurfaceControl leash);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200528
529 /**
Evan Rosky55bddd82020-01-29 13:07:18 -0800530 * Called when the animator is about to start animating the leash.
531 *
532 * @param t The transaction to use to apply any necessary changes.
533 * @param leash The leash that was created.
534 */
535 default void onLeashAnimationStarting(Transaction t, SurfaceControl leash) { }
536
537 /**
lumarkf6f34942019-04-29 16:56:50 +0800538 * Called when the leash is being destroyed, or when the leash is being transferred to
539 * another SurfaceAnimator.
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200540 *
541 * @param t The transaction to use to apply any necessary changes.
542 */
lumarkf6f34942019-04-29 16:56:50 +0800543 void onAnimationLeashLost(Transaction t);
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200544
545 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +0100546 * @return A new surface to be used for the animation leash, inserted at the correct
547 * position in the hierarchy.
548 */
549 SurfaceControl.Builder makeAnimationLeash();
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200550
551 /**
Jorim Jaggi596a1992017-12-29 14:48:02 +0100552 * @return The parent that should be used for the animation leash.
553 */
554 @Nullable SurfaceControl getAnimationLeashParent();
555
556 /**
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200557 * @return The surface of the object to be animated.
Robert Carrdea7bf42019-04-04 12:02:51 -0700558 * This SurfaceControl must be valid if non-null.
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200559 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100560 @Nullable SurfaceControl getSurfaceControl();
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200561
562 /**
563 * @return The parent of the surface object to be animated.
Robert Carrdea7bf42019-04-04 12:02:51 -0700564 * This SurfaceControl must be valid if non-null.
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200565 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100566 @Nullable SurfaceControl getParentSurfaceControl();
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200567
568 /**
569 * @return The width of the surface to be animated.
570 */
571 int getSurfaceWidth();
572
573 /**
574 * @return The height of the surface to be animated.
575 */
576 int getSurfaceHeight();
Jorim Jaggi6de61012018-03-19 14:53:23 +0100577
578 /**
579 * Gets called when the animation is about to finish and gives the client the opportunity to
580 * defer finishing the animation, i.e. it keeps the leash around until the client calls
581 * {@link #cancelAnimation}.
582 *
583 * @param endDeferFinishCallback The callback to call when defer finishing should be ended.
584 * @return Whether the client would like to defer the animation finish.
585 */
586 default boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
587 return false;
588 }
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200589 }
590}