diff options
| author | 2021-09-17 17:07:04 +0000 | |
|---|---|---|
| committer | 2021-09-21 16:25:40 +0200 | |
| commit | cab1bbffa59ebbd7b2039f8775047c62f0c68e5f (patch) | |
| tree | ace65304cff03339462d19af339ec774a6b53631 | |
| parent | ea2130f4990a1a9e598b13c7102cf9434579cccf (diff) | |
Show color layer in task animations when requested
Additionally wrap AnimationAdapter to inject custom onCancelledCallback
which should run when the animation is cancelled.
We can't rely on the onAnimationFinished callback since that doesn't run
when the animation adapter is canceled by the surface animator and it is still
running (i.e. restarted due to a new animation being requested before
the old one finished).
Since the finishedCallbacks are not always called when an animation
adapter is cancelled this cancel callback serves as a way to inject and run custom clean
up code for the animation adapter, which in our case is used to clear
the background color of an animation.
Test: atest FlickerTests:TaskTransitionTest
Bug: 199507257
Change-Id: Ic603b2711c19299f01271131062765255451310a
3 files changed, 80 insertions, 16 deletions
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java index 3c6c23b08091..c7bf8ecfe949 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimator.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java @@ -59,11 +59,30 @@ class SurfaceAnimator { @VisibleForTesting final Animatable mAnimatable; private final OnAnimationFinishedCallback mInnerAnimationFinishedCallback; + + /** + * Static callback to run on all animations started through this SurfaceAnimator + * when an animation on a Surface is finished or cancelled without restart. + */ @VisibleForTesting @Nullable final OnAnimationFinishedCallback mStaticAnimationFinishedCallback; + + /** + * Callback unique to each animation (i.e. AnimationAdapter). To be run when an animation on a + * Surface is finished or cancelled without restart. + */ + @Nullable + private OnAnimationFinishedCallback mSurfaceAnimationFinishedCallback; + + /** + * The callback is triggered after the SurfaceAnimator sends a cancel call to the underlying + * AnimationAdapter. + * NOTE: Must be called wherever we call onAnimationCancelled on mAnimation. + */ @Nullable - private OnAnimationFinishedCallback mAnimationFinishedCallback; + private Runnable mAnimationCancelledCallback; + private boolean mAnimationStartDelayed; /** @@ -100,7 +119,7 @@ class SurfaceAnimator { return; } final OnAnimationFinishedCallback animationFinishCallback = - mAnimationFinishedCallback; + mSurfaceAnimationFinishedCallback; reset(mAnimatable.getPendingTransaction(), true /* destroyLeash */); if (staticAnimationFinishedCallback != null) { staticAnimationFinishedCallback.onAnimationFinished(type, anim); @@ -130,15 +149,19 @@ class SurfaceAnimator { * This is important as it will start with the leash hidden or visible before * handing it to the component that is responsible to run the animation. * @param animationFinishedCallback The callback being triggered when the animation finishes. + * @param animationCancelledCallback The callback is triggered after the SurfaceAnimator sends a + * cancel call to the underlying AnimationAdapter. */ void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, @AnimationType int type, @Nullable OnAnimationFinishedCallback animationFinishedCallback, + @Nullable Runnable animationCancelledCallback, @Nullable SurfaceFreezer freezer) { cancelAnimation(t, true /* restarting */, true /* forwardCancel */); mAnimation = anim; mAnimationType = type; - mAnimationFinishedCallback = animationFinishedCallback; + mSurfaceAnimationFinishedCallback = animationFinishedCallback; + mAnimationCancelledCallback = animationCancelledCallback; final SurfaceControl surface = mAnimatable.getSurfaceControl(); if (surface == null) { Slog.w(TAG, "Unable to start animation, surface is null or no children."); @@ -161,14 +184,9 @@ class SurfaceAnimator { } void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, - @AnimationType int type, - @Nullable OnAnimationFinishedCallback animationFinishedCallback) { - startAnimation(t, anim, hidden, type, animationFinishedCallback, null /* freezer */); - } - - void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, @AnimationType int type) { - startAnimation(t, anim, hidden, type, null /* animationFinishedCallback */); + startAnimation(t, anim, hidden, type, null /* animationFinishedCallback */, + null /* animationCancelledCallback */, null /* freezer */); } /** @@ -278,7 +296,8 @@ class SurfaceAnimator { mLeash = from.mLeash; mAnimation = from.mAnimation; mAnimationType = from.mAnimationType; - mAnimationFinishedCallback = from.mAnimationFinishedCallback; + mSurfaceAnimationFinishedCallback = from.mSurfaceAnimationFinishedCallback; + mAnimationCancelledCallback = from.mAnimationCancelledCallback; // Cancel source animation, but don't let animation runner cancel the animation. from.cancelAnimation(t, false /* restarting */, false /* forwardCancel */); @@ -306,11 +325,16 @@ class SurfaceAnimator { final SurfaceControl leash = mLeash; final AnimationAdapter animation = mAnimation; final @AnimationType int animationType = mAnimationType; - final OnAnimationFinishedCallback animationFinishedCallback = mAnimationFinishedCallback; + final OnAnimationFinishedCallback animationFinishedCallback = + mSurfaceAnimationFinishedCallback; + final Runnable animationCancelledCallback = mAnimationCancelledCallback; reset(t, false); if (animation != null) { if (!mAnimationStartDelayed && forwardCancel) { animation.onAnimationCancelled(leash); + if (animationCancelledCallback != null) { + animationCancelledCallback.run(); + } } if (!restarting) { if (mStaticAnimationFinishedCallback != null) { @@ -335,7 +359,7 @@ class SurfaceAnimator { private void reset(Transaction t, boolean destroyLeash) { mService.mAnimationTransferMap.remove(mAnimation); mAnimation = null; - mAnimationFinishedCallback = null; + mSurfaceAnimationFinishedCallback = null; mAnimationType = ANIMATION_TYPE_NONE; if (mLeash == null) { return; diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 70464fc4e0ea..ee4c629189dc 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -2210,6 +2210,11 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { } @Override + TaskDisplayArea getTaskDisplayArea() { + return this; + } + + @Override boolean isTaskDisplayArea() { return true; } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index b1c7e196b70c..d9a8883e299e 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -850,6 +850,12 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< return parent != null ? parent.getRootDisplayArea() : null; } + @Nullable + TaskDisplayArea getTaskDisplayArea() { + WindowContainer parent = getParent(); + return parent != null ? parent.getTaskDisplayArea() : null; + } + boolean isAttached() { return getDisplayArea() != null; } @@ -2495,10 +2501,13 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< * some point but the meaning is too weird to work for all containers. * @param type The type of animation defined as {@link AnimationType}. * @param animationFinishedCallback The callback being triggered when the animation finishes. + * @param animationCancelledCallback The callback is triggered after the SurfaceAnimator sends a + * cancel call to the underlying AnimationAdapter. */ void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, @AnimationType int type, - @Nullable OnAnimationFinishedCallback animationFinishedCallback) { + @Nullable OnAnimationFinishedCallback animationFinishedCallback, + @Nullable Runnable animationCancelledCallback) { if (DEBUG_ANIM) { Slog.v(TAG, "Starting animation on " + this + ": type=" + type + ", anim=" + anim); } @@ -2506,7 +2515,14 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< // TODO: This should use isVisible() but because isVisible has a really weird meaning at // the moment this doesn't work for all animatable window containers. mSurfaceAnimator.startAnimation(t, anim, hidden, type, animationFinishedCallback, - mSurfaceFreezer); + animationCancelledCallback, mSurfaceFreezer); + } + + void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, + @AnimationType int type, + @Nullable OnAnimationFinishedCallback animationFinishedCallback) { + startAnimation(t, anim, hidden, type, animationFinishedCallback, + null /* adapterAnimationCancelledCallback */); } void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, @@ -2714,8 +2730,27 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< if (sources != null) { mSurfaceAnimationSources.addAll(sources); } + + TaskDisplayArea taskDisplayArea = getTaskDisplayArea(); + int backgroundColor = adapter.getBackgroundColor(); + + boolean shouldSetBackgroundColor = taskDisplayArea != null && backgroundColor != 0; + + if (shouldSetBackgroundColor) { + taskDisplayArea.setBackgroundColor(backgroundColor); + } + + Runnable clearColorBackground = () -> { + if (shouldSetBackgroundColor) { + taskDisplayArea.clearBackgroundColor(); + } + }; + startAnimation(getPendingTransaction(), adapter, !isVisible(), - ANIMATION_TYPE_APP_TRANSITION); + ANIMATION_TYPE_APP_TRANSITION, + (type, anim) -> clearColorBackground.run(), + clearColorBackground); + if (adapter.getShowWallpaper()) { getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; } |