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

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23103198

Change-Id: Ia87a655604393ff5186be3a1958f4b1e5afe0bdf
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Treehugger Robot
2023-05-12 15:42:26 +00:00
committed by Automerger Merge Worker
3 changed files with 41 additions and 5 deletions

View File

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

View File

@@ -158,6 +158,16 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
mAllCallbacks.remove(callback);
// Re-populate the top callback to WM if the removed callback was previously the top one.
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());
}
}

View File

@@ -173,4 +173,25 @@ public class WindowOnBackInvokedDispatcherTest {
waitForIdle();
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);
}
}