Pass back split bounds and meta info with GroupedTaskInfo

* Compute and save a StagedSplitBounds object for every
pair to determine it's position, size, divider, etc.
* Moved GroupTask to Launcher
* Moved StagedSplitBounds from launcher to wm/shell
because sharing is caring.

Bug: 203006080
Change-Id: I8513e027f8c9606fbed1283013eafea2cf905f3f
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
index 836a6f6..7cf3baf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
@@ -41,10 +41,13 @@
 import com.android.wm.shell.common.annotations.ExternalThread;
 import com.android.wm.shell.common.annotations.ShellMainThread;
 import com.android.wm.shell.util.GroupedRecentTaskInfo;
+import com.android.wm.shell.util.StagedSplitBounds;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Manages the recent task list from the system, caching it as necessary.
@@ -62,6 +65,13 @@
     // Mapping of split task ids, mappings are symmetrical (ie. if t1 is the taskid of a task in a
     // pair, then mSplitTasks[t1] = t2, and mSplitTasks[t2] = t1)
     private final SparseIntArray mSplitTasks = new SparseIntArray();
+    /**
+     * Maps taskId to {@link StagedSplitBounds} for both taskIDs.
+     * Meaning there will be two taskId integers mapping to the same object.
+     * If there's any ordering to the pairing than we can probably just get away with only one
+     * taskID mapping to it, leaving both for consistency with {@link #mSplitTasks} for now.
+     */
+    private final Map<Integer, StagedSplitBounds> mTaskSplitBoundsMap = new HashMap<>();
 
     /**
      * Creates {@link RecentTasksController}, returns {@code null} if the feature is not
@@ -97,15 +107,20 @@
     /**
      * Adds a split pair. This call does not validate the taskIds, only that they are not the same.
      */
-    public void addSplitPair(int taskId1, int taskId2) {
+    public void addSplitPair(int taskId1, int taskId2, StagedSplitBounds splitBounds) {
         if (taskId1 == taskId2) {
             return;
         }
         // Remove any previous pairs
         removeSplitPair(taskId1);
         removeSplitPair(taskId2);
+        mTaskSplitBoundsMap.remove(taskId1);
+        mTaskSplitBoundsMap.remove(taskId2);
+
         mSplitTasks.put(taskId1, taskId2);
         mSplitTasks.put(taskId2, taskId1);
+        mTaskSplitBoundsMap.put(taskId1, splitBounds);
+        mTaskSplitBoundsMap.put(taskId2, splitBounds);
     }
 
     /**
@@ -116,6 +131,8 @@
         if (pairedTaskId != INVALID_TASK_ID) {
             mSplitTasks.delete(taskId);
             mSplitTasks.delete(pairedTaskId);
+            mTaskSplitBoundsMap.remove(taskId);
+            mTaskSplitBoundsMap.remove(pairedTaskId);
         }
     }
 
@@ -203,7 +220,8 @@
             if (pairedTaskId != INVALID_TASK_ID) {
                 final ActivityManager.RecentTaskInfo pairedTaskInfo = rawMapping.get(pairedTaskId);
                 rawMapping.remove(pairedTaskId);
-                recentTasks.add(new GroupedRecentTaskInfo(taskInfo, pairedTaskInfo));
+                recentTasks.add(new GroupedRecentTaskInfo(taskInfo, pairedTaskInfo,
+                        mTaskSplitBoundsMap.get(pairedTaskId)));
             } else {
                 recentTasks.add(new GroupedRecentTaskInfo(taskInfo));
             }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 3c35e6a..95886c8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -96,6 +96,7 @@
 import com.android.wm.shell.recents.RecentTasksController;
 import com.android.wm.shell.splitscreen.SplitScreenController.ExitReason;
 import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.util.StagedSplitBounds;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -696,11 +697,25 @@
         }
 
         mRecentTasks.ifPresent(recentTasks -> {
+            Rect topLeftBounds = mSplitLayout.getBounds1();
+            Rect bottomRightBounds = mSplitLayout.getBounds2();
             int mainStageTopTaskId = mMainStage.getTopVisibleChildTaskId();
             int sideStageTopTaskId = mSideStage.getTopVisibleChildTaskId();
+            boolean sideStageTopLeft = mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT;
+            int leftTopTaskId;
+            int rightBottomTaskId;
+            if (sideStageTopLeft) {
+                leftTopTaskId = sideStageTopTaskId;
+                rightBottomTaskId = mainStageTopTaskId;
+            } else {
+                leftTopTaskId = mainStageTopTaskId;
+                rightBottomTaskId = sideStageTopTaskId;
+            }
+            StagedSplitBounds splitBounds = new StagedSplitBounds(topLeftBounds, bottomRightBounds,
+                    leftTopTaskId, rightBottomTaskId);
             if (mainStageTopTaskId != INVALID_TASK_ID && sideStageTopTaskId != INVALID_TASK_ID) {
                 // Update the pair for the top tasks
-                recentTasks.addSplitPair(mainStageTopTaskId, sideStageTopTaskId);
+                recentTasks.addSplitPair(mainStageTopTaskId, sideStageTopTaskId, splitBounds);
             }
         });
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/GroupedRecentTaskInfo.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/GroupedRecentTaskInfo.java
index 0331ba1..603d05d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/GroupedRecentTaskInfo.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/GroupedRecentTaskInfo.java
@@ -30,25 +30,34 @@
 public class GroupedRecentTaskInfo implements Parcelable {
     public @NonNull ActivityManager.RecentTaskInfo mTaskInfo1;
     public @Nullable ActivityManager.RecentTaskInfo mTaskInfo2;
+    public @Nullable StagedSplitBounds mStagedSplitBounds;
 
     public GroupedRecentTaskInfo(@NonNull ActivityManager.RecentTaskInfo task1) {
-        this(task1, null);
+        this(task1, null, null);
     }
 
     public GroupedRecentTaskInfo(@NonNull ActivityManager.RecentTaskInfo task1,
-            @Nullable ActivityManager.RecentTaskInfo task2) {
+            @Nullable ActivityManager.RecentTaskInfo task2,
+            @Nullable StagedSplitBounds stagedSplitBounds) {
         mTaskInfo1 = task1;
         mTaskInfo2 = task2;
+        mStagedSplitBounds = stagedSplitBounds;
     }
 
     GroupedRecentTaskInfo(Parcel parcel) {
         mTaskInfo1 = parcel.readTypedObject(ActivityManager.RecentTaskInfo.CREATOR);
         mTaskInfo2 = parcel.readTypedObject(ActivityManager.RecentTaskInfo.CREATOR);
+        mStagedSplitBounds = parcel.readTypedObject(StagedSplitBounds.CREATOR);
     }
 
     @Override
     public String toString() {
-        return "Task1: " + getTaskInfo(mTaskInfo1) + ", Task2: " + getTaskInfo(mTaskInfo2);
+        String taskString = "Task1: " + getTaskInfo(mTaskInfo1)
+                + ", Task2: " + getTaskInfo(mTaskInfo2);
+        if (mStagedSplitBounds != null) {
+            taskString += ", SplitBounds: " + mStagedSplitBounds.toString();
+        }
+        return taskString;
     }
 
     private String getTaskInfo(ActivityManager.RecentTaskInfo taskInfo) {
@@ -67,6 +76,7 @@
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeTypedObject(mTaskInfo1, flags);
         parcel.writeTypedObject(mTaskInfo2, flags);
+        parcel.writeTypedObject(mStagedSplitBounds, flags);
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/StagedSplitBounds.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/StagedSplitBounds.java
new file mode 100644
index 0000000..aadf792
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/StagedSplitBounds.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.wm.shell.util;
+
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Container of various information needed to display split screen
+ * tasks/leashes/etc in Launcher
+ */
+public class StagedSplitBounds implements Parcelable {
+    public final Rect leftTopBounds;
+    public final Rect rightBottomBounds;
+    /** This rect represents the actual gap between the two apps */
+    public final Rect visualDividerBounds;
+    // This class is orientation-agnostic, so we compute both for later use
+    public final float topTaskPercent;
+    public final float leftTaskPercent;
+    /**
+     * If {@code true}, that means at the time of creation of this object, the
+     * split-screened apps were vertically stacked. This is useful in scenarios like
+     * rotation where the bounds won't change, but this variable can indicate what orientation
+     * the bounds were originally in
+     */
+    public final boolean appsStackedVertically;
+    public final int leftTopTaskId;
+    public final int rightBottomTaskId;
+
+    public StagedSplitBounds(Rect leftTopBounds, Rect rightBottomBounds,
+            int leftTopTaskId, int rightBottomTaskId) {
+        this.leftTopBounds = leftTopBounds;
+        this.rightBottomBounds = rightBottomBounds;
+        this.leftTopTaskId = leftTopTaskId;
+        this.rightBottomTaskId = rightBottomTaskId;
+
+        if (rightBottomBounds.top > leftTopBounds.top) {
+            // vertical apps, horizontal divider
+            this.visualDividerBounds = new Rect(leftTopBounds.left, leftTopBounds.bottom,
+                    leftTopBounds.right, rightBottomBounds.top);
+            appsStackedVertically = true;
+        } else {
+            // horizontal apps, vertical divider
+            this.visualDividerBounds = new Rect(leftTopBounds.right, leftTopBounds.top,
+                    rightBottomBounds.left, leftTopBounds.bottom);
+            appsStackedVertically = false;
+        }
+
+        leftTaskPercent = this.leftTopBounds.width() / (float) rightBottomBounds.right;
+        topTaskPercent = this.leftTopBounds.height() / (float) rightBottomBounds.bottom;
+    }
+
+    public StagedSplitBounds(Parcel parcel) {
+        leftTopBounds = parcel.readTypedObject(Rect.CREATOR);
+        rightBottomBounds = parcel.readTypedObject(Rect.CREATOR);
+        visualDividerBounds = parcel.readTypedObject(Rect.CREATOR);
+        topTaskPercent = parcel.readFloat();
+        leftTaskPercent = parcel.readFloat();
+        appsStackedVertically = parcel.readBoolean();
+        leftTopTaskId = parcel.readInt();
+        rightBottomTaskId = parcel.readInt();
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeTypedObject(leftTopBounds, flags);
+        parcel.writeTypedObject(rightBottomBounds, flags);
+        parcel.writeTypedObject(visualDividerBounds, flags);
+        parcel.writeFloat(topTaskPercent);
+        parcel.writeFloat(leftTaskPercent);
+        parcel.writeBoolean(appsStackedVertically);
+        parcel.writeInt(leftTopTaskId);
+        parcel.writeInt(rightBottomTaskId);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public String toString() {
+        return "LeftTop: " + leftTopBounds + ", taskId: " + leftTopTaskId + "\n"
+                + "RightBottom: " + rightBottomBounds + ", taskId: " + rightBottomTaskId +  "\n"
+                + "Divider: " + visualDividerBounds + "\n"
+                + "AppsVertical? " + appsStackedVertically;
+    }
+
+    public static final Creator<StagedSplitBounds> CREATOR = new Creator<StagedSplitBounds>() {
+        @Override
+        public StagedSplitBounds createFromParcel(Parcel in) {
+            return new StagedSplitBounds(in);
+        }
+
+        @Override
+        public StagedSplitBounds[] newArray(int size) {
+            return new StagedSplitBounds[size];
+        }
+    };
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
index a1e1231..19a5417 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
@@ -20,6 +20,8 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
@@ -31,10 +33,9 @@
 import static java.lang.Integer.MAX_VALUE;
 
 import android.app.ActivityManager;
-import android.app.WindowConfiguration;
 import android.content.Context;
+import android.graphics.Rect;
 import android.view.SurfaceControl;
-import android.window.TaskAppearedInfo;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -45,6 +46,7 @@
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.TaskStackListenerImpl;
 import com.android.wm.shell.util.GroupedRecentTaskInfo;
+import com.android.wm.shell.util.StagedSplitBounds;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -106,8 +108,11 @@
         setRawList(t1, t2, t3, t4, t5, t6);
 
         // Mark a couple pairs [t2, t4], [t3, t5]
-        mRecentTasksController.addSplitPair(t2.taskId, t4.taskId);
-        mRecentTasksController.addSplitPair(t3.taskId, t5.taskId);
+        StagedSplitBounds pair1Bounds = new StagedSplitBounds(new Rect(), new Rect(), 2, 4);
+        StagedSplitBounds pair2Bounds = new StagedSplitBounds(new Rect(), new Rect(), 3, 5);
+
+        mRecentTasksController.addSplitPair(t2.taskId, t4.taskId, pair1Bounds);
+        mRecentTasksController.addSplitPair(t3.taskId, t5.taskId, pair2Bounds);
 
         ArrayList<GroupedRecentTaskInfo> recentTasks = mRecentTasksController.getRecentTasks(
                 MAX_VALUE, RECENT_IGNORE_UNAVAILABLE, 0);
@@ -126,7 +131,8 @@
         setRawList(t1, t2, t3);
 
         // Add a pair
-        mRecentTasksController.addSplitPair(t2.taskId, t3.taskId);
+        StagedSplitBounds pair1Bounds = new StagedSplitBounds(new Rect(), new Rect(), 2, 3);
+        mRecentTasksController.addSplitPair(t2.taskId, t3.taskId, pair1Bounds);
         reset(mRecentTasksController);
 
         // Remove one of the tasks and ensure the pair is removed
@@ -201,10 +207,23 @@
         int[] flattenedTaskIds = new int[recentTasks.size() * 2];
         for (int i = 0; i < recentTasks.size(); i++) {
             GroupedRecentTaskInfo pair = recentTasks.get(i);
-            flattenedTaskIds[2 * i] = pair.mTaskInfo1.taskId;
+            int taskId1 = pair.mTaskInfo1.taskId;
+            flattenedTaskIds[2 * i] = taskId1;
             flattenedTaskIds[2 * i + 1] = pair.mTaskInfo2 != null
                     ? pair.mTaskInfo2.taskId
                     : -1;
+
+            if (pair.mTaskInfo2 != null) {
+                assertNotNull(pair.mStagedSplitBounds);
+                int leftTopTaskId = pair.mStagedSplitBounds.leftTopTaskId;
+                int bottomRightTaskId = pair.mStagedSplitBounds.rightBottomTaskId;
+                // Unclear if pairs are ordered by split position, most likely not.
+                assertTrue(leftTopTaskId == taskId1 || leftTopTaskId == pair.mTaskInfo2.taskId);
+                assertTrue(bottomRightTaskId == taskId1
+                        || bottomRightTaskId == pair.mTaskInfo2.taskId);
+            } else {
+                assertNull(pair.mStagedSplitBounds);
+            }
         }
         assertTrue("Expected: " + Arrays.toString(expectedTaskIds)
                         + " Received: " + Arrays.toString(flattenedTaskIds),
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/StagedSplitBoundsTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/StagedSplitBoundsTest.java
new file mode 100644
index 0000000..ad73c56
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/StagedSplitBoundsTest.java
@@ -0,0 +1,94 @@
+package com.android.wm.shell.recents;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.graphics.Rect;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.wm.shell.util.StagedSplitBounds;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class StagedSplitBoundsTest {
+    private static final int DEVICE_WIDTH = 100;
+    private static final int DEVICE_LENGTH = 200;
+    private static final int DIVIDER_SIZE = 20;
+    private static final int TASK_ID_1 = 4;
+    private static final int TASK_ID_2 = 9;
+
+    // Bounds in screen space
+    private final Rect mTopRect = new Rect();
+    private final Rect mBottomRect = new Rect();
+    private final Rect mLeftRect = new Rect();
+    private final Rect mRightRect = new Rect();
+
+    @Before
+    public void setup() {
+        mTopRect.set(0, 0, DEVICE_WIDTH, DEVICE_LENGTH / 2 - DIVIDER_SIZE / 2);
+        mBottomRect.set(0, DEVICE_LENGTH / 2 + DIVIDER_SIZE / 2,
+                DEVICE_WIDTH, DEVICE_LENGTH);
+        mLeftRect.set(0, 0, DEVICE_WIDTH / 2 - DIVIDER_SIZE / 2, DEVICE_LENGTH);
+        mRightRect.set(DEVICE_WIDTH / 2 + DIVIDER_SIZE / 2, 0,
+                DEVICE_WIDTH, DEVICE_LENGTH);
+    }
+
+    @Test
+    public void testVerticalStacked() {
+        StagedSplitBounds ssb = new StagedSplitBounds(mTopRect, mBottomRect,
+                TASK_ID_1, TASK_ID_2);
+        assertTrue(ssb.appsStackedVertically);
+    }
+
+    @Test
+    public void testHorizontalStacked() {
+        StagedSplitBounds ssb = new StagedSplitBounds(mLeftRect, mRightRect,
+                TASK_ID_1, TASK_ID_2);
+        assertFalse(ssb.appsStackedVertically);
+    }
+
+    @Test
+    public void testHorizontalDividerBounds() {
+        StagedSplitBounds ssb = new StagedSplitBounds(mTopRect, mBottomRect,
+                TASK_ID_1, TASK_ID_2);
+        Rect dividerBounds = ssb.visualDividerBounds;
+        assertEquals(0, dividerBounds.left);
+        assertEquals(DEVICE_LENGTH / 2 - DIVIDER_SIZE / 2, dividerBounds.top);
+        assertEquals(DEVICE_WIDTH, dividerBounds.right);
+        assertEquals(DEVICE_LENGTH / 2 + DIVIDER_SIZE / 2, dividerBounds.bottom);
+    }
+
+    @Test
+    public void testVerticalDividerBounds() {
+        StagedSplitBounds ssb = new StagedSplitBounds(mLeftRect, mRightRect,
+                TASK_ID_1, TASK_ID_2);
+        Rect dividerBounds = ssb.visualDividerBounds;
+        assertEquals(DEVICE_WIDTH / 2 - DIVIDER_SIZE / 2, dividerBounds.left);
+        assertEquals(0, dividerBounds.top);
+        assertEquals(DEVICE_WIDTH / 2 + DIVIDER_SIZE / 2, dividerBounds.right);
+        assertEquals(DEVICE_LENGTH, dividerBounds.bottom);
+    }
+
+    @Test
+    public void testEqualVerticalTaskPercent() {
+        StagedSplitBounds ssb = new StagedSplitBounds(mTopRect, mBottomRect,
+                TASK_ID_1, TASK_ID_2);
+        float topPercentSpaceTaken = (float) (DEVICE_LENGTH / 2 - DIVIDER_SIZE / 2) / DEVICE_LENGTH;
+        assertEquals(topPercentSpaceTaken, ssb.topTaskPercent, 0.01);
+    }
+
+    @Test
+    public void testEqualHorizontalTaskPercent() {
+        StagedSplitBounds ssb = new StagedSplitBounds(mLeftRect, mRightRect,
+                TASK_ID_1, TASK_ID_2);
+        float leftPercentSpaceTaken = (float) (DEVICE_WIDTH / 2 - DIVIDER_SIZE / 2) / DEVICE_WIDTH;
+        assertEquals(leftPercentSpaceTaken, ssb.leftTaskPercent, 0.01);
+    }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/GroupTask.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/GroupTask.java
deleted file mode 100644
index 323b20e..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/GroupTask.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.shared.recents.model;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-/**
- * A group task in the recent tasks list.
- * TODO: Move this into Launcher
- */
-public class GroupTask {
-    public @NonNull Task task1;
-    public @Nullable Task task2;
-
-    public GroupTask(@NonNull Task t1, @Nullable Task t2) {
-        task1 = t1;
-        task2 = t2;
-    }
-
-    public GroupTask(@NonNull GroupTask group) {
-        task1 = new Task(group.task1);
-        task2 = group.task2 != null
-                ? new Task(group.task2)
-                : null;
-    }
-
-    public boolean containsTask(int taskId) {
-        return task1.key.id == taskId || (task2 != null && task2.key.id == taskId);
-    }
-}