From 29721a13196391e79c90dd0cb0f5de591697d46b Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Mon, 21 Jun 2021 21:34:51 +0200 Subject: [PATCH] Insets Animations: Always dispatch onEnd when cancelled Previously, we only dispatched onEnd if onStart was already dispatched. However, some animations might get cancelled after onPrepare but before onStart. In that case, it is rather tricky for apps to actually cancel the animation. Now we always dispatch onEnd if onPrepare has been dispatched already. Fixes: 177983907 Test: atest WindowInsetsAnimationControllerTests Change-Id: I3fa142110bd5593679f87561c138ed3318034fca --- core/java/android/view/InsetsController.java | 2 +- core/java/android/view/ViewRootInsetsControllerHost.java | 4 ++++ core/java/android/view/WindowInsetsAnimation.java | 7 +++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 8080883c2b3e0..145607ada4f4a 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -1265,7 +1265,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } stateChanged |= getSourceConsumer(types.valueAt(j)).notifyAnimationFinished(); } - if (invokeCallback && runningAnimation.startDispatched) { + if (invokeCallback) { dispatchAnimationEnd(runningAnimation.runner.getAnimation()); } break; diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java index d8cd6056de904..27821fd6608dc 100644 --- a/core/java/android/view/ViewRootInsetsControllerHost.java +++ b/core/java/android/view/ViewRootInsetsControllerHost.java @@ -110,6 +110,10 @@ public class ViewRootInsetsControllerHost implements InsetsController.Host { @Override public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) { if (DEBUG) Log.d(TAG, "windowInsetsAnimation ended"); + if (mViewRoot.mView == null) { + // The view has already detached from window. + return; + } mViewRoot.mView.dispatchWindowInsetsAnimationEnd(animation); } diff --git a/core/java/android/view/WindowInsetsAnimation.java b/core/java/android/view/WindowInsetsAnimation.java index ab5b5ba51a6e1..6576eea404965 100644 --- a/core/java/android/view/WindowInsetsAnimation.java +++ b/core/java/android/view/WindowInsetsAnimation.java @@ -360,6 +360,13 @@ public final class WindowInsetsAnimation { * finished, and then revert to the starting state of the animation in the first * {@link #onProgress} callback by using post-layout view properties like {@link View#setX} * and related methods. + * + *

Note that the animation might be cancelled before {@link #onStart} is dispatched. On + * {@link android.os.Build.VERSION_CODES#S S} and later, {@link #onEnd} is immediately + * dispatched without an {@link #onStart} in that case. + * On {@link android.os.Build.VERSION_CODES#R R}, no callbacks are dispatched after + * {@code #onPrepare} for such an animation. + * *

* Note: If the animation is application controlled by using * {@link WindowInsetsController#controlWindowInsetsAnimation}, the end state of the