From a79b8851f71134277a1ab1fc5631d4d1a0bef044 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Tue, 26 May 2020 21:25:15 +0200 Subject: [PATCH] InsetsController: Add missing onWindowInsetsAnimationEnd when cancelling Fixes a few issues around cancelling insets animations: - dispatch the onEnd callback when the animation gets cancelled - When using the CancellationSignal, we need to properly cancel the animation, and not just the controller - otherwise we never actually remove it from mRunningAnimations. - Now that cancellation dispatches to apps, make sure they do not restart a different animation of the same type we just cancelled Bug: 156740834 Test: atest WindowInsetsAnimationControllerTests Change-Id: I4c36470a816ff8e3b92cd03090b8e947a2234f13 --- core/java/android/view/InsetsController.java | 35 +++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 758062f41428b..b370b14d198b1 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -69,6 +69,8 @@ import java.util.function.BiFunction; */ public class InsetsController implements WindowInsetsController, InsetsAnimationControlCallbacks { + private int mTypesBeingCancelled; + public interface Host { Handler getHandler(); @@ -778,6 +780,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @AnimationType int animationType, @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation, boolean useInsetsAnimationThread) { + if ((types & mTypesBeingCancelled) != 0) { + throw new IllegalStateException("Cannot start a new insets animation of " + + Type.toString(types) + + " while an existing " + Type.toString(mTypesBeingCancelled) + + " is being cancelled."); + } if (types == 0) { // nothing to animate. listener.onCancelled(null); @@ -827,7 +835,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation animationType); mRunningAnimations.add(new RunningAnimation(runner, animationType)); if (cancellationSignal != null) { - cancellationSignal.setOnCancelListener(runner::cancel); + cancellationSignal.setOnCancelListener(() -> { + cancelAnimation(runner, true /* invokeCallback */); + }); } if (layoutInsetsDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN) { showDirectly(types); @@ -915,14 +925,20 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } private void cancelExistingControllers(@InsetsType int types) { - for (int i = mRunningAnimations.size() - 1; i >= 0; i--) { - InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner; - if ((control.getTypes() & types) != 0) { - cancelAnimation(control, true /* invokeCallback */); + final int originalmTypesBeingCancelled = mTypesBeingCancelled; + mTypesBeingCancelled |= types; + try { + for (int i = mRunningAnimations.size() - 1; i >= 0; i--) { + InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner; + if ((control.getTypes() & types) != 0) { + cancelAnimation(control, true /* invokeCallback */); + } } - } - if ((types & ime()) != 0) { - abortPendingImeControlRequest(); + if ((types & ime()) != 0) { + abortPendingImeControlRequest(); + } + } finally { + mTypesBeingCancelled = originalmTypesBeingCancelled; } } @@ -977,6 +993,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mHost.notifyInsetsChanged(); } } + if (invokeCallback && runningAnimation.startDispatched) { + dispatchAnimationEnd(runningAnimation.runner.getAnimation()); + } break; } }