Revert^2 "Cancel gestures on launcher destroy"

f0de6cc2cad5e2224bccf60cab31b26468ba0231

Bug: 261816852
Fixes: 244593270
Fixes: 257976590
Fixes: 261504234
Test: FallbackRecentsTest#goToOverviewFromApp and FallbackRecentsTest#goToOverviewFromHome
Change-Id: If49a08fd62b99c9bbc007900b613b83747916f5f
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 3d8ffc4..d3d9a6e 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -50,6 +50,7 @@
 import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.CANCEL_RECENTS_ANIMATION;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.EXPECTING_TASK_APPEARED;
+import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.LAUNCHER_DESTROYED;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.ON_SETTLED_ON_END_TARGET;
 import static com.android.quickstep.util.VibratorWrapper.OVERVIEW_HAPTIC;
 import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
@@ -181,6 +182,7 @@
                     if (mActivity != activity) {
                         return;
                     }
+                    handleActivityDestroyed();
                     mRecentsView = null;
                     mActivity = null;
                 }
@@ -451,6 +453,7 @@
         if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) {
             return false;
         }
+        mStateCallback.resumeCallbacks();
 
         T createdActivity = mActivityInterface.getCreatedActivity();
         if (createdActivity != null) {
@@ -520,6 +523,15 @@
         return true;
     }
 
+    private void handleActivityDestroyed() {
+        ActiveGestureLog.INSTANCE.addLog("Launcher activity destroyed", LAUNCHER_DESTROYED);
+        if (mActivityInterface.shouldCancelGestureOnDestroy()) {
+            onGestureCancelled();
+        } else {
+            mStateCallback.pauseCallbacks();
+        }
+    }
+
     /**
      * Return true if the window should be translated horizontally if the recents view scrolls
      */
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 274b686..22eaa97 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -123,6 +123,14 @@
     public abstract AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
             boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback);
 
+    /**
+     * Returns {@code true} iff an ongoing navigational gesture should be cancelled on activity
+     * destroy. Otherwise, the MultiStateCallbacks will be paused until the activity is recreated.
+     */
+    public boolean shouldCancelGestureOnDestroy() {
+        return true;
+    }
+
     public abstract ActivityInitListener createActivityInitListener(
             Predicate<Boolean> onInitListener);
 
diff --git a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
index ae9fb0b..4cb4665 100644
--- a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
@@ -88,6 +88,11 @@
     }
 
     @Override
+    public boolean shouldCancelGestureOnDestroy() {
+        return false;
+    }
+
+    @Override
     public ActivityInitListener createActivityInitListener(
             Predicate<Boolean> onInitListener) {
         return new ActivityInitListener<>((activity, alreadyOnHome) ->
diff --git a/quickstep/src/com/android/quickstep/MultiStateCallback.java b/quickstep/src/com/android/quickstep/MultiStateCallback.java
index a68bea2..6d767ed 100644
--- a/quickstep/src/com/android/quickstep/MultiStateCallback.java
+++ b/quickstep/src/com/android/quickstep/MultiStateCallback.java
@@ -31,6 +31,7 @@
 
 import java.util.ArrayList;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.StringJoiner;
 import java.util.function.Consumer;
 
@@ -52,6 +53,9 @@
 
     private int mState = 0;
 
+    private boolean mCallbacksPaused = false;
+    private final List<Runnable> mPendingCallbacks = new ArrayList<>();
+
     public MultiStateCallback(String[] stateNames) {
         this(stateNames, stateFlag -> null);
     }
@@ -78,6 +82,24 @@
         }
     }
 
+    /** Pauses callbacks. */
+    public void pauseCallbacks() {
+        mCallbacksPaused = true;
+    }
+
+    /** Immediately queues any callbacks that were pending paused. */
+    public void resumeCallbacks() {
+        if (!mCallbacksPaused) {
+            return;
+        }
+        mCallbacksPaused = false;
+        List<Runnable> queuedCallbacks = new ArrayList<>(mPendingCallbacks);
+        mPendingCallbacks.clear();
+        for (Runnable runnable : queuedCallbacks) {
+            runnable.run();
+        }
+    }
+
     /**
      * Adds the provided state flags to the global state and executes any callbacks as a result.
      */
@@ -99,7 +121,12 @@
             if ((mState & state) == state) {
                 LinkedList<Runnable> callbacks = mCallbacks.valueAt(i);
                 while (!callbacks.isEmpty()) {
-                    callbacks.pollFirst().run();
+                    Runnable cb = callbacks.pollFirst();
+                    if (mCallbacksPaused) {
+                        mPendingCallbacks.add(cb);
+                    } else {
+                        cb.run();
+                    }
                 }
             }
         }
@@ -151,7 +178,11 @@
             if (wasOn != isOn) {
                 ArrayList<Consumer<Boolean>> listeners = mStateChangeListeners.valueAt(i);
                 for (Consumer<Boolean> listener : listeners) {
-                    listener.accept(isOn);
+                    if (mCallbacksPaused) {
+                        mPendingCallbacks.add(() -> listener.accept(isOn));
+                    } else {
+                        listener.accept(isOn);
+                    }
                 }
             }
         }
diff --git a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
index 60065fb..0fdd8b5 100644
--- a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
+++ b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
@@ -37,7 +37,7 @@
         ON_SETTLED_ON_END_TARGET, START_RECENTS_ANIMATION, FINISH_RECENTS_ANIMATION,
         CANCEL_RECENTS_ANIMATION, SET_ON_PAGE_TRANSITION_END_CALLBACK, CANCEL_CURRENT_ANIMATION,
         CLEANUP_SCREENSHOT, SCROLLER_ANIMATION_ABORTED, TASK_APPEARED, EXPECTING_TASK_APPEARED,
-        FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER,
+        FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER, LAUNCHER_DESTROYED,
 
         /**
          * These GestureEvents are specifically associated to state flags that get set in
@@ -162,6 +162,13 @@
                                         + "before/without setting end target to new task",
                                 writer);
                         break;
+                    case LAUNCHER_DESTROYED:
+                        errorDetected |= printErrorIfTrue(
+                                true,
+                                prefix,
+                                /* errorMessage= */ "Launcher destroyed mid-gesture",
+                                writer);
+                        break;
                     case STATE_GESTURE_COMPLETED:
                         errorDetected |= printErrorIfTrue(
                                 !encounteredEvents.contains(GestureEvent.MOTION_UP),
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index 47bef7b..a4dbf6a 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -168,7 +168,6 @@
 
     // b/143488140
     //@NavigationModeSwitch
-    @Ignore
     @Test
     public void goToOverviewFromHome() {
         mDevice.pressHome();
@@ -216,7 +215,6 @@
 
     // b/143488140
     //@NavigationModeSwitch
-    @Ignore
     @Test
     public void testOverview() {
         startAppFast(getAppPackageName());