Merge "Call onBackCancelled() when an active callback is removed from the WindowOnBackInvokedDispatcher" into udc-dev

This commit is contained in:
Treehugger Robot
2023-05-12 14:54:41 +00:00
committed by Android (Google) Code Review
3 changed files with 41 additions and 5 deletions

View File

@@ -43,7 +43,7 @@ public class BackProgressAnimator {
private ProgressCallback mCallback; private ProgressCallback mCallback;
private float mProgress = 0; private float mProgress = 0;
private BackMotionEvent mLastBackEvent; private BackMotionEvent mLastBackEvent;
private boolean mStarted = false; private boolean mBackAnimationInProgress = false;
private void setProgress(float progress) { private void setProgress(float progress) {
mProgress = progress; mProgress = progress;
@@ -87,7 +87,7 @@ public class BackProgressAnimator {
* @param event the {@link BackMotionEvent} containing the latest target progress. * @param event the {@link BackMotionEvent} containing the latest target progress.
*/ */
public void onBackProgressed(BackMotionEvent event) { public void onBackProgressed(BackMotionEvent event) {
if (!mStarted) { if (!mBackAnimationInProgress) {
return; return;
} }
mLastBackEvent = event; mLastBackEvent = event;
@@ -108,7 +108,7 @@ public class BackProgressAnimator {
reset(); reset();
mLastBackEvent = event; mLastBackEvent = event;
mCallback = callback; mCallback = callback;
mStarted = true; mBackAnimationInProgress = true;
} }
/** /**
@@ -122,7 +122,7 @@ public class BackProgressAnimator {
// Should never happen. // Should never happen.
mSpring.cancel(); mSpring.cancel();
} }
mStarted = false; mBackAnimationInProgress = false;
mLastBackEvent = null; mLastBackEvent = null;
mCallback = null; mCallback = null;
mProgress = 0; mProgress = 0;
@@ -149,8 +149,13 @@ public class BackProgressAnimator {
mSpring.animateToFinalPosition(0); mSpring.animateToFinalPosition(0);
} }
/** Returns true if the back animation is in progress. */
boolean isBackAnimationInProgress() {
return mBackAnimationInProgress;
}
private void updateProgressValue(float progress) { private void updateProgressValue(float progress) {
if (mLastBackEvent == null || mCallback == null || !mStarted) { if (mLastBackEvent == null || mCallback == null || !mBackAnimationInProgress) {
return; return;
} }
mCallback.onProgressUpdate( mCallback.onProgressUpdate(

View File

@@ -158,6 +158,16 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
mAllCallbacks.remove(callback); mAllCallbacks.remove(callback);
// Re-populate the top callback to WM if the removed callback was previously the top one. // Re-populate the top callback to WM if the removed callback was previously the top one.
if (previousTopCallback == callback) { if (previousTopCallback == callback) {
// We should call onBackCancelled() when an active callback is removed from dispatcher.
if (mProgressAnimator.isBackAnimationInProgress()
&& callback instanceof OnBackAnimationCallback) {
// The ProgressAnimator will handle the new topCallback, so we don't want to call
// onBackCancelled() on it. We call immediately the callback instead.
OnBackAnimationCallback animatedCallback = (OnBackAnimationCallback) callback;
animatedCallback.onBackCancelled();
Log.d(TAG, "The callback was removed while a back animation was in progress, "
+ "an onBackCancelled() was dispatched.");
}
setTopOnBackInvokedCallback(getTopCallback()); setTopOnBackInvokedCallback(getTopCallback());
} }
} }

View File

@@ -173,4 +173,25 @@ public class WindowOnBackInvokedDispatcherTest {
waitForIdle(); waitForIdle();
verify(mCallback2).onBackStarted(any(BackEvent.class)); verify(mCallback2).onBackStarted(any(BackEvent.class));
} }
@Test
public void onUnregisterWhileBackInProgress_callOnBackCancelled() throws RemoteException {
ArgumentCaptor<OnBackInvokedCallbackInfo> captor =
ArgumentCaptor.forClass(OnBackInvokedCallbackInfo.class);
mDispatcher.registerOnBackInvokedCallback(
OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCallback1);
verify(mWindowSession).setOnBackInvokedCallbackInfo(
Mockito.eq(mWindow),
captor.capture());
IOnBackInvokedCallback iOnBackInvokedCallback = captor.getValue().getCallback();
iOnBackInvokedCallback.onBackStarted(mBackEvent);
waitForIdle();
verify(mCallback1).onBackStarted(any(BackEvent.class));
mDispatcher.unregisterOnBackInvokedCallback(mCallback1);
verify(mCallback1).onBackCancelled();
verifyNoMoreInteractions(mCallback1);
}
} }