Merge "Improving proximity state logs" into main
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index b3f09a9..ed2fd99 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -1290,7 +1290,11 @@
@NonNull UserHandle user) {}
/**
- * Called when a window with a secure surface is no longer shown on the device.
+ * Called when there is no longer any window with a secure surface shown on the device.
+ *
+ * <p>This is only called once there are no more secure windows shown on the device. If
+ * there are multiple secure windows shown on the device, this callback will be called only
+ * once all of them are hidden.</p>
*
* @param displayId The display ID on which the window was shown before.
*
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 68f812f..b3b8c6e 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.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 @@
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 @@
// 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 @@
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 @@
}
void removeUser(int userId) {
- mUserRootTaskInFront.delete(userId);
+ if (Flags.enableTopVisibleRootTaskPerUserTracking()) {
+ mUserVisibleRootTasks.delete(userId);
+ } else {
+ mUserRootTaskInFront.delete(userId);
+ }
}
/**
@@ -1976,7 +2031,13 @@
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 023cc55..699ed02 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.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.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.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 @@
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;