Fix blocking issues re. window transitions and quick scrub

- Clean up the consumer when starting quickscrub/switch in addition to
  motion up
- Defer invalidating the handler until after quickscrub ends
- Ensure that we always finish the remote animation

Bug: 67957962
Bug: 70180755

Change-Id: Id5af5dc9917638f1dfb8e4a04c358aadb19fd67a
diff --git a/quickstep/src/com/android/quickstep/BaseSwipeInteractionHandler.java b/quickstep/src/com/android/quickstep/BaseSwipeInteractionHandler.java
index 21b032b..b3ebd77 100644
--- a/quickstep/src/com/android/quickstep/BaseSwipeInteractionHandler.java
+++ b/quickstep/src/com/android/quickstep/BaseSwipeInteractionHandler.java
@@ -38,8 +38,10 @@
 
     public abstract void updateInteractionType(@InteractionType int interactionType);
 
+    @WorkerThread
     public abstract void onQuickScrubEnd();
 
+    @WorkerThread
     public abstract void onQuickScrubProgress(float progress);
 
     @WorkerThread
diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
index 61d4790..d8f7aaf 100644
--- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
+++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
@@ -157,13 +157,7 @@
                             startTouchTrackingForScreenshotAnimation();
                         }
 
-                        // Notify the handler that the gesture has actually started
-                        mInteractionHandler.onGestureStarted();
-
-                        // Notify the system that we have started tracking the event
-                        if (mISystemUiProxy != null) {
-                            executeSafely(mISystemUiProxy::onRecentsAnimationStarted);
-                        }
+                        notifyGestureStarted();
                     }
                 } else {
                     // Move
@@ -182,6 +176,16 @@
         }
     }
 
+    private void notifyGestureStarted() {
+        // Notify the handler that the gesture has actually started
+        mInteractionHandler.onGestureStarted();
+
+        // Notify the system that we have started tracking the event
+        if (mISystemUiProxy != null) {
+            executeSafely(mISystemUiProxy::onRecentsAnimationStarted);
+        }
+    }
+
     private boolean isNavBarOnRight() {
         return mDisplayRotation == Surface.ROTATION_90 && mStableInsets.right > 0;
     }
@@ -263,7 +267,7 @@
         handler.setLauncherOnDrawCallback(() -> {
             drawWaitLock.countDown();
             if (handler == mInteractionHandler) {
-                switchToMainConsumer();
+                switchToMainChoreographer();
             }
         });
         handler.initWhenReady(mMainThreadExecutor);
@@ -346,6 +350,8 @@
 
     @Override
     public void updateTouchTracking(int interactionType) {
+        notifyGestureStarted();
+
         mMainThreadExecutor.execute(() -> {
             if (mInteractionHandler != null) {
                 mInteractionHandler.updateInteractionType(interactionType);
@@ -378,7 +384,7 @@
 
     public void onTouchTrackingComplete() { }
 
-    public void switchToMainConsumer() { }
+    public void switchToMainChoreographer() { }
 
     @Override
     public void preProcessMotionEvent(MotionEvent ev) {
diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java
index 3e65ffe..61684e0 100644
--- a/quickstep/src/com/android/quickstep/QuickScrubController.java
+++ b/quickstep/src/com/android/quickstep/QuickScrubController.java
@@ -62,6 +62,7 @@
             int snapDuration = Math.abs(page - mRecentsView.getPageNearestToCenterOfScreen())
                     * QUICKSCRUB_END_SNAP_DURATION_PER_PAGE;
             mRecentsView.snapToPage(page, snapDuration);
+            // TODO: Fix this to actually wait until page-settle
             mRecentsView.postDelayed(() -> {
                 if (page < mRecentsView.getFirstTaskIndex()) {
                     mRecentsView.getPageAt(page).performClick();
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 6f3a8ff..5e89644 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -190,7 +190,7 @@
                 mHomeIntent, mISystemUiProxy, mMainThreadExecutor) {
 
             @Override
-            public void switchToMainConsumer() {
+            public void switchToMainChoreographer() {
                 if (mCurrentConsumer == this) {
                     mEventQueue.setInterimChoreographer(null);
                 }
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 6082aea..17f0482 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -142,6 +142,7 @@
 
     private @InteractionType int mInteractionType = INTERACTION_NORMAL;
     private boolean mStartedQuickScrubFromHome;
+    private boolean mDeferredQuickScrubEnd;
 
     private final RecentsAnimationWrapper mRecentsAnimationWrapper = new RecentsAnimationWrapper();
     private Matrix mTmpMatrix = new Matrix();
@@ -352,6 +353,7 @@
 
     private void updateUiForQuickScrub() {
         mStartedQuickScrubFromHome = mWasLauncherAlreadyVisible;
+        mDeferredQuickScrubEnd = false;
         mQuickScrubController = mRecentsView.getQuickScrubController();
         mQuickScrubController.onQuickScrubStart(mStartedQuickScrubFromHome);
         animateToProgress(1f, MAX_SWIPE_DURATION);
@@ -547,7 +549,11 @@
     }
 
     public void reset() {
-        setStateOnUiThread(STATE_HANDLER_INVALIDATED);
+        if (mInteractionType != INTERACTION_QUICK_SCRUB) {
+            // Only invalidate the handler if we are not quick scrubbing, otherwise, it will be
+            // invalidated after the quick scrub ends
+            setStateOnUiThread(STATE_HANDLER_INVALIDATED);
+        }
     }
 
     private void invalidateHandler() {
@@ -573,6 +579,22 @@
     }
 
     private void switchToScreenshot() {
+        synchronized (mRecentsAnimationWrapper) {
+            if (mRecentsAnimationWrapper.controller != null) {
+                TransactionCompat transaction = new TransactionCompat();
+                for (RemoteAnimationTargetCompat app : mRecentsAnimationWrapper.targets) {
+                    if (app.mode == MODE_CLOSING) {
+                        // Update the screenshot of the task
+                        final ThumbnailData thumbnail =
+                                mRecentsAnimationWrapper.controller.screenshotTask(app.taskId);
+                        mRecentsView.updateThumbnail(app.taskId, thumbnail);
+                    }
+                }
+                transaction.apply();
+            }
+        }
+        mRecentsAnimationWrapper.finish(true /* toHome */);
+
         if (mInteractionType == INTERACTION_QUICK_SWITCH) {
             for (int i = mRecentsView.getFirstTaskIndex(); i < mRecentsView.getPageCount(); i++) {
                 TaskView taskView = (TaskView) mRecentsView.getPageAt(i);
@@ -585,24 +607,12 @@
             }
         } else if (mInteractionType == INTERACTION_QUICK_SCRUB) {
             if (mQuickScrubController != null) {
-                mQuickScrubController.snapToPageForCurrentQuickScrubSection();
-            }
-        } else {
-            synchronized (mRecentsAnimationWrapper) {
-                if (mRecentsAnimationWrapper.controller != null) {
-                    TransactionCompat transaction = new TransactionCompat();
-                    for (RemoteAnimationTargetCompat app : mRecentsAnimationWrapper.targets) {
-                        if (app.mode == MODE_CLOSING) {
-                            // Update the screenshot of the task
-                            final ThumbnailData thumbnail =
-                                    mRecentsAnimationWrapper.controller.screenshotTask(app.taskId);
-                            mRecentsView.updateThumbnail(app.taskId, thumbnail);
-                        }
-                    }
-                    transaction.apply();
+                if (mDeferredQuickScrubEnd) {
+                    onQuickScrubEnd();
+                } else {
+                    mQuickScrubController.snapToPageForCurrentQuickScrubSection();
                 }
             }
-            mRecentsAnimationWrapper.finish(true /* toHome */);
         }
     }
 
@@ -610,7 +620,6 @@
         // Re apply state in case we did something funky during the transition.
         mLauncher.getStateManager().reapplyState();
 
-
         // Animate ui the first icon.
         View currentRecentsPage = mRecentsView.getPageAt(mRecentsView.getCurrentPage());
         if (currentRecentsPage instanceof TaskView) {
@@ -619,11 +628,24 @@
     }
 
     public void onQuickScrubEnd() {
+        if ((mStateCallback.getState() & STATE_SCALED_CONTROLLER_RECENTS) == 0) {
+            // If we are still animating into recents, then defer until that has run to end
+            // quick scrub since we need to finish the window animation before launching the next
+            // task
+            mDeferredQuickScrubEnd = true;
+            return;
+        }
+
         if (mQuickScrubController != null) {
             mQuickScrubController.onQuickScrubEnd();
         } else {
             // TODO:
         }
+
+        // Normally this is handled in reset(), but since we are still scrubbing after the
+        // transition into recents, we need to defer the handler invalidation for quick scrub until
+        // after the gesture ends
+        setStateOnUiThread(STATE_HANDLER_INVALIDATED);
     }
 
     public void onQuickScrubProgress(float progress) {