Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit abe5fe29 authored by Winson Chung's avatar Winson Chung
Browse files

2a/ Generalize GroupedRecentTaskInfo into GroupedTaskInfo

- This CL generalizes the type for the grouped task info so that we
  can reuse it for RunningTaskInfos in addition to RecentTaskInfos.
  This has the benefit of consolidating (in the future) multiple paths
  from Shell -> Launcher which require aggregating information about
  various shell features, as opposed to APIs today which contain
  only Core-specific data types (ie. the TaskInfos themselves).  There
  are otherwise no behavior changes in this CL.
- This does not change any ordering of calls from shell -> launcher,
  and does not provide more than a single task when reporting
  taskMovedToFront (this will be implemented in a followup CL)

Bug: 346588978
Flag: EXEMPT adding new flag enable_shell_top_task_tracking
Test: Build SystemUI & Launcher
Test: atest WMShellUnitTests
Change-Id: Ieb44463397bb2665fa6d8a8328be2d6a23c65792
parent d73e3332
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -2764,14 +2764,19 @@ public class ActivityManager {
        /**
         * Information of organized child tasks.
         *
         * @deprecated No longer used
         * @hide
         */
        @Deprecated
        public ArrayList<RecentTaskInfo> childrenTaskInfos = new ArrayList<>();

        /**
         * Information about the last snapshot taken for this task.
         *
         * @deprecated No longer used
         * @hide
         */
        @Deprecated
        public PersistedTaskSnapshotData lastSnapshotData = new PersistedTaskSnapshotData();

        public RecentTaskInfo() {
@@ -2793,7 +2798,7 @@ public class ActivityManager {
            lastSnapshotData.taskSize = source.readTypedObject(Point.CREATOR);
            lastSnapshotData.contentInsets = source.readTypedObject(Rect.CREATOR);
            lastSnapshotData.bufferSize = source.readTypedObject(Point.CREATOR);
            super.readFromParcel(source);
            super.readTaskFromParcel(source);
        }

        @Override
@@ -2804,7 +2809,7 @@ public class ActivityManager {
            dest.writeTypedObject(lastSnapshotData.taskSize, flags);
            dest.writeTypedObject(lastSnapshotData.contentInsets, flags);
            dest.writeTypedObject(lastSnapshotData.bufferSize, flags);
            super.writeToParcel(dest, flags);
            super.writeTaskToParcel(dest, flags);
        }

        public static final @android.annotation.NonNull Creator<RecentTaskInfo> CREATOR
@@ -2988,13 +2993,13 @@ public class ActivityManager {

        public void readFromParcel(Parcel source) {
            id = source.readInt();
            super.readFromParcel(source);
            super.readTaskFromParcel(source);
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(id);
            super.writeToParcel(dest, flags);
            super.writeTaskToParcel(dest, flags);
        }

        public static final @android.annotation.NonNull Creator<RunningTaskInfo> CREATOR = new Creator<RunningTaskInfo>() {
+2 −3
Original line number Diff line number Diff line
@@ -534,10 +534,9 @@ public class ActivityTaskManager {
            dest.writeIntArray(childTaskUserIds);
            dest.writeInt(visible ? 1 : 0);
            dest.writeInt(position);
            super.writeToParcel(dest, flags);
            super.writeTaskToParcel(dest, flags);
        }

        @Override
        void readFromParcel(Parcel source) {
            bounds = source.readTypedObject(Rect.CREATOR);
            childTaskIds = source.createIntArray();
@@ -546,7 +545,7 @@ public class ActivityTaskManager {
            childTaskUserIds = source.createIntArray();
            visible = source.readInt() > 0;
            position = source.readInt();
            super.readFromParcel(source);
            super.readTaskFromParcel(source);
        }

        public static final @NonNull Creator<RootTaskInfo> CREATOR = new Creator<>() {
+6 −4
Original line number Diff line number Diff line
@@ -358,8 +358,9 @@ public class TaskInfo {
        // Do nothing
    }

    private TaskInfo(Parcel source) {
        readFromParcel(source);
    /** @hide */
    public TaskInfo(Parcel source) {
        readTaskFromParcel(source);
    }

    /**
@@ -516,7 +517,7 @@ public class TaskInfo {
    /**
     * Reads the TaskInfo from a parcel.
     */
    void readFromParcel(Parcel source) {
    void readTaskFromParcel(Parcel source) {
        userId = source.readInt();
        taskId = source.readInt();
        effectiveUid = source.readInt();
@@ -568,8 +569,9 @@ public class TaskInfo {

    /**
     * Writes the TaskInfo to a parcel.
     * @hide
     */
    void writeToParcel(Parcel dest, int flags) {
    public void writeTaskToParcel(Parcel dest, int flags) {
        dest.writeInt(userId);
        dest.writeInt(taskId);
        dest.writeInt(effectiveUid);
+1 −1
Original line number Diff line number Diff line
@@ -16,4 +16,4 @@

package com.android.wm.shell.shared;

parcelable GroupedRecentTaskInfo;
 No newline at end of file
parcelable GroupedTaskInfo;
 No newline at end of file
+110 −58
Original line number Diff line number Diff line
@@ -17,7 +17,8 @@
package com.android.wm.shell.shared;

import android.annotation.IntDef;
import android.app.ActivityManager;
import android.app.ActivityManager.RecentTaskInfo;
import android.app.TaskInfo;
import android.app.WindowConfiguration;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,69 +28,91 @@ import androidx.annotation.Nullable;

import com.android.wm.shell.shared.split.SplitBounds;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * Simple container for recent tasks.  May contain either a single or pair of tasks.
 * Simple container for recent tasks which should be presented as a single task within the
 * Overview UI.
 */
public class GroupedRecentTaskInfo implements Parcelable {
public class GroupedTaskInfo implements Parcelable {

    public static final int TYPE_SINGLE = 1;
    public static final int TYPE_FULLSCREEN = 1;
    public static final int TYPE_SPLIT = 2;
    public static final int TYPE_FREEFORM = 3;

    @IntDef(prefix = {"TYPE_"}, value = {
            TYPE_SINGLE,
            TYPE_FULLSCREEN,
            TYPE_SPLIT,
            TYPE_FREEFORM
    })
    public @interface GroupType {}

    /**
     * The type of this particular task info, can be one of TYPE_FULLSCREEN, TYPE_SPLIT or
     * TYPE_FREEFORM.
     */
    @GroupType
    protected final int mType;

    /**
     * The list of tasks associated with this single recent task info.
     * TYPE_FULLSCREEN: Contains the stack of tasks associated with a single "task" in overview
     * TYPE_SPLIT: Contains the two split roots of each side
     * TYPE_FREEFORM: Contains the set of tasks currently in freeform mode
     */
    @NonNull
    private final ActivityManager.RecentTaskInfo[] mTasks;
    protected final List<TaskInfo> mTasks;

    /**
     * Only set for TYPE_SPLIT.
     *
     * Information about the split bounds.
     */
    @Nullable
    private final SplitBounds mSplitBounds;
    @GroupType
    private final int mType;
    // TODO(b/348332802): move isMinimized inside each Task object instead once we have a
    //  replacement for RecentTaskInfo
    private final int[] mMinimizedTaskIds;
    protected final SplitBounds mSplitBounds;

    /**
     * Create new for a single task
     * Only set for TYPE_FREEFORM.
     *
     * TODO(b/348332802): move isMinimized inside each Task object instead once we have a
     *  replacement for RecentTaskInfo
     */
    public static GroupedRecentTaskInfo forSingleTask(
            @NonNull ActivityManager.RecentTaskInfo task) {
        return new GroupedRecentTaskInfo(new ActivityManager.RecentTaskInfo[]{task}, null,
                TYPE_SINGLE, null /* minimizedFreeformTasks */);
    @Nullable
    protected final int[] mMinimizedTaskIds;

    /**
     * Create new for a stack of fullscreen tasks
     */
    public static GroupedTaskInfo forFullscreenTasks(@NonNull TaskInfo task) {
        return new GroupedTaskInfo(List.of(task), null, TYPE_FULLSCREEN,
                null /* minimizedFreeformTasks */);
    }

    /**
     * Create new for a pair of tasks in split screen
     */
    public static GroupedRecentTaskInfo forSplitTasks(@NonNull ActivityManager.RecentTaskInfo task1,
            @NonNull ActivityManager.RecentTaskInfo task2, @Nullable SplitBounds splitBounds) {
        return new GroupedRecentTaskInfo(new ActivityManager.RecentTaskInfo[]{task1, task2},
                splitBounds, TYPE_SPLIT, null /* minimizedFreeformTasks */);
    public static GroupedTaskInfo forSplitTasks(@NonNull TaskInfo task1,
                    @NonNull TaskInfo task2, @Nullable SplitBounds splitBounds) {
        return new GroupedTaskInfo(List.of(task1, task2), splitBounds, TYPE_SPLIT,
                null /* minimizedFreeformTasks */);
    }

    /**
     * Create new for a group of freeform tasks
     */
    public static GroupedRecentTaskInfo forFreeformTasks(
            @NonNull ActivityManager.RecentTaskInfo[] tasks,
    public static GroupedTaskInfo forFreeformTasks(
                    @NonNull List<TaskInfo> tasks,
                    @NonNull Set<Integer> minimizedFreeformTasks) {
        return new GroupedRecentTaskInfo(
                tasks,
                null /* splitBounds */,
                TYPE_FREEFORM,
        return new GroupedTaskInfo(tasks, null /* splitBounds */, TYPE_FREEFORM,
                minimizedFreeformTasks.stream().mapToInt(i -> i).toArray());
    }

    private GroupedRecentTaskInfo(
            @NonNull ActivityManager.RecentTaskInfo[] tasks,
    private GroupedTaskInfo(
            @NonNull List<TaskInfo> tasks,
            @Nullable SplitBounds splitBounds,
            @GroupType int type,
            @Nullable int[] minimizedFreeformTaskIds) {
@@ -100,52 +123,56 @@ public class GroupedRecentTaskInfo implements Parcelable {
        ensureAllMinimizedIdsPresent(tasks, minimizedFreeformTaskIds);
    }

    private static void ensureAllMinimizedIdsPresent(
            @NonNull ActivityManager.RecentTaskInfo[] tasks,
    private void ensureAllMinimizedIdsPresent(
            @NonNull List<TaskInfo> tasks,
            @Nullable int[] minimizedFreeformTaskIds) {
        if (minimizedFreeformTaskIds == null) {
            return;
        }
        if (!Arrays.stream(minimizedFreeformTaskIds).allMatch(
                taskId -> Arrays.stream(tasks).anyMatch(task -> task.taskId == taskId))) {
                taskId -> tasks.stream().anyMatch(task -> task.taskId == taskId))) {
            throw new IllegalArgumentException("Minimized task IDs contain non-existent Task ID.");
        }
    }

    GroupedRecentTaskInfo(Parcel parcel) {
        mTasks = parcel.createTypedArray(ActivityManager.RecentTaskInfo.CREATOR);
    protected GroupedTaskInfo(@NonNull Parcel parcel) {
        mTasks = new ArrayList();
        final int numTasks = parcel.readInt();
        for (int i = 0; i < numTasks; i++) {
            mTasks.add(new TaskInfo(parcel));
        }
        mSplitBounds = parcel.readTypedObject(SplitBounds.CREATOR);
        mType = parcel.readInt();
        mMinimizedTaskIds = parcel.createIntArray();
    }

    /**
     * Get primary {@link ActivityManager.RecentTaskInfo}
     * Get primary {@link RecentTaskInfo}
     */
    @NonNull
    public ActivityManager.RecentTaskInfo getTaskInfo1() {
        return mTasks[0];
    public TaskInfo getTaskInfo1() {
        return mTasks.getFirst();
    }

    /**
     * Get secondary {@link ActivityManager.RecentTaskInfo}.
     * Get secondary {@link RecentTaskInfo}.
     *
     * Used in split screen.
     */
    @Nullable
    public ActivityManager.RecentTaskInfo getTaskInfo2() {
        if (mTasks.length > 1) {
            return mTasks[1];
    public TaskInfo getTaskInfo2() {
        if (mTasks.size() > 1) {
            return mTasks.get(1);
        }
        return null;
    }

    /**
     * Get all {@link ActivityManager.RecentTaskInfo}s grouped together.
     * Get all {@link RecentTaskInfo}s grouped together.
     */
    @NonNull
    public List<ActivityManager.RecentTaskInfo> getTaskInfoList() {
        return Arrays.asList(mTasks);
    public List<TaskInfo> getTaskInfoList() {
        return mTasks;
    }

    /**
@@ -164,28 +191,46 @@ public class GroupedRecentTaskInfo implements Parcelable {
        return mType;
    }

    @Nullable
    public int[] getMinimizedTaskIds() {
        return mMinimizedTaskIds;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof GroupedTaskInfo)) {
            return false;
        }
        GroupedTaskInfo other = (GroupedTaskInfo) obj;
        return mType == other.mType
                && Objects.equals(mTasks, other.mTasks)
                && Objects.equals(mSplitBounds, other.mSplitBounds)
                && Arrays.equals(mMinimizedTaskIds, other.mMinimizedTaskIds);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mType, mTasks, mSplitBounds, Arrays.hashCode(mMinimizedTaskIds));
    }

    @Override
    public String toString() {
        StringBuilder taskString = new StringBuilder();
        for (int i = 0; i < mTasks.length; i++) {
        for (int i = 0; i < mTasks.size(); i++) {
            if (i == 0) {
                taskString.append("Task");
            } else {
                taskString.append(", Task");
            }
            taskString.append(i + 1).append(": ").append(getTaskInfo(mTasks[i]));
            taskString.append(i + 1).append(": ").append(getTaskInfo(mTasks.get(i)));
        }
        if (mSplitBounds != null) {
            taskString.append(", SplitBounds: ").append(mSplitBounds);
        }
        taskString.append(", Type=");
        switch (mType) {
            case TYPE_SINGLE:
                taskString.append("TYPE_SINGLE");
            case TYPE_FULLSCREEN:
                taskString.append("TYPE_FULLSCREEN");
                break;
            case TYPE_SPLIT:
                taskString.append("TYPE_SPLIT");
@@ -199,7 +244,7 @@ public class GroupedRecentTaskInfo implements Parcelable {
        return taskString.toString();
    }

    private String getTaskInfo(ActivityManager.RecentTaskInfo taskInfo) {
    private String getTaskInfo(TaskInfo taskInfo) {
        if (taskInfo == null) {
            return null;
        }
@@ -213,7 +258,12 @@ public class GroupedRecentTaskInfo implements Parcelable {

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeTypedArray(mTasks, 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++) {
            mTasks.get(i).writeTaskToParcel(parcel, flags);
        }
        parcel.writeTypedObject(mSplitBounds, flags);
        parcel.writeInt(mType);
        parcel.writeIntArray(mMinimizedTaskIds);
@@ -224,13 +274,15 @@ public class GroupedRecentTaskInfo implements Parcelable {
        return 0;
    }

    public static final @android.annotation.NonNull Creator<GroupedRecentTaskInfo> CREATOR =
            new Creator<GroupedRecentTaskInfo>() {
        public GroupedRecentTaskInfo createFromParcel(Parcel source) {
            return new GroupedRecentTaskInfo(source);
    public static final Creator<GroupedTaskInfo> CREATOR = new Creator() {
        @Override
        public GroupedTaskInfo createFromParcel(Parcel in) {
            return new GroupedTaskInfo(in);
        }
        public GroupedRecentTaskInfo[] newArray(int size) {
            return new GroupedRecentTaskInfo[size];

        @Override
        public GroupedTaskInfo[] newArray(int size) {
            return new GroupedTaskInfo[size];
        }
    };
}
Loading