summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/GroupedTaskInfo.java182
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/GroupedTaskInfoTest.kt202
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java29
3 files changed, 315 insertions, 98 deletions
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/GroupedTaskInfo.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/GroupedTaskInfo.java
index 4300e84e8044..2ca011bfe000 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/GroupedTaskInfo.java
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/GroupedTaskInfo.java
@@ -16,10 +16,12 @@
package com.android.wm.shell.shared;
+import static android.app.WindowConfiguration.windowingModeToString;
+import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+
import android.annotation.IntDef;
import android.app.ActivityManager.RecentTaskInfo;
import android.app.TaskInfo;
-import android.app.WindowConfiguration;
import android.os.Parcel;
import android.os.Parcelable;
@@ -28,11 +30,14 @@ import androidx.annotation.Nullable;
import com.android.wm.shell.shared.split.SplitBounds;
+import kotlin.collections.CollectionsKt;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.stream.Collectors;
/**
* Simple container for recent tasks which should be presented as a single task within the
@@ -43,11 +48,13 @@ public class GroupedTaskInfo implements Parcelable {
public static final int TYPE_FULLSCREEN = 1;
public static final int TYPE_SPLIT = 2;
public static final int TYPE_FREEFORM = 3;
+ public static final int TYPE_MIXED = 4;
@IntDef(prefix = {"TYPE_"}, value = {
TYPE_FULLSCREEN,
TYPE_SPLIT,
- TYPE_FREEFORM
+ TYPE_FREEFORM,
+ TYPE_MIXED
})
public @interface GroupType {}
@@ -64,7 +71,7 @@ public class GroupedTaskInfo implements Parcelable {
* TYPE_SPLIT: Contains the two split roots of each side
* TYPE_FREEFORM: Contains the set of tasks currently in freeform mode
*/
- @NonNull
+ @Nullable
protected final List<TaskInfo> mTasks;
/**
@@ -85,6 +92,14 @@ public class GroupedTaskInfo implements Parcelable {
protected final int[] mMinimizedTaskIds;
/**
+ * Only set for TYPE_MIXED.
+ *
+ * The mixed set of task infos in this group.
+ */
+ @Nullable
+ protected final List<GroupedTaskInfo> mGroupedTasks;
+
+ /**
* Create new for a stack of fullscreen tasks
*/
public static GroupedTaskInfo forFullscreenTasks(@NonNull TaskInfo task) {
@@ -111,18 +126,41 @@ public class GroupedTaskInfo implements Parcelable {
minimizedFreeformTasks.stream().mapToInt(i -> i).toArray());
}
+ /**
+ * Create new for a group of grouped task infos, those grouped task infos may not be mixed
+ * themselves (ie. multiple depths of mixed grouped task infos are not allowed).
+ */
+ public static GroupedTaskInfo forMixed(@NonNull List<GroupedTaskInfo> groupedTasks) {
+ if (groupedTasks.isEmpty()) {
+ throw new IllegalArgumentException("Expected non-empty grouped task list");
+ }
+ if (groupedTasks.stream().anyMatch(task -> task.mType == TYPE_MIXED)) {
+ throw new IllegalArgumentException("Unexpected grouped task list");
+ }
+ return new GroupedTaskInfo(groupedTasks);
+ }
+
private GroupedTaskInfo(
@NonNull List<TaskInfo> tasks,
@Nullable SplitBounds splitBounds,
@GroupType int type,
@Nullable int[] minimizedFreeformTaskIds) {
mTasks = tasks;
+ mGroupedTasks = null;
mSplitBounds = splitBounds;
mType = type;
mMinimizedTaskIds = minimizedFreeformTaskIds;
ensureAllMinimizedIdsPresent(tasks, minimizedFreeformTaskIds);
}
+ private GroupedTaskInfo(@NonNull List<GroupedTaskInfo> groupedTasks) {
+ mTasks = null;
+ mGroupedTasks = groupedTasks;
+ mSplitBounds = null;
+ mType = TYPE_MIXED;
+ mMinimizedTaskIds = null;
+ }
+
private void ensureAllMinimizedIdsPresent(
@NonNull List<TaskInfo> tasks,
@Nullable int[] minimizedFreeformTaskIds) {
@@ -141,26 +179,47 @@ public class GroupedTaskInfo implements Parcelable {
for (int i = 0; i < numTasks; i++) {
mTasks.add(new TaskInfo(parcel));
}
+ mGroupedTasks = parcel.createTypedArrayList(GroupedTaskInfo.CREATOR);
mSplitBounds = parcel.readTypedObject(SplitBounds.CREATOR);
mType = parcel.readInt();
mMinimizedTaskIds = parcel.createIntArray();
}
/**
- * Get primary {@link RecentTaskInfo}
+ * If TYPE_MIXED, returns the root of the grouped tasks
+ * For all other types, returns this task itself
+ */
+ @NonNull
+ public GroupedTaskInfo getBaseGroupedTask() {
+ if (mType == TYPE_MIXED) {
+ return mGroupedTasks.getFirst();
+ }
+ return this;
+ }
+
+ /**
+ * Get primary {@link TaskInfo}.
+ *
+ * @throws IllegalStateException if the group is TYPE_MIXED.
*/
@NonNull
public TaskInfo getTaskInfo1() {
+ if (mType == TYPE_MIXED) {
+ throw new IllegalStateException("No indexed tasks for a mixed task");
+ }
return mTasks.getFirst();
}
/**
- * Get secondary {@link RecentTaskInfo}.
+ * Get secondary {@link TaskInfo}, used primarily for TYPE_SPLIT.
*
- * Used in split screen.
+ * @throws IllegalStateException if the group is TYPE_MIXED.
*/
@Nullable
public TaskInfo getTaskInfo2() {
+ if (mType == TYPE_MIXED) {
+ throw new IllegalStateException("No indexed tasks for a mixed task");
+ }
if (mTasks.size() > 1) {
return mTasks.get(1);
}
@@ -172,9 +231,7 @@ public class GroupedTaskInfo implements Parcelable {
*/
@Nullable
public TaskInfo getTaskById(int taskId) {
- return mTasks.stream()
- .filter(task -> task.taskId == taskId)
- .findFirst().orElse(null);
+ return CollectionsKt.firstOrNull(getTaskInfoList(), taskInfo -> taskInfo.taskId == taskId);
}
/**
@@ -182,35 +239,59 @@ public class GroupedTaskInfo implements Parcelable {
*/
@NonNull
public List<TaskInfo> getTaskInfoList() {
- return mTasks;
+ if (mType == TYPE_MIXED) {
+ return CollectionsKt.flatMap(mGroupedTasks, groupedTaskInfo -> groupedTaskInfo.mTasks);
+ } else {
+ return mTasks;
+ }
}
/**
* @return Whether this grouped task contains a task with the given {@code taskId}.
*/
public boolean containsTask(int taskId) {
- return mTasks.stream()
- .anyMatch((task -> task.taskId == taskId));
+ return getTaskById(taskId) != null;
}
/**
- * Return {@link SplitBounds} if this is a split screen entry or {@code null}
+ * Returns whether the group is of the given type, if this is a TYPE_MIXED group, then returns
+ * whether the root task info is of the given type.
+ */
+ public boolean isBaseType(@GroupType int type) {
+ return getBaseGroupedTask().mType == type;
+ }
+
+ /**
+ * Return {@link SplitBounds} if this is a split screen entry or {@code null}. Only valid for
+ * TYPE_SPLIT.
*/
@Nullable
public SplitBounds getSplitBounds() {
+ if (mType == TYPE_MIXED) {
+ throw new IllegalStateException("No split bounds for a mixed task");
+ }
return mSplitBounds;
}
/**
- * Get type of this recents entry. One of {@link GroupType}
+ * Get type of this recents entry. One of {@link GroupType}.
+ * Note: This is deprecated, callers should use `isBaseType()` and not make assumptions about
+ * specific group types
*/
+ @Deprecated
@GroupType
public int getType() {
return mType;
}
+ /**
+ * Returns the set of minimized task ids, only valid for TYPE_FREEFORM.
+ */
@Nullable
public int[] getMinimizedTaskIds() {
+ if (mType == TYPE_MIXED) {
+ throw new IllegalStateException("No minimized task ids for a mixed task");
+ }
return mMinimizedTaskIds;
}
@@ -222,67 +303,64 @@ public class GroupedTaskInfo implements Parcelable {
GroupedTaskInfo other = (GroupedTaskInfo) obj;
return mType == other.mType
&& Objects.equals(mTasks, other.mTasks)
+ && Objects.equals(mGroupedTasks, other.mGroupedTasks)
&& Objects.equals(mSplitBounds, other.mSplitBounds)
&& Arrays.equals(mMinimizedTaskIds, other.mMinimizedTaskIds);
}
@Override
public int hashCode() {
- return Objects.hash(mType, mTasks, mSplitBounds, Arrays.hashCode(mMinimizedTaskIds));
+ return Objects.hash(mType, mTasks, mGroupedTasks, mSplitBounds,
+ Arrays.hashCode(mMinimizedTaskIds));
}
@Override
public String toString() {
StringBuilder taskString = new StringBuilder();
- for (int i = 0; i < mTasks.size(); i++) {
- if (i == 0) {
- taskString.append("Task");
- } else {
- taskString.append(", Task");
+ if (mType == TYPE_MIXED) {
+ taskString.append("GroupedTasks=" + mGroupedTasks.stream()
+ .map(GroupedTaskInfo::toString)
+ .collect(Collectors.joining(",\n\t", "[\n\t", "\n]")));
+ } else {
+ taskString.append("Tasks=" + mTasks.stream()
+ .map(taskInfo -> getTaskInfoDumpString(taskInfo))
+ .collect(Collectors.joining(", ", "[", "]")));
+ if (mSplitBounds != null) {
+ taskString.append(", SplitBounds=").append(mSplitBounds);
}
- taskString.append(i + 1).append(": ").append(getTaskInfo(mTasks.get(i)));
+ taskString.append(", Type=" + typeToString(mType));
+ taskString.append(", Minimized Task IDs=" + Arrays.toString(mMinimizedTaskIds));
}
- if (mSplitBounds != null) {
- taskString.append(", SplitBounds: ").append(mSplitBounds);
- }
- taskString.append(", Type=");
- switch (mType) {
- case TYPE_FULLSCREEN:
- taskString.append("TYPE_FULLSCREEN");
- break;
- case TYPE_SPLIT:
- taskString.append("TYPE_SPLIT");
- break;
- case TYPE_FREEFORM:
- taskString.append("TYPE_FREEFORM");
- break;
- }
- taskString.append(", Minimized Task IDs: ");
- taskString.append(Arrays.toString(mMinimizedTaskIds));
return taskString.toString();
}
- private String getTaskInfo(TaskInfo taskInfo) {
+ private String getTaskInfoDumpString(TaskInfo taskInfo) {
if (taskInfo == null) {
return null;
}
+ final boolean isExcluded = (taskInfo.baseIntent.getFlags()
+ & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
return "id=" + taskInfo.taskId
- + " baseIntent=" +
- (taskInfo.baseIntent != null && taskInfo.baseIntent.getComponent() != null
- ? taskInfo.baseIntent.getComponent().flattenToString()
- : "null")
- + " winMode=" + WindowConfiguration.windowingModeToString(
- taskInfo.getWindowingMode());
+ + " winMode=" + windowingModeToString(taskInfo.getWindowingMode())
+ + " visReq=" + taskInfo.isVisibleRequested
+ + " vis=" + taskInfo.isVisible
+ + " excluded=" + isExcluded
+ + " baseIntent="
+ + (taskInfo.baseIntent != null && taskInfo.baseIntent.getComponent() != null
+ ? taskInfo.baseIntent.getComponent().flattenToShortString()
+ : "null");
}
@Override
public void writeToParcel(Parcel parcel, int flags) {
// We don't use the parcel list methods because we want to only write the TaskInfo state
// and not the subclasses (Recents/RunningTaskInfo) whose fields are all deprecated
- parcel.writeInt(mTasks.size());
- for (int i = 0; i < mTasks.size(); i++) {
+ final int tasksSize = mTasks != null ? mTasks.size() : 0;
+ parcel.writeInt(tasksSize);
+ for (int i = 0; i < tasksSize; i++) {
mTasks.get(i).writeTaskToParcel(parcel, flags);
}
+ parcel.writeTypedList(mGroupedTasks);
parcel.writeTypedObject(mSplitBounds, flags);
parcel.writeInt(mType);
parcel.writeIntArray(mMinimizedTaskIds);
@@ -293,6 +371,16 @@ public class GroupedTaskInfo implements Parcelable {
return 0;
}
+ private String typeToString(@GroupType int type) {
+ return switch (type) {
+ case TYPE_FULLSCREEN -> "FULLSCREEN";
+ case TYPE_SPLIT -> "SPLIT";
+ case TYPE_FREEFORM -> "FREEFORM";
+ case TYPE_MIXED -> "MIXED";
+ default -> "UNKNOWN";
+ };
+ }
+
public static final Creator<GroupedTaskInfo> CREATOR = new Creator() {
@Override
public GroupedTaskInfo createFromParcel(Parcel in) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/GroupedTaskInfoTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/GroupedTaskInfoTest.kt
index fd3adabfd44b..32096645aea7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/GroupedTaskInfoTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/GroupedTaskInfoTest.kt
@@ -40,6 +40,7 @@ import org.mockito.Mockito.mock
/**
* Tests for [GroupedTaskInfo]
+ * Build & Run: atest WMShellUnitTests:GroupedTaskInfoTest
*/
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -47,7 +48,7 @@ class GroupedTaskInfoTest : ShellTestCase() {
@Test
fun testSingleTask_hasCorrectType() {
- assertThat(singleTaskGroupInfo().type).isEqualTo(TYPE_FULLSCREEN)
+ assertThat(singleTaskGroupInfo().isBaseType(TYPE_FULLSCREEN)).isTrue()
}
@Test
@@ -66,7 +67,7 @@ class GroupedTaskInfoTest : ShellTestCase() {
@Test
fun testSplitTasks_hasCorrectType() {
- assertThat(splitTasksGroupInfo().type).isEqualTo(TYPE_SPLIT)
+ assertThat(splitTasksGroupInfo().isBaseType(TYPE_SPLIT)).isTrue()
}
@Test
@@ -87,8 +88,8 @@ class GroupedTaskInfoTest : ShellTestCase() {
@Test
fun testFreeformTasks_hasCorrectType() {
- assertThat(freeformTasksGroupInfo(freeformTaskIds = arrayOf(1)).type)
- .isEqualTo(TYPE_FREEFORM)
+ assertThat(freeformTasksGroupInfo(freeformTaskIds = arrayOf(1)).isBaseType(TYPE_FREEFORM))
+ .isTrue()
}
@Test
@@ -111,83 +112,155 @@ class GroupedTaskInfoTest : ShellTestCase() {
}
@Test
+ fun testMixedWithFullscreenBase_hasCorrectType() {
+ assertThat(mixedTaskGroupInfoWithFullscreenBase().isBaseType(TYPE_FULLSCREEN)).isTrue()
+ }
+
+ @Test
+ fun testMixedWithSplitBase_hasCorrectType() {
+ assertThat(mixedTaskGroupInfoWithSplitBase().isBaseType(TYPE_SPLIT)).isTrue()
+ }
+
+ @Test
+ fun testMixedWithFreeformBase_hasCorrectType() {
+ assertThat(mixedTaskGroupInfoWithFreeformBase().isBaseType(TYPE_FREEFORM)).isTrue()
+ }
+
+ @Test
+ fun testMixed_disallowEmptyMixed() {
+ assertThrows(IllegalArgumentException::class.java) {
+ GroupedTaskInfo.forMixed(listOf())
+ }
+ }
+
+ @Test
+ fun testMixed_disallowNestedMixed() {
+ assertThrows(IllegalArgumentException::class.java) {
+ GroupedTaskInfo.forMixed(listOf(
+ GroupedTaskInfo.forMixed(listOf(singleTaskGroupInfo()))))
+ }
+ }
+
+ @Test
+ fun testMixed_disallowNonMixedAccessors() {
+ val mixed = mixedTaskGroupInfoWithFullscreenBase()
+ assertThrows(IllegalStateException::class.java) {
+ mixed.taskInfo1
+ }
+ assertThrows(IllegalStateException::class.java) {
+ mixed.taskInfo2
+ }
+ assertThrows(IllegalStateException::class.java) {
+ mixed.splitBounds
+ }
+ assertThrows(IllegalStateException::class.java) {
+ mixed.minimizedTaskIds
+ }
+ }
+
+ @Test
fun testParcelling_singleTask() {
- val recentTaskInfo = singleTaskGroupInfo()
+ val taskInfo = singleTaskGroupInfo()
val parcel = Parcel.obtain()
- recentTaskInfo.writeToParcel(parcel, 0)
+ taskInfo.writeToParcel(parcel, 0)
parcel.setDataPosition(0)
// Read the object back from the parcel
- val recentTaskInfoParcel: GroupedTaskInfo =
+ val taskInfoFromParcel: GroupedTaskInfo =
GroupedTaskInfo.CREATOR.createFromParcel(parcel)
- assertThat(recentTaskInfoParcel.type).isEqualTo(TYPE_FULLSCREEN)
- assertThat(recentTaskInfoParcel.taskInfo1.taskId).isEqualTo(1)
- assertThat(recentTaskInfoParcel.taskInfo2).isNull()
+ assertThat(taskInfoFromParcel.isBaseType(TYPE_FULLSCREEN)).isTrue()
+ assertThat(taskInfoFromParcel.taskInfo1.taskId).isEqualTo(1)
+ assertThat(taskInfoFromParcel.taskInfo2).isNull()
}
@Test
fun testParcelling_splitTasks() {
- val recentTaskInfo = splitTasksGroupInfo()
+ val taskInfo = splitTasksGroupInfo()
val parcel = Parcel.obtain()
- recentTaskInfo.writeToParcel(parcel, 0)
+ taskInfo.writeToParcel(parcel, 0)
parcel.setDataPosition(0)
// Read the object back from the parcel
- val recentTaskInfoParcel: GroupedTaskInfo =
+ val taskInfoFromParcel: GroupedTaskInfo =
GroupedTaskInfo.CREATOR.createFromParcel(parcel)
- assertThat(recentTaskInfoParcel.type).isEqualTo(TYPE_SPLIT)
- assertThat(recentTaskInfoParcel.taskInfo1.taskId).isEqualTo(1)
- assertThat(recentTaskInfoParcel.taskInfo2).isNotNull()
- assertThat(recentTaskInfoParcel.taskInfo2!!.taskId).isEqualTo(2)
- assertThat(recentTaskInfoParcel.splitBounds).isNotNull()
- assertThat(recentTaskInfoParcel.splitBounds!!.snapPosition).isEqualTo(SNAP_TO_2_50_50)
+ assertThat(taskInfoFromParcel.isBaseType(TYPE_SPLIT)).isTrue()
+ assertThat(taskInfoFromParcel.taskInfo1.taskId).isEqualTo(1)
+ assertThat(taskInfoFromParcel.taskInfo2).isNotNull()
+ assertThat(taskInfoFromParcel.taskInfo2!!.taskId).isEqualTo(2)
+ assertThat(taskInfoFromParcel.splitBounds).isNotNull()
+ assertThat(taskInfoFromParcel.splitBounds!!.snapPosition).isEqualTo(SNAP_TO_2_50_50)
}
@Test
fun testParcelling_freeformTasks() {
- val recentTaskInfo = freeformTasksGroupInfo(freeformTaskIds = arrayOf(1, 2, 3))
+ val taskInfo = freeformTasksGroupInfo(freeformTaskIds = arrayOf(1, 2, 3))
val parcel = Parcel.obtain()
- recentTaskInfo.writeToParcel(parcel, 0)
+ taskInfo.writeToParcel(parcel, 0)
parcel.setDataPosition(0)
// Read the object back from the parcel
- val recentTaskInfoParcel: GroupedTaskInfo =
+ val taskInfoFromParcel: GroupedTaskInfo =
GroupedTaskInfo.CREATOR.createFromParcel(parcel)
- assertThat(recentTaskInfoParcel.type).isEqualTo(TYPE_FREEFORM)
- assertThat(recentTaskInfoParcel.taskInfoList).hasSize(3)
+ assertThat(taskInfoFromParcel.isBaseType(TYPE_FREEFORM)).isTrue()
+ assertThat(taskInfoFromParcel.taskInfoList).hasSize(3)
// Only compare task ids
val taskIdComparator = Correspondence.transforming<TaskInfo, Int>(
{ it?.taskId }, "has taskId of"
)
- assertThat(recentTaskInfoParcel.taskInfoList).comparingElementsUsing(taskIdComparator)
- .containsExactly(1, 2, 3)
+ assertThat(taskInfoFromParcel.taskInfoList).comparingElementsUsing(taskIdComparator)
+ .containsExactly(1, 2, 3).inOrder()
}
@Test
fun testParcelling_freeformTasks_minimizedTasks() {
- val recentTaskInfo = freeformTasksGroupInfo(
+ val taskInfo = freeformTasksGroupInfo(
freeformTaskIds = arrayOf(1, 2, 3), minimizedTaskIds = arrayOf(2))
val parcel = Parcel.obtain()
- recentTaskInfo.writeToParcel(parcel, 0)
+ taskInfo.writeToParcel(parcel, 0)
parcel.setDataPosition(0)
// Read the object back from the parcel
- val recentTaskInfoParcel: GroupedTaskInfo =
+ val taskInfoFromParcel: GroupedTaskInfo =
GroupedTaskInfo.CREATOR.createFromParcel(parcel)
- assertThat(recentTaskInfoParcel.type).isEqualTo(TYPE_FREEFORM)
- assertThat(recentTaskInfoParcel.minimizedTaskIds).isEqualTo(arrayOf(2).toIntArray())
+ assertThat(taskInfoFromParcel.isBaseType(TYPE_FREEFORM)).isTrue()
+ assertThat(taskInfoFromParcel.minimizedTaskIds).isEqualTo(arrayOf(2).toIntArray())
}
@Test
- fun testGetTaskById_singleTasks() {
+ fun testParcelling_mixedTasks() {
+ val taskInfo = GroupedTaskInfo.forMixed(listOf(
+ freeformTasksGroupInfo(freeformTaskIds = arrayOf(4, 5, 6),
+ minimizedTaskIds = arrayOf(5)),
+ splitTasksGroupInfo(firstId = 2, secondId = 3),
+ singleTaskGroupInfo(id = 1)))
+
+ val parcel = Parcel.obtain()
+ taskInfo.writeToParcel(parcel, 0)
+ parcel.setDataPosition(0)
+
+ // Read the object back from the parcel
+ val taskInfoFromParcel: GroupedTaskInfo =
+ GroupedTaskInfo.CREATOR.createFromParcel(parcel)
+ assertThat(taskInfoFromParcel.isBaseType(TYPE_FREEFORM)).isTrue()
+ assertThat(taskInfoFromParcel.baseGroupedTask.minimizedTaskIds).isEqualTo(
+ arrayOf(5).toIntArray())
+ for (i in 1..6) {
+ assertThat(taskInfoFromParcel.containsTask(i)).isTrue()
+ }
+ assertThat(taskInfoFromParcel.taskInfoList).hasSize(taskInfo.taskInfoList.size)
+ }
+
+ @Test
+ fun testTaskProperties_singleTasks() {
val task1 = createTaskInfo(id = 1234)
val taskInfo = GroupedTaskInfo.forFullscreenTasks(task1)
assertThat(taskInfo.getTaskById(1234)).isEqualTo(task1)
assertThat(taskInfo.containsTask(1234)).isTrue()
+ assertThat(taskInfo.taskInfoList).isEqualTo(listOf(task1))
}
@Test
- fun testGetTaskById_multipleTasks() {
+ fun testTaskProperties_splitTasks() {
val task1 = createTaskInfo(id = 1)
val task2 = createTaskInfo(id = 2)
val splitBounds = SplitBounds(Rect(), Rect(), 1, 2, SNAP_TO_2_50_50)
@@ -198,6 +271,41 @@ class GroupedTaskInfoTest : ShellTestCase() {
assertThat(taskInfo.getTaskById(2)).isEqualTo(task2)
assertThat(taskInfo.containsTask(1)).isTrue()
assertThat(taskInfo.containsTask(2)).isTrue()
+ assertThat(taskInfo.taskInfoList).isEqualTo(listOf(task1, task2))
+ }
+
+ @Test
+ fun testTaskProperties_freeformTasks() {
+ val task1 = createTaskInfo(id = 1)
+ val task2 = createTaskInfo(id = 2)
+
+ val taskInfo = GroupedTaskInfo.forFreeformTasks(listOf(task1, task2), setOf())
+
+ assertThat(taskInfo.getTaskById(1)).isEqualTo(task1)
+ assertThat(taskInfo.getTaskById(2)).isEqualTo(task2)
+ assertThat(taskInfo.containsTask(1)).isTrue()
+ assertThat(taskInfo.containsTask(2)).isTrue()
+ assertThat(taskInfo.taskInfoList).isEqualTo(listOf(task1, task2))
+ }
+
+ @Test
+ fun testTaskProperties_mixedTasks() {
+ val task1 = createTaskInfo(id = 1)
+ val task2 = createTaskInfo(id = 2)
+ val task3 = createTaskInfo(id = 3)
+ val splitBounds = SplitBounds(Rect(), Rect(), 1, 2, SNAP_TO_2_50_50)
+
+ val splitTasks = GroupedTaskInfo.forSplitTasks(task1, task2, splitBounds)
+ val fullscreenTasks = GroupedTaskInfo.forFullscreenTasks(task3)
+ val mixedTasks = GroupedTaskInfo.forMixed(listOf(splitTasks, fullscreenTasks))
+
+ assertThat(mixedTasks.getTaskById(1)).isEqualTo(task1)
+ assertThat(mixedTasks.getTaskById(2)).isEqualTo(task2)
+ assertThat(mixedTasks.getTaskById(3)).isEqualTo(task3)
+ assertThat(mixedTasks.containsTask(1)).isTrue()
+ assertThat(mixedTasks.containsTask(2)).isTrue()
+ assertThat(mixedTasks.containsTask(3)).isTrue()
+ assertThat(mixedTasks.taskInfoList).isEqualTo(listOf(task1, task2, task3))
}
private fun createTaskInfo(id: Int) = ActivityManager.RecentTaskInfo().apply {
@@ -205,14 +313,14 @@ class GroupedTaskInfoTest : ShellTestCase() {
token = WindowContainerToken(mock(IWindowContainerToken::class.java))
}
- private fun singleTaskGroupInfo(): GroupedTaskInfo {
- val task = createTaskInfo(id = 1)
+ private fun singleTaskGroupInfo(id: Int = 1): GroupedTaskInfo {
+ val task = createTaskInfo(id)
return GroupedTaskInfo.forFullscreenTasks(task)
}
- private fun splitTasksGroupInfo(): GroupedTaskInfo {
- val task1 = createTaskInfo(id = 1)
- val task2 = createTaskInfo(id = 2)
+ private fun splitTasksGroupInfo(firstId: Int = 1, secondId: Int = 2): GroupedTaskInfo {
+ val task1 = createTaskInfo(firstId)
+ val task2 = createTaskInfo(secondId)
val splitBounds = SplitBounds(Rect(), Rect(), 1, 2, SNAP_TO_2_50_50)
return GroupedTaskInfo.forSplitTasks(task1, task2, splitBounds)
}
@@ -225,4 +333,22 @@ class GroupedTaskInfoTest : ShellTestCase() {
freeformTaskIds.map { createTaskInfo(it) }.toList(),
minimizedTaskIds.toSet())
}
+
+ private fun mixedTaskGroupInfoWithFullscreenBase(): GroupedTaskInfo {
+ return GroupedTaskInfo.forMixed(listOf(
+ singleTaskGroupInfo(id = 1),
+ singleTaskGroupInfo(id = 2)))
+ }
+
+ private fun mixedTaskGroupInfoWithSplitBase(): GroupedTaskInfo {
+ return GroupedTaskInfo.forMixed(listOf(
+ splitTasksGroupInfo(firstId = 2, secondId = 3),
+ singleTaskGroupInfo(id = 1)))
+ }
+
+ private fun mixedTaskGroupInfoWithFreeformBase(): GroupedTaskInfo {
+ return GroupedTaskInfo.forMixed(listOf(
+ freeformTasksGroupInfo(freeformTaskIds = arrayOf(2, 3, 4)),
+ singleTaskGroupInfo(id = 1)))
+ }
}
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 22b45e8c63af..7e5d6ce38c5a 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
@@ -24,6 +24,9 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.launcher3.Flags.FLAG_ENABLE_USE_TOP_VISIBLE_ACTIVITY_FOR_EXCLUDE_FROM_RECENT_TASK;
import static com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_PERSISTENCE;
+import static com.android.wm.shell.shared.GroupedTaskInfo.TYPE_FREEFORM;
+import static com.android.wm.shell.shared.GroupedTaskInfo.TYPE_FULLSCREEN;
+import static com.android.wm.shell.shared.GroupedTaskInfo.TYPE_SPLIT;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_50_50;
import static org.junit.Assert.assertEquals;
@@ -346,9 +349,9 @@ public class RecentTasksControllerTest extends ShellTestCase {
GroupedTaskInfo singleGroup2 = recentTasks.get(2);
// Check that groups have expected types
- assertEquals(GroupedTaskInfo.TYPE_FREEFORM, freeformGroup.getType());
- assertEquals(GroupedTaskInfo.TYPE_FULLSCREEN, singleGroup1.getType());
- assertEquals(GroupedTaskInfo.TYPE_FULLSCREEN, singleGroup2.getType());
+ assertTrue(freeformGroup.isBaseType(TYPE_FREEFORM));
+ assertTrue(singleGroup1.isBaseType(TYPE_FULLSCREEN));
+ assertTrue(singleGroup2.isBaseType(TYPE_FULLSCREEN));
// Check freeform group entries
assertEquals(t1, freeformGroup.getTaskInfoList().get(0));
@@ -385,9 +388,9 @@ public class RecentTasksControllerTest extends ShellTestCase {
GroupedTaskInfo singleGroup = recentTasks.get(2);
// Check that groups have expected types
- assertEquals(GroupedTaskInfo.TYPE_SPLIT, splitGroup.getType());
- assertEquals(GroupedTaskInfo.TYPE_FREEFORM, freeformGroup.getType());
- assertEquals(GroupedTaskInfo.TYPE_FULLSCREEN, singleGroup.getType());
+ assertTrue(splitGroup.isBaseType(TYPE_SPLIT));
+ assertTrue(freeformGroup.isBaseType(TYPE_FREEFORM));
+ assertTrue(singleGroup.isBaseType(TYPE_FULLSCREEN));
// Check freeform group entries
assertEquals(t3, freeformGroup.getTaskInfoList().get(0));
@@ -420,10 +423,10 @@ public class RecentTasksControllerTest extends ShellTestCase {
// Expect no grouping of tasks
assertEquals(4, recentTasks.size());
- assertEquals(GroupedTaskInfo.TYPE_FULLSCREEN, recentTasks.get(0).getType());
- assertEquals(GroupedTaskInfo.TYPE_FULLSCREEN, recentTasks.get(1).getType());
- assertEquals(GroupedTaskInfo.TYPE_FULLSCREEN, recentTasks.get(2).getType());
- assertEquals(GroupedTaskInfo.TYPE_FULLSCREEN, recentTasks.get(3).getType());
+ assertTrue(recentTasks.get(0).isBaseType(TYPE_FULLSCREEN));
+ assertTrue(recentTasks.get(1).isBaseType(TYPE_FULLSCREEN));
+ assertTrue(recentTasks.get(2).isBaseType(TYPE_FULLSCREEN));
+ assertTrue(recentTasks.get(3).isBaseType(TYPE_FULLSCREEN));
assertEquals(t1, recentTasks.get(0).getTaskInfo1());
assertEquals(t2, recentTasks.get(1).getTaskInfo1());
@@ -457,9 +460,9 @@ public class RecentTasksControllerTest extends ShellTestCase {
GroupedTaskInfo singleGroup2 = recentTasks.get(2);
// Check that groups have expected types
- assertEquals(GroupedTaskInfo.TYPE_FREEFORM, freeformGroup.getType());
- assertEquals(GroupedTaskInfo.TYPE_FULLSCREEN, singleGroup1.getType());
- assertEquals(GroupedTaskInfo.TYPE_FULLSCREEN, singleGroup2.getType());
+ assertTrue(freeformGroup.isBaseType(TYPE_FREEFORM));
+ assertTrue(singleGroup1.isBaseType(TYPE_FULLSCREEN));
+ assertTrue(singleGroup2.isBaseType(TYPE_FULLSCREEN));
// Check freeform group entries
assertEquals(3, freeformGroup.getTaskInfoList().size());