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

Commit 4ee187ee authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Return all visible activities for VIS" into main

parents ab161f7f 48a461f3
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -178,6 +178,17 @@ flag {
    is_fixed_read_only: true
}

flag {
    namespace: "windowing_sdk"
    name: "return_all_visible_activities_for_vis"
    description: "Return all visible activities in multi-tasking feature to VIS"
    bug: "434114340"
    is_fixed_read_only: true
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    namespace: "windowing_sdk"
    name: "dispose_task_fragment_synchronously"
+11 −8
Original line number Diff line number Diff line
@@ -143,20 +143,23 @@ public abstract class ActivityTaskManagerInternal implements ActiveUids.Observer
            IVoiceInteractor mInteractor);

    /**
     * Returns the top activity from each of the currently visible root tasks, and the related task
     * id. The first entry will be the focused activity.
     * @return a list of {@link ActivityAssistInfo} of the visible activities in the all displays.
     * Visible activities in the focused root Task are at the front of the list.
     *
     * <p>NOTE: If the top activity is in the split screen, the other activities in the same split
     * screen will also be returned.
     * <p>NOTE: This includes all visible activities, even if one is paused, which means it is
     * behind a translucent container.
     */
    public abstract List<ActivityAssistInfo> getTopVisibleActivities();

    /**
     * Returns the top activity from each of the currently visible root tasks of the given
     * display, and the related task id. The first entry will be the focused activity.
     * @return a list of {@link ActivityAssistInfo} of the visible activities in the given display.
     * Visible activities in the focused root Task are at the front of the list.
     *
     * <p>NOTE: If the top activity is in the split screen, the other activities in the same split
     * screen will also be returned.
     * <p>NOTE: This includes all visible activities, even if one is paused, which means it is
     * behind a translucent container.
     *
     * @param displayId if the displayId is not found, this will return visible activities in all
     *                  displays.
     */
    public abstract List<ActivityAssistInfo> getTopVisibleActivities(int displayId);

+64 −31
Original line number Diff line number Diff line
@@ -1661,20 +1661,51 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
    }

    /**
     * @return a list of pairs, containing activities and their task id which are the top ones in
     * each visible root task. The first entry will be the focused activity.
     * @return a list of {@link ActivityAssistInfo} of the visible activities in the given display.
     * Visible activities in the focused root Task are at the front of the list.
     *
     * <p>NOTE: If the top activity is in the split screen, the other activities in the same split
     * screen will also be returned.
     * <p>NOTE: This includes all visible activities, even if one is paused, which means it is
     * behind a translucent container.
     */
    List<ActivityAssistInfo> getTopVisibleActivities(int displayId) {
        final ArrayList<ActivityAssistInfo> topVisibleActivities = new ArrayList<>();
        final ArrayList<ActivityAssistInfo> activityAssistInfos = new ArrayList<>();
        final DisplayContent dc =
                displayId != INVALID_DISPLAY ? getDisplayContent(displayId) : null;
        final Task topFocusedRootTask =
                dc != null ? dc.getFocusedRootTask() : getTopDisplayFocusedRootTask();

        if (Flags.returnAllVisibleActivitiesForVis()) {
            final ArrayList<ActivityAssistInfo> visibleActivitiesInFocusedRoot = new ArrayList<>();
            final Consumer<ActivityRecord> collectFromFocusedRoot = activity -> {
                if (activity.isVisibleRequested()) {
                    visibleActivitiesInFocusedRoot.add(new ActivityAssistInfo(activity));
                }
            };
            final Consumer<ActivityRecord> collectFromNonFocusedRoot = activity -> {
                if (activity.isVisibleRequested()) {
                    topVisibleActivities.add(new ActivityAssistInfo(activity));
                }
            };
            final Consumer<Task> collectFromDisplay = leafTaskFragment -> {
                if (!leafTaskFragment.isVisibleRequested()) {
                    return;
                }
                if (leafTaskFragment.getRootTask() == topFocusedRootTask) {
                    leafTaskFragment.forAllActivities(collectFromFocusedRoot);
                } else {
                    leafTaskFragment.forAllActivities(collectFromNonFocusedRoot);
                }
            };

            if (dc != null) {
                dc.forAllRootTasks(collectFromDisplay);
            } else {
                // Traverse all displays.
                forAllRootTasks(collectFromDisplay);
            }
            topVisibleActivities.addAll(0, visibleActivitiesInFocusedRoot);
        } else {
            final ArrayList<ActivityAssistInfo> activityAssistInfos = new ArrayList<>();
            final Consumer<Task> collectVisibleActivities = rootTask -> {
                // Get top activity from a visible root task and add it to the list.
                if (rootTask.shouldBeVisible(null /* starting */)) {
@@ -1706,6 +1737,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
                // Traverse all displays.
                forAllRootTasks(collectVisibleActivities);
            }
        }

        return topVisibleActivities;
    }

+111 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import static com.android.server.wm.ActivityRecord.State.STOPPING;
import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
import static com.android.server.wm.RootWindowContainer.MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE;
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
import static com.android.window.flags.Flags.FLAG_RETURN_ALL_VISIBLE_ACTIVITIES_FOR_VIS;

import static com.google.common.truth.Truth.assertThat;

@@ -1395,6 +1396,116 @@ public class RootWindowContainerTests extends WindowTestsBase {
                anyBoolean());
    }

    @Test
    public void testGetTopVisibleActivities_fullscreen() {
        // Make every Task opaque.
        final ActivityTaskSupervisor.OpaqueContainerHelper opaqueContainerHelper =
                mAtm.mTaskSupervisor.mOpaqueContainerHelper;
        spyOn(opaqueContainerHelper);
        doReturn(true).when(opaqueContainerHelper).isOpaque(
                any(), any(), anyBoolean(), anyBoolean());

        final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
        final ActivityRecord bottomR = createActivityRecord(display);
        final ActivityRecord topR = createActivityRecord(display);
        // The Task behind another should be invisible.
        bottomR.setVisibleRequested(false);

        final List<ActivityAssistInfo> result = mRootWindowContainer.getTopVisibleActivities(
                display.mDisplayId);

        assertEquals(1, result.size());
        assertEquals(topR.token, result.get(0).getActivityToken());
    }

    @Test
    public void testGetTopVisibleActivities_splitScreen() {
        // Make every Task opaque.
        final ActivityTaskSupervisor.OpaqueContainerHelper opaqueContainerHelper =
                mAtm.mTaskSupervisor.mOpaqueContainerHelper;
        spyOn(opaqueContainerHelper);
        doReturn(true).when(opaqueContainerHelper).isOpaque(
                any(), any(), anyBoolean(), anyBoolean());

        final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
        final ActivityRecord splitActivity0 = createActivityRecordWithParentTask(display,
                WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
        final ActivityRecord splitActivity1 = createActivityRecordWithParentTask(
                splitActivity0.getRootTask());
        final Task splitTask0 = splitActivity0.getTask();
        final Task splitTask1 = splitActivity1.getTask();
        splitTask0.setAdjacentTaskFragments(new TaskFragment.AdjacentSet(splitTask0, splitTask1));
        splitTask0.setBounds(0, 0, 500, 500);
        splitTask1.setBounds(500, 0, 1000, 500);

        final List<ActivityAssistInfo> result = mRootWindowContainer.getTopVisibleActivities(
                display.mDisplayId);

        assertEquals(2, result.size());
        assertEquals(splitActivity1.token, result.get(0).getActivityToken());
        assertEquals(splitActivity0.token, result.get(1).getActivityToken());
    }

    @EnableFlags(FLAG_RETURN_ALL_VISIBLE_ACTIVITIES_FOR_VIS)
    @Test
    public void testGetTopVisibleActivities_rootTaskWithMultiLeafTasks() {
        final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
        final Task deskRoot = createTask(display, WINDOWING_MODE_MULTI_WINDOW,
                ACTIVITY_TYPE_STANDARD);
        final ActivityRecord activity0 = createActivityRecordWithParentTask(deskRoot);
        final ActivityRecord activity1 = createActivityRecordWithParentTask(deskRoot);
        final ActivityRecord activity2 = createActivityRecordWithParentTask(deskRoot);

        final List<ActivityAssistInfo> result = mRootWindowContainer.getTopVisibleActivities(
                display.mDisplayId);

        assertEquals(3, result.size());
        assertEquals(activity2.token, result.get(0).getActivityToken());
        assertEquals(activity1.token, result.get(1).getActivityToken());
        assertEquals(activity0.token, result.get(2).getActivityToken());
    }

    @EnableFlags(FLAG_RETURN_ALL_VISIBLE_ACTIVITIES_FOR_VIS)
    @Test
    public void testGetTopVisibleActivities_activityEmbedding() {
        final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
        final Task task = createTask(display, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
        final TaskFragment tf0 = createTaskFragmentWithActivity(task);
        final TaskFragment tf1 = createTaskFragmentWithActivity(task);
        tf0.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        tf1.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        tf0.setBounds(0, 0, 500, 500);
        tf1.setBounds(500, 0, 1000, 500);
        tf0.setAdjacentTaskFragments(new TaskFragment.AdjacentSet(tf0, tf1));
        final ActivityRecord activity0 = tf0.getTopMostActivity();
        final ActivityRecord activity1 = tf1.getTopMostActivity();

        final List<ActivityAssistInfo> result = mRootWindowContainer.getTopVisibleActivities(
                display.mDisplayId);

        assertEquals(2, result.size());
        assertEquals(activity1.token, result.get(0).getActivityToken());
        assertEquals(activity0.token, result.get(1).getActivityToken());
    }

    @EnableFlags(FLAG_RETURN_ALL_VISIBLE_ACTIVITIES_FOR_VIS)
    @Test
    public void testGetTopVisibleActivities_behindTranslucent() {
        final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
        // Create two visible requested activities in one Task to simulate one behind another
        // translucent.
        final Task task = createTask(display, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
        final ActivityRecord activity0 = createActivityRecord(task);
        final ActivityRecord activity1 = createActivityRecord(task);

        final List<ActivityAssistInfo> result = mRootWindowContainer.getTopVisibleActivities(
                display.mDisplayId);

        assertEquals(2, result.size());
        assertEquals(activity1.token, result.get(0).getActivityToken());
        assertEquals(activity0.token, result.get(1).getActivityToken());
    }

    /**
     * Mock {@link RootWindowContainer#resolveHomeActivity} for returning consistent activity
     * info for test cases.
+3 −0
Original line number Diff line number Diff line
@@ -1491,6 +1491,9 @@ public class WindowTestsBase extends SystemServiceTestsBase {
            while (mCreateActivityCount > 0) {
                final ActivityRecord activity = new ActivityBuilder(mAtm).build();
                taskFragment.addChild(activity);
                if (mParentTask != null) {
                    postCreateActivitySetup(activity, mParentTask.getDisplayContent());
                }
                mCreateActivityCount--;
            }
            if (mOrganizer != null) {