Defer nav handle action until after the recents transition is complete
Bug: 303078360
Test: Force delay in finishing recents transition and verify with bug steps
Change-Id: I2021cc291204261de56ef9c912d8b5935059c7fb
Signed-off-by: Winson Chung <winsonc@google.com>
diff --git a/quickstep/src/com/android/quickstep/InputConsumer.java b/quickstep/src/com/android/quickstep/InputConsumer.java
index 23def14..f898e2f 100644
--- a/quickstep/src/com/android/quickstep/InputConsumer.java
+++ b/quickstep/src/com/android/quickstep/InputConsumer.java
@@ -126,4 +126,14 @@
}
return name.toString();
}
+
+ /**
+ * Returns an input consumer of the given class type, or null if none is found.
+ */
+ default <T extends InputConsumer> T getInputConsumerOfClass(Class<T> c) {
+ if (getClass().equals(c)) {
+ return c.cast(this);
+ }
+ return null;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
index 3d332c2..5d26ec0 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
@@ -115,7 +115,8 @@
/* extras= */ 0,
/* gestureEvent= */ ON_START_RECENTS_ANIMATION);
notifyAnimationCanceled();
- animationController.finish(false /* toHome */, false /* sendUserLeaveHint */);
+ animationController.finish(false /* toHome */, false /* sendUserLeaveHint */,
+ null /* finishCb */);
return;
}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
index 8972dc8..341e18c 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
@@ -21,6 +21,7 @@
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.FINISH_RECENTS_ANIMATION;
import android.content.Context;
+import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.view.IRecentsAnimationController;
@@ -32,6 +33,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
+import com.android.internal.os.IResultReceiver;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.RunnableList;
import com.android.quickstep.util.ActiveGestureErrorDetector;
@@ -172,12 +174,19 @@
mFinishTargetIsLauncher = toRecents;
mOnFinishedListener.accept(this);
Runnable finishCb = () -> {
- mController.finish(toRecents, sendUserLeaveHint);
+ mController.finish(toRecents, sendUserLeaveHint, new IResultReceiver.Stub() {
+ @Override
+ public void send(int i, Bundle bundle) throws RemoteException {
+ ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation-callback");
+ MAIN_EXECUTOR.execute(() -> {
+ mPendingFinishCallbacks.executeAllAndDestroy();
+ });
+ }
+ });
InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH);
InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME);
InteractionJankMonitorWrapper.end(
InteractionJankMonitorWrapper.CUJ_APP_SWIPE_TO_RECENTS);
- MAIN_EXECUTOR.execute(mPendingFinishCallbacks::executeAllAndDestroy);
};
if (forceFinish) {
finishCb.run();
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index f5a7ecc..f1b31f7 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -119,7 +119,8 @@
}
}
// But force-finish it anyways
- finishRunningRecentsAnimation(false /* toHome */, true /* forceFinish */);
+ finishRunningRecentsAnimation(false /* toHome */, true /* forceFinish */,
+ null /* forceFinishCb */);
if (mCallbacks != null) {
// If mCallbacks still != null, that means we are getting this startRecentsAnimation()
@@ -325,19 +326,20 @@
* Finishes the running recents animation.
*/
public void finishRunningRecentsAnimation(boolean toHome) {
- finishRunningRecentsAnimation(toHome, false /* forceFinish */);
+ finishRunningRecentsAnimation(toHome, false /* forceFinish */, null /* forceFinishCb */);
}
/**
* Finishes the running recents animation.
* @param forceFinish will synchronously finish the controller
*/
- public void finishRunningRecentsAnimation(boolean toHome, boolean forceFinish) {
+ public void finishRunningRecentsAnimation(boolean toHome, boolean forceFinish,
+ Runnable forceFinishCb) {
if (mController != null) {
ActiveGestureLog.INSTANCE.addLog(
/* event= */ "finishRunningRecentsAnimation", toHome);
if (forceFinish) {
- mController.finishController(toHome, null, false /* sendUserLeaveHint */,
+ mController.finishController(toHome, forceFinishCb, false /* sendUserLeaveHint */,
true /* forceFinish */);
} else {
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), toHome
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
index 63771f0..5557639 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
@@ -48,6 +48,14 @@
*/
protected abstract String getDelegatorName();
+ @Override
+ public <T extends InputConsumer> T getInputConsumerOfClass(Class<T> c) {
+ if (getClass().equals(c)) {
+ return c.cast(this);
+ }
+ return mDelegate.getInputConsumerOfClass(c);
+ }
+
protected void setActive(MotionEvent ev) {
ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(getDelegatorName())
.append(" became active"));
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
index addcfb8..fc3f3ab 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
@@ -52,9 +52,15 @@
if (isInArea(motionEvent.getRawX())) {
Runnable longPressRunnable = mNavHandleLongPressHandler.getLongPressRunnable();
if (longPressRunnable != null) {
- setActive(motionEvent);
-
- MAIN_EXECUTOR.post(longPressRunnable);
+ OtherActivityInputConsumer oaic = getInputConsumerOfClass(
+ OtherActivityInputConsumer.class);
+ if (oaic != null) {
+ oaic.setForceFinishRecentsTransitionCallback(longPressRunnable);
+ setActive(motionEvent);
+ } else {
+ setActive(motionEvent);
+ MAIN_EXECUTOR.post(longPressRunnable);
+ }
}
}
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 7e61167..28c00eb 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -125,6 +125,9 @@
// Might be displacement in X or Y, depending on the direction we are swiping from the nav bar.
private float mStartDisplacement;
+ // The callback called upon finishing the recents transition if it was force-canceled
+ private Runnable mForceFinishRecentsTransitionCallback;
+
public OtherActivityInputConsumer(Context base, RecentsAnimationDeviceState deviceState,
TaskAnimationManager taskAnimationManager, GestureState gestureState,
boolean isDeferredDownTarget, Consumer<OtherActivityInputConsumer> onCompleteCallback,
@@ -444,7 +447,7 @@
// animateToProgress so we have to manually finish here. In the case of
// ACTION_CANCEL, someone else may be doing something so finish synchronously.
mTaskAnimationManager.finishRunningRecentsAnimation(false /* toHome */,
- isCanceled /* forceFinish */);
+ isCanceled /* forceFinish */, mForceFinishRecentsTransitionCallback);
} else {
// The animation hasn't started yet, so insert a replacement handler into the
// callbacks which immediately finishes the animation after it starts.
@@ -513,6 +516,14 @@
}
/**
+ * Sets a callback to be called when the recents transition is force-canceled by another input
+ * consumer being made active.
+ */
+ public void setForceFinishRecentsTransitionCallback(Runnable r) {
+ mForceFinishRecentsTransitionCallback = r;
+ }
+
+ /**
* A listener which just finishes the animation immediately after starting. Replaces
* AbsSwipeUpHandler if the gesture itself finishes before the animation even starts.
*/