diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 3d95f65df8425..0a2810fb3b7a6 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -70,6 +70,8 @@ import java.util.function.BiFunction; */ public class InsetsController implements WindowInsetsController, InsetsAnimationControlCallbacks { + private int mTypesBeingCancelled; + public interface Host { Handler getHandler(); @@ -809,6 +811,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); @@ -868,7 +876,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (DEBUG) Log.d(TAG, "Animation added to runner. useInsetsAnimationThread: " + useInsetsAnimationThread); if (cancellationSignal != null) { - cancellationSignal.setOnCancelListener(runner::cancel); + cancellationSignal.setOnCancelListener(() -> { + cancelAnimation(runner, true /* invokeCallback */); + }); } if (layoutInsetsDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN) { showDirectly(types); @@ -963,14 +973,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; } } @@ -1029,6 +1045,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mHost.notifyInsetsChanged(); } } + if (invokeCallback && runningAnimation.startDispatched) { + dispatchAnimationEnd(runningAnimation.runner.getAnimation()); + } break; } }