Finally remove `task1` and `task2` from `GroupTask`

See go/refactor-group-task for details. This is the final CL
in this refactor, where `task1` and `task2` are finally removed,
and `DesktopTask` is allowed to have empty tasks.

Bug: 388593902
Test: m
Flag: EXEMPT pure refactor with no behavior change.
Change-Id: I8af39b58138f11030981311efc2e95a77cef125b
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index c7f33e9..fd327c2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -26,8 +26,6 @@
 import static com.android.launcher3.config.FeatureFlags.enableTaskbarPinning;
 import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
 
-import static java.util.function.Predicate.not;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Canvas;
@@ -420,7 +418,7 @@
                 .filter(Objects::nonNull)
                 .toArray(ItemInfo[]::new);
         // TODO(b/343289567 and b/316004172): support app pairs and desktop mode.
-        recentTasks = recentTasks.stream().filter(not(GroupTask::supportsMultipleTasks)).toList();
+        recentTasks = recentTasks.stream().filter(it -> it instanceof SingleTask).toList();
 
         if (taskbarRecentsLayoutTransition()) {
             updateItemsWithLayoutTransition(hotseatItemInfos, recentTasks);
@@ -671,7 +669,7 @@
             // Replace any Recent views with the appropriate type if it's not already that type.
             final int expectedLayoutResId;
             boolean isCollection = false;
-            if (task.supportsMultipleTasks()) {
+            if (!(task instanceof SingleTask)) {
                 if (task.taskViewType == TaskViewType.DESKTOP) {
                     // TODO(b/316004172): use Desktop tile layout.
                     expectedLayoutResId = -1;
diff --git a/quickstep/src/com/android/quickstep/util/DesktopTask.kt b/quickstep/src/com/android/quickstep/util/DesktopTask.kt
index 5d61dd4..53ea022 100644
--- a/quickstep/src/com/android/quickstep/util/DesktopTask.kt
+++ b/quickstep/src/com/android/quickstep/util/DesktopTask.kt
@@ -20,14 +20,9 @@
 
 /**
  * A [Task] container that can contain N number of tasks that are part of the desktop in recent
- * tasks list.
+ * tasks list. Note that desktops can be empty with no tasks in them.
  */
-class DesktopTask(override val tasks: List<Task>) :
-    GroupTask(tasks[0], task2 = null, TaskViewType.DESKTOP) {
-
-    override fun containsTask(taskId: Int) = tasks.any { it.key.id == taskId }
-
-    override fun supportsMultipleTasks() = true
+class DesktopTask(tasks: List<Task>) : GroupTask(tasks, TaskViewType.DESKTOP) {
 
     override fun copy() = DesktopTask(tasks)
 
diff --git a/quickstep/src/com/android/quickstep/util/GroupTask.kt b/quickstep/src/com/android/quickstep/util/GroupTask.kt
index 9ab9633..49c37dc 100644
--- a/quickstep/src/com/android/quickstep/util/GroupTask.kt
+++ b/quickstep/src/com/android/quickstep/util/GroupTask.kt
@@ -15,7 +15,6 @@
  */
 package com.android.quickstep.util
 
-import androidx.annotation.VisibleForTesting
 import com.android.launcher3.util.SplitConfigurationOptions
 import com.android.quickstep.views.TaskViewType
 import com.android.systemui.shared.recents.model.Task
@@ -25,20 +24,8 @@
  * An abstract class for creating [Task] containers that can be [SingleTask]s, [SplitTask]s, or
  * [DesktopTask]s in the recent tasks list.
  */
-abstract class GroupTask
-@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
-constructor(
-    @Deprecated("Prefer using `getTasks()` instead") @JvmField val task1: Task,
-    @Deprecated("Prefer using `getTasks()` instead") @JvmField val task2: Task?,
-    @JvmField val taskViewType: TaskViewType,
-) {
-    protected constructor(
-        task1: Task,
-        task2: Task?,
-    ) : this(task1, task2, if (task2 != null) TaskViewType.GROUPED else TaskViewType.SINGLE)
-
-    open fun containsTask(taskId: Int) =
-        task1.key.id == taskId || (task2 != null && task2.key.id == taskId)
+abstract class GroupTask(val tasks: List<Task>, @JvmField val taskViewType: TaskViewType) {
+    fun containsTask(taskId: Int) = tasks.any { it.key.id == taskId }
 
     /**
      * Returns true if a task in this group has a package name that matches the given `packageName`.
@@ -54,18 +41,9 @@
 
     fun isEmpty() = tasks.isEmpty()
 
-    /** Returns whether this task supports multiple tasks or not. */
-    open fun supportsMultipleTasks() = taskViewType == TaskViewType.GROUPED
-
-    /** Returns a List of all the Tasks in this GroupTask */
-    open val tasks: List<Task>
-        get() = listOfNotNull(task1, task2)
-
     /** Creates a copy of this instance */
     abstract fun copy(): GroupTask
 
-    override fun toString() = "type=$taskViewType task1=$task1 task2=$task2"
-
     override fun equals(o: Any?): Boolean {
         if (this === o) return true
         if (o !is GroupTask) return false
@@ -76,14 +54,14 @@
 }
 
 /** A [Task] container that must contain exactly one task in the recent tasks list. */
-class SingleTask(task: Task) : GroupTask(task, task2 = null, TaskViewType.SINGLE) {
+class SingleTask(task: Task) : GroupTask(listOf(task), TaskViewType.SINGLE) {
 
     val task: Task
-        get() = task1
+        get() = tasks[0]
 
-    override fun copy() = SingleTask(task1)
+    override fun copy() = SingleTask(task)
 
-    override fun toString() = "type=$taskViewType task=$task1"
+    override fun toString() = "type=$taskViewType task=$task"
 
     override fun equals(o: Any?): Boolean {
         if (this === o) return true
@@ -97,17 +75,18 @@
  * in the recent tasks list.
  */
 class SplitTask(task1: Task, task2: Task, val splitBounds: SplitConfigurationOptions.SplitBounds) :
-    GroupTask(task1, task2, TaskViewType.GROUPED) {
+    GroupTask(listOf(task1, task2), TaskViewType.GROUPED) {
 
     val topLeftTask: Task
-        get() = if (splitBounds.leftTopTaskId == task1.key.id) task1!! else task2!!
+        get() = if (splitBounds.leftTopTaskId == tasks[0].key.id) tasks[0] else tasks[1]
 
     val bottomRightTask: Task
-        get() = if (topLeftTask == task1) task2!! else task1!!
+        get() = if (topLeftTask == tasks[0]) tasks[1] else tasks[0]
 
-    override fun copy() = SplitTask(task1, task2!!, splitBounds)
+    override fun copy() = SplitTask(tasks[0], tasks[1], splitBounds)
 
-    override fun toString() = "type=$taskViewType task1=$task1 task2=$task2"
+    override fun toString() =
+        "type=$taskViewType topLeftTask=$topLeftTask bottomRightTask=$bottomRightTask"
 
     override fun equals(o: Any?): Boolean {
         if (this === o) return true