Fix quick switching to any task that already appeared

Previously we did this for the last task that appeared, but didn't
take into account cases where multiple tasks had appeared during
the same gesture state. We handle that now.

Test:
- Quick switch to delayed task A, start new gesture, return to the
  first app after onTaskAppeared(A)
- Quick switch to delayed task A, start new gesture, wait for
  onTaskAppeared(A), then switch to delayed task B, start new
  gesture, wait for onTaskAppeared(B), and switch back to A
- Quick switch to delayed task A, start new gesture, wait for
  onTaskAppeared(A), then switch to delayed task B, start new
  gesture, wait for onTaskAppeared(B), and switch back to A and
  quickly back to original app (before settling on A)
Ensure task starts/resumes and is interactable in all cases.

Bug: 158588954
Change-Id: I647a6d015baa1d9b6d613e6c0e584589f35da54a
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
index b5fb31a..56af2e0 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
@@ -144,13 +144,14 @@
                 TaskView nextTask = mRecentsView.getTaskView(taskId);
                 if (nextTask != null) {
                     mGestureState.updateLastStartedTaskId(taskId);
+                    boolean hasTaskPreviouslyAppeared = mGestureState.getPreviouslyAppearedTaskIds()
+                            .contains(taskId);
                     nextTask.launchTask(false /* animate */, true /* freezeTaskList */,
                             success -> {
                                 resultCallback.accept(success);
                                 if (success) {
-                                    if (mRecentsView.indexOfChild(nextTask)
-                                            == getLastAppearedTaskIndex()) {
-                                        onRestartLastAppearedTask();
+                                    if (hasTaskPreviouslyAppeared) {
+                                        onRestartPreviouslyAppearedTask();
                                     }
                                 } else {
                                     mActivityInterface.onLaunchTaskFailed();
@@ -171,7 +172,7 @@
      * start A again to ensure it stays on top.
      */
     @CallSuper
-    protected void onRestartLastAppearedTask() {
+    protected void onRestartPreviouslyAppearedTask() {
         // Finish the controller here, since we won't get onTaskAppeared() for a task that already
         // appeared.
         if (mRecentsAnimationController != null) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
index f2438b6..7b3a787 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
@@ -1097,8 +1097,8 @@
     }
 
     @Override
-    protected void onRestartLastAppearedTask() {
-        super.onRestartLastAppearedTask();
+    protected void onRestartPreviouslyAppearedTask() {
+        super.onRestartPreviouslyAppearedTask();
         reset();
     }
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index 226c818..be69a36 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -540,6 +540,8 @@
         if (mTaskAnimationManager.isRecentsAnimationRunning()) {
             gestureState.updateRunningTask(mGestureState.getRunningTask());
             gestureState.updateLastStartedTaskId(mGestureState.getLastStartedTaskId());
+            gestureState.updatePreviouslyAppearedTaskIds(
+                    mGestureState.getPreviouslyAppearedTaskIds());
         } else {
             gestureState.updateRunningTask(TraceHelper.whitelistIpcs("getRunningTask.0",
                     () -> mAM.getRunningTask(false /* filterOnlyVisibleRecents */)));
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index 188072a..00b5eb9 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -30,6 +30,8 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
 
 /**
  * Manages the state for an active system gesture, listens for events from the system and Launcher,
@@ -128,6 +130,7 @@
     private ActivityManager.RunningTaskInfo mRunningTask;
     private GestureEndTarget mEndTarget;
     private RemoteAnimationTargetCompat mLastAppearedTaskTarget;
+    private Set<Integer> mPreviouslyAppearedTaskIds = new HashSet<>();
     private int mLastStartedTaskId = -1;
 
     public GestureState(OverviewComponentObserver componentObserver, int gestureId) {
@@ -147,6 +150,7 @@
         mRunningTask = other.mRunningTask;
         mEndTarget = other.mEndTarget;
         mLastAppearedTaskTarget = other.mLastAppearedTaskTarget;
+        mPreviouslyAppearedTaskIds = other.mPreviouslyAppearedTaskIds;
         mLastStartedTaskId = other.mLastStartedTaskId;
     }
 
@@ -234,6 +238,9 @@
      */
     public void updateLastAppearedTaskTarget(RemoteAnimationTargetCompat lastAppearedTaskTarget) {
         mLastAppearedTaskTarget = lastAppearedTaskTarget;
+        if (lastAppearedTaskTarget != null) {
+            mPreviouslyAppearedTaskIds.add(lastAppearedTaskTarget.taskId);
+        }
     }
 
     /**
@@ -243,6 +250,14 @@
         return mLastAppearedTaskTarget != null ? mLastAppearedTaskTarget.taskId : -1;
     }
 
+    public void updatePreviouslyAppearedTaskIds(Set<Integer> previouslyAppearedTaskIds) {
+        mPreviouslyAppearedTaskIds = previouslyAppearedTaskIds;
+    }
+
+    public Set<Integer> getPreviouslyAppearedTaskIds() {
+        return mPreviouslyAppearedTaskIds;
+    }
+
     /**
      * Updates the last task that we started via startActivityFromRecents() during this gesture.
      */