diff options
| -rw-r--r-- | services/core/java/com/android/server/wm/RootWindowContainer.java | 73 | ||||
| -rw-r--r-- | services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java | 36 |
2 files changed, 103 insertions, 6 deletions
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 46312aff1fb6..c284222a7c1d 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -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); - mUserRootTaskInFront.put(mCurrentUser, focusRootTaskId); + 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. - mUserRootTaskInFront.put(mCurrentUser, focusRootTaskId); + 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,7 +2014,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } void removeUser(int userId) { - mUserRootTaskInFront.delete(userId); + if (Flags.enableTopVisibleRootTaskPerUserTracking()) { + mUserVisibleRootTasks.delete(userId); + } else { + mUserRootTaskInFront.delete(userId); + } } /** @@ -1976,7 +2031,13 @@ class RootWindowContainer extends WindowContainer<DisplayContent> rootTask = getDefaultTaskDisplayArea().getOrCreateRootHomeTask(); } - mUserRootTaskInFront.put(userId, rootTask.getRootTaskId()); + 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()); + } } } diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java index 7e8bd38fb6a9..d53825ffefa7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -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; @@ -1331,6 +1335,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; |