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

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

Merge "Restore all visible root tasks on user switch." into main

parents 060674a4 9c005632
Loading
Loading
Loading
Loading
+67 −6
Original line number Diff line number Diff line
@@ -156,6 +156,7 @@ import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.utils.Slogf;
import com.android.server.wm.utils.RegionUtils;
import com.android.window.flags.Flags;

import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -262,6 +263,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
    int mCurrentUser;
    /** Root task id of the front root task when user switched, indexed by userId. */
    SparseIntArray mUserRootTaskInFront = new SparseIntArray(2);
    SparseArray<IntArray> mUserVisibleRootTasks = new SparseArray<>();

    /**
     * A list of tokens that cause the top activity to be put to sleep.
@@ -1924,7 +1926,18 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
        // appropriate.
        removeRootTasksInWindowingModes(WINDOWING_MODE_PINNED);

        if (Flags.enableTopVisibleRootTaskPerUserTracking()) {
            final IntArray visibleRootTasks = new IntArray();
            forAllRootTasks(rootTask -> {
                if (mCurrentUser == rootTask.mUserId && rootTask.isVisibleRequested()) {
                    visibleRootTasks.add(rootTask.getRootTaskId());
                }
            }, /* traverseTopToBottom */ false);
            mUserVisibleRootTasks.put(mCurrentUser, visibleRootTasks);
        } else {
            mUserRootTaskInFront.put(mCurrentUser, focusRootTaskId);
        }

        mCurrentUser = userId;

        mTaskSupervisor.mStartingUsers.add(uss);
@@ -1937,22 +1950,60 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
            Slog.i(TAG, "Persisting top task because it belongs to an always-visible user");
            // For a normal user-switch, we will restore the new user's task. But if the pre-switch
            // top task is an always-visible (Communal) one, keep it even after the switch.
            if (Flags.enableTopVisibleRootTaskPerUserTracking()) {
                final IntArray rootTasks = mUserVisibleRootTasks.get(mCurrentUser);
                rootTasks.add(focusRootTaskId);
                mUserVisibleRootTasks.put(mCurrentUser, rootTasks);
            } else {
                mUserRootTaskInFront.put(mCurrentUser, focusRootTaskId);
            }

        }

        final int restoreRootTaskId = mUserRootTaskInFront.get(userId);
        final IntArray rootTaskIdsToRestore = mUserVisibleRootTasks.get(userId);
        boolean homeInFront = false;
        if (Flags.enableTopVisibleRootTaskPerUserTracking()) {
            if (rootTaskIdsToRestore == null) {
                // If there are no root tasks saved, try restore id 0 which should create and launch
                // the home task.
                handleRootTaskLaunchOnUserSwitch(/* restoreRootTaskId */INVALID_TASK_ID);
                homeInFront = true;
            } else {
                for (int i = 0; i < rootTaskIdsToRestore.size(); i++) {
                    handleRootTaskLaunchOnUserSwitch(rootTaskIdsToRestore.get(i));
                }
                // Check if the top task is type home
                if (rootTaskIdsToRestore.size() > 0) {
                    final int topRootTaskId = rootTaskIdsToRestore.get(
                            rootTaskIdsToRestore.size() - 1);
                    homeInFront = isHomeTask(topRootTaskId);
                }
            }
        } else {
            handleRootTaskLaunchOnUserSwitch(restoreRootTaskId);
            // Check if the top task is type home
            homeInFront = isHomeTask(restoreRootTaskId);
        }
        return homeInFront;
    }

    private boolean isHomeTask(int taskId) {
        final Task rootTask = getRootTask(taskId);
        return rootTask != null && rootTask.isActivityTypeHome();
    }

    private void handleRootTaskLaunchOnUserSwitch(int restoreRootTaskId) {
        Task rootTask = getRootTask(restoreRootTaskId);
        if (rootTask == null) {
            rootTask = getDefaultTaskDisplayArea().getOrCreateRootHomeTask();
        }
        final boolean homeInFront = rootTask.isActivityTypeHome();
        if (rootTask.isOnHomeDisplay()) {
            rootTask.moveToFront("switchUserOnHomeDisplay");
        } else {
            // Root task was moved to another display while user was swapped out.
            resumeHomeActivity(null, "switchUserOnOtherDisplay", getDefaultTaskDisplayArea());
        }
        return homeInFront;
    }

    /** Returns whether the given user is to be always-visible (e.g. a communal profile). */
@@ -1963,8 +2014,12 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
    }

    void removeUser(int userId) {
        if (Flags.enableTopVisibleRootTaskPerUserTracking()) {
            mUserVisibleRootTasks.delete(userId);
        } else {
            mUserRootTaskInFront.delete(userId);
        }
    }

    /**
     * Update the last used root task id for non-current user (current user's last
@@ -1976,9 +2031,15 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
                rootTask = getDefaultTaskDisplayArea().getOrCreateRootHomeTask();
            }

            if (Flags.enableTopVisibleRootTaskPerUserTracking()) {
                final IntArray rootTasks = mUserVisibleRootTasks.get(userId, new IntArray());
                rootTasks.add(rootTask.getRootTaskId());
                mUserVisibleRootTasks.put(userId, rootTasks);
            } else {
                mUserRootTaskInFront.put(userId, rootTask.getRootTaskId());
            }
        }
    }

    /**
     * Move root task with all its existing content to specified task display area.
+36 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ 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.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertEquals;
@@ -63,6 +64,7 @@ import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;

import android.app.ActivityOptions;
import android.app.WindowConfiguration;
@@ -77,12 +79,14 @@ import android.graphics.Rect;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.UserHandle;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.util.Pair;

import androidx.test.filters.MediumTest;

import com.android.internal.app.ResolverActivity;
import com.android.window.flags.Flags;

import org.junit.Before;
import org.junit.Test;
@@ -1332,6 +1336,38 @@ public class RootWindowContainerTests extends WindowTestsBase {
        assertEquals(taskDisplayArea.getTopRootTask(), taskDisplayArea.getRootHomeTask());
    }

    @EnableFlags(Flags.FLAG_ENABLE_TOP_VISIBLE_ROOT_TASK_PER_USER_TRACKING)
    @Test
    public void testSwitchUser_withVisibleRootTasks_storesAllVisibleRootTasksForCurrentUser() {
        // Set up root tasks
        final Task rootTask1 = mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask(
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
        final Task rootTask2 = mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask(
                WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
        final Task rootTask3 = mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask(
                WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
        doReturn(rootTask3).when(mRootWindowContainer).getTopDisplayFocusedRootTask();

        // Set up user ids and visibility
        rootTask1.mUserId = mRootWindowContainer.mCurrentUser;
        rootTask2.mUserId = mRootWindowContainer.mCurrentUser;
        rootTask3.mUserId = mRootWindowContainer.mCurrentUser;
        rootTask1.mVisibleRequested = false;
        rootTask2.mVisibleRequested = true;
        rootTask3.mVisibleRequested = true;

        // Switch to a different user
        int currentUser = mRootWindowContainer.mCurrentUser;
        int otherUser = currentUser + 1;
        mRootWindowContainer.switchUser(otherUser, null);

        // Verify that the previous user persists it's previous visible root tasks
        assertArrayEquals(
                new int[]{rootTask2.mTaskId, rootTask3.mTaskId},
                mRootWindowContainer.mUserVisibleRootTasks.get(currentUser).toArray()
        );
    }

    @Test
    public void testLockAllProfileTasks() {
        final int profileUid = UserHandle.PER_USER_RANGE + UserHandle.MIN_SECONDARY_USER_ID;