Gracefully handle some edge cases in quick scrub

- Switch to normal overview if task fails to launch in onQuickScrubEnd()
- Stop auto-advancing if recents isn't visible
- Wait until transition to quick scrub completes before launching

Bug: 77521777
Bug: 78557737
Change-Id: I5206c0d3c52bf792f52cf3e7adcf03f8a2de18bb
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index 88cd376..8a6abb2 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -263,7 +263,7 @@
         @Override
         public RecentsView getVisibleRecentsView() {
             Launcher launcher = getVisibleLaucher();
-            return launcher != null && launcher.isInState(OVERVIEW)
+            return launcher != null && launcher.getStateManager().getState().overviewUi
                     ? launcher.getOverviewPanel() : null;
         }
 
diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java
index ea9d009..7bb9877 100644
--- a/quickstep/src/com/android/quickstep/QuickScrubController.java
+++ b/quickstep/src/com/android/quickstep/QuickScrubController.java
@@ -16,6 +16,7 @@
 
 package com.android.quickstep;
 
+import android.util.Log;
 import android.view.HapticFeedbackConstants;
 
 import com.android.launcher3.Alarm;
@@ -45,6 +46,7 @@
             0.05f, 0.35f, 0.65f, 0.95f
     };
 
+    private static final String TAG = "QuickScrubController";
     private static final boolean ENABLE_AUTO_ADVANCE = true;
     private static final long AUTO_ADVANCE_DELAY = 500;
     private static final int QUICKSCRUB_SNAP_DURATION_PER_PAGE = 325;
@@ -58,6 +60,8 @@
     private int mQuickScrubSection;
     private boolean mStartedFromHome;
     private boolean mFinishedTransitionToQuickScrub;
+    private Runnable mOnFinishedTransitionToQuickScrubRunnable;
+    private ActivityControlHelper mActivityControlHelper;
 
     public QuickScrubController(BaseActivity activity, RecentsView recentsView) {
         mActivity = activity;
@@ -68,11 +72,13 @@
         }
     }
 
-    public void onQuickScrubStart(boolean startingFromHome) {
+    public void onQuickScrubStart(boolean startingFromHome, ActivityControlHelper controlHelper) {
         mInQuickScrub = true;
         mStartedFromHome = startingFromHome;
         mQuickScrubSection = 0;
         mFinishedTransitionToQuickScrub = false;
+        mOnFinishedTransitionToQuickScrubRunnable = null;
+        mActivityControlHelper = controlHelper;
 
         snapToNextTaskIfAvailable();
         mActivity.getUserEventDispatcher().resetActionDurationMillis();
@@ -85,13 +91,18 @@
         }
         int page = mRecentsView.getNextPage();
         Runnable launchTaskRunnable = () -> {
-            TaskView taskView = ((TaskView) mRecentsView.getPageAt(page));
+            TaskView taskView = mRecentsView.getPageAt(page);
             if (taskView != null) {
-                taskView.launchTask(true);
+                taskView.launchTask(true, (result) -> {
+                    if (!result) {
+                        taskView.notifyTaskLaunchFailed(TAG);
+                        breakOutOfQuickScrub();
+                    }
+                }, taskView.getHandler());
             } else {
-                // Break out of quick scrub so user can interact with launcher.
-                mActivity.onBackPressed();
+                breakOutOfQuickScrub();
             }
+            mActivityControlHelper = null;
         };
         int snapDuration = Math.abs(page - mRecentsView.getPageNearestToCenterOfScreen())
                 * QUICKSCRUB_END_SNAP_DURATION_PER_PAGE;
@@ -100,13 +111,27 @@
             mRecentsView.setNextPageSwitchRunnable(launchTaskRunnable);
         } else {
             // No page move needed, just launch it
-            launchTaskRunnable.run();
+            if (mFinishedTransitionToQuickScrub) {
+                launchTaskRunnable.run();
+            } else {
+                mOnFinishedTransitionToQuickScrubRunnable = launchTaskRunnable;
+            }
         }
         mActivity.getUserEventDispatcher().logActionOnControl(Touch.DRAGDROP,
                 ControlType.QUICK_SCRUB_BUTTON, null, mStartedFromHome ?
                         ContainerType.WORKSPACE : ContainerType.APP);
     }
 
+    /**
+     * Attempts to go to normal overview or back to home, so UI doesn't prevent user interaction.
+     */
+    private void breakOutOfQuickScrub() {
+        if (mRecentsView.getChildCount() == 0 || mActivityControlHelper == null
+                || !mActivityControlHelper.switchToRecentsIfVisible()) {
+            mActivity.onBackPressed();
+        }
+    }
+
     public void onQuickScrubProgress(float progress) {
         int quickScrubSection = 0;
         for (float threshold : QUICK_SCRUB_THRESHOLDS) {
@@ -135,6 +160,10 @@
 
     public void onFinishedTransitionToQuickScrub() {
         mFinishedTransitionToQuickScrub = true;
+        if (mOnFinishedTransitionToQuickScrubRunnable != null) {
+            mOnFinishedTransitionToQuickScrubRunnable.run();
+            mOnFinishedTransitionToQuickScrubRunnable = null;
+        }
     }
 
     public void snapToNextTaskIfAvailable() {
@@ -166,6 +195,12 @@
     @Override
     public void onAlarm(Alarm alarm) {
         int currPage = mRecentsView.getNextPage();
+        boolean recentsVisible = mActivityControlHelper != null
+                && mActivityControlHelper.getVisibleRecentsView() != null;
+        if (!recentsVisible) {
+            Log.w(TAG, "Failed to auto advance; recents not visible");
+            return;
+        }
         if (mQuickScrubSection == QUICK_SCRUB_THRESHOLDS.length
                 && currPage < mRecentsView.getPageCount() - 1) {
             goToPageWithHaptic(currPage + 1);
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 25649fa..c9afcb5 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -21,9 +21,7 @@
 import static android.view.MotionEvent.ACTION_POINTER_DOWN;
 import static android.view.MotionEvent.ACTION_POINTER_UP;
 import static android.view.MotionEvent.ACTION_UP;
-
-import static com.android.systemui.shared.system.ActivityManagerWrapper
-        .CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
+import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
 import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
 
 import android.annotation.TargetApi;
@@ -348,8 +346,8 @@
                 mStartPending = true;
 
                 Runnable action = () -> {
-                    mQuickScrubController.onQuickScrubStart(
-                            mActivityHelper.onQuickInteractionStart(mActivity, true));
+                    mQuickScrubController.onQuickScrubStart(mActivityHelper.onQuickInteractionStart(
+                            mActivity, true), mActivityHelper);
                     mQuickScrubController.onQuickScrubProgress(mLastProgress);
                     mStartPending = false;
 
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index ec50e67..027f2e9 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -64,7 +64,6 @@
 import com.android.quickstep.ActivityControlHelper.LayoutListener;
 import com.android.quickstep.TouchConsumer.InteractionType;
 import com.android.quickstep.util.ClipAnimationHelper;
-import com.android.quickstep.util.RemoteAnimationProvider;
 import com.android.quickstep.util.RemoteAnimationTargetSet;
 import com.android.quickstep.util.SysuiEventLogger;
 import com.android.quickstep.views.RecentsView;
@@ -767,7 +766,7 @@
         }
 
         mActivityControlHelper.onQuickInteractionStart(mActivity, false);
-        mQuickScrubController.onQuickScrubStart(false);
+        mQuickScrubController.onQuickScrubStart(false, mActivityControlHelper);
 
         // Inform the last progress in case we skipped before.
         mQuickScrubController.onQuickScrubProgress(mCurrentQuickScrubProgress);