Fix overview cmd launching wrong task in landscape

Previously we used the bottom most view in recents list to launch the
recent task when the user pressed the overview button. However, if
the user is in landscape and scrolls up so the bottom view is not
attached, pressing overview command will launch whatever the bottom task
is visually which is incorrect. Instead, we get the actual task from the
model to launch and only use the "view => app" animation if the view for
that task is attached. If it isn't, we use the basic animation.

Bug: 130735711
Test: Go to landscape, scroll up, hit command, launches correct task
Change-Id: Idff88054443259e917bbec1b47d78efbb1544283
diff --git a/go/quickstep/src/com/android/quickstep/TaskActionController.java b/go/quickstep/src/com/android/quickstep/TaskActionController.java
index 09e2367..0e921c0 100644
--- a/go/quickstep/src/com/android/quickstep/TaskActionController.java
+++ b/go/quickstep/src/com/android/quickstep/TaskActionController.java
@@ -20,6 +20,8 @@
 import android.app.ActivityOptions;
 import android.view.View;
 
+import androidx.annotation.NonNull;
+
 import com.android.quickstep.views.TaskItemView;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -39,11 +41,11 @@
     }
 
     /**
-     * Launch the task associated with the task holder, animating into the app.
+     * Launch the task associated with the task holder, animating into the app from the task view.
      *
      * @param viewHolder the task view holder to launch
      */
-    public void launchTask(TaskHolder viewHolder) {
+    public void launchTaskFromView(@NonNull TaskHolder viewHolder) {
         if (!viewHolder.getTask().isPresent()) {
             return;
         }
@@ -61,6 +63,17 @@
     }
 
     /**
+     * Launch the task directly with a basic animation.
+     *
+     * @param task the task to launch
+     */
+    public void launchTask(@NonNull Task task) {
+        ActivityOptions opts = ActivityOptions.makeBasic();
+        ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(task.key, opts,
+                null /* resultCallback */, null /* resultCallbackHandler */);
+    }
+
+    /**
      * Removes the task holder and the task, updating the model and the view.
      *
      * @param viewHolder the task view holder to remove
diff --git a/go/quickstep/src/com/android/quickstep/TaskAdapter.java b/go/quickstep/src/com/android/quickstep/TaskAdapter.java
index 4f2b422..509bf29 100644
--- a/go/quickstep/src/com/android/quickstep/TaskAdapter.java
+++ b/go/quickstep/src/com/android/quickstep/TaskAdapter.java
@@ -83,7 +83,8 @@
                 TaskItemView itemView = (TaskItemView) LayoutInflater.from(parent.getContext())
                         .inflate(R.layout.task_item_view, parent, false);
                 TaskHolder taskHolder = new TaskHolder(itemView);
-                itemView.setOnClickListener(view -> mTaskActionController.launchTask(taskHolder));
+                itemView.setOnClickListener(
+                        view -> mTaskActionController.launchTaskFromView(taskHolder));
                 return taskHolder;
             case ITEM_TYPE_CLEAR_ALL:
                 View clearView = LayoutInflater.from(parent.getContext())
diff --git a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
index b8c482d..cf6eb6d 100644
--- a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
+++ b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
@@ -59,6 +59,8 @@
 import com.android.systemui.shared.recents.model.Task;
 
 import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
 import java.util.Optional;
 
 /**
@@ -263,23 +265,33 @@
      * the app. In that case, we launch the next most recent.
      */
     public void handleOverviewCommand() {
-        // TODO(130735711): Need to address case where most recent task is off screen/unattached.
-        ArrayList<TaskItemView> taskViews = getTaskViews();
-        int taskViewsSize = taskViews.size();
-        if (taskViewsSize <= 1) {
+        List<Task> tasks = mTaskLoader.getCurrentTaskList();
+        int tasksSize = tasks.size();
+        if (tasksSize == 0) {
             // Do nothing
             return;
         }
-        TaskHolder taskToLaunch;
-        if (mTransitionedFromApp && taskViewsSize > 1) {
+        Task taskToLaunch;
+        if (mTransitionedFromApp && tasksSize > 1) {
             // Launch the next most recent app
-            TaskItemView itemView = taskViews.get(1);
-            taskToLaunch = (TaskHolder) mTaskRecyclerView.getChildViewHolder(itemView);
+            taskToLaunch = tasks.get(1);
         } else {
             // Launch the most recent app
-            TaskItemView itemView = taskViews.get(0);
-            taskToLaunch = (TaskHolder) mTaskRecyclerView.getChildViewHolder(itemView);
+            taskToLaunch = tasks.get(0);
         }
+
+        // See if view for this task is attached, and if so, animate launch from that view.
+        ArrayList<TaskItemView> itemViews = getTaskViews();
+        for (int i = 0, size = itemViews.size(); i < size; i++) {
+            TaskItemView taskView = itemViews.get(i);
+            TaskHolder holder = (TaskHolder) mTaskRecyclerView.getChildViewHolder(taskView);
+            if (Objects.equals(holder.getTask(), Optional.of(taskToLaunch))) {
+                mTaskActionController.launchTaskFromView(holder);
+                return;
+            }
+        }
+
+        // Otherwise, just use a basic launch animation.
         mTaskActionController.launchTask(taskToLaunch);
     }