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

Commit c21b1cb6 authored by Momoko Hattori's avatar Momoko Hattori Committed by Felipe Leme
Browse files

Fix getPreviousFullUserToEnterForeground() for interactive HSU

- Remove isFull() check in getPreviousFullUserToEnterForeground() so
  that it can return the interactive HSU (headless system user), which
  is not a full user.
- Fix UserManagerService.LifeCycle.onUserStarting() so that the last
  foreground time for interactive HSU is correctly set on boot.
- Rename the method to getPreviousUserToEnterForeground() (drop 'Full').

Bug: 412630247
Test: atest com.android.server.pm.UserManagerServiceMockedTest
Test: atest android.host.multiuser.UserManagerHostTest
Test: On a desktop device:
      1. On the login screen, click 'Add person' flow.
      2. On the first screen of setup wizard, click 'Cancel'.
      3. Observe that the login screen is shown again.
Test: On a desktop device:
      a. Switch to a non-system user (e.g., user 10).
      b. Reboot the device.
      c. Do the 1.~3. above (Click 'Add person', then 'Cancel')
Flag: EXEMPT bug fix

Change-Id: Ia601d9598ae3625cf7d5ee02b5846edc7c7beca3
parent 5bcd67ee
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ interface IUserManager {
    UserInfo getPrimaryUser();
    int getMainUserId();
    int getCommunalProfileId();
    int getPreviousFullUserToEnterForeground();
    int getPreviousUserToEnterForeground();
    List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying, boolean excludePreCreated);
    List<UserInfo> getProfiles(int userId, boolean enabledOnly);
    int[] getProfileIds(int userId, boolean enabledOnly);
+1 −1
Original line number Diff line number Diff line
@@ -5250,7 +5250,7 @@ public class UserManager {
    })
    public @Nullable UserHandle getPreviousForegroundUser() {
        try {
            final int previousUser = mService.getPreviousFullUserToEnterForeground();
            final int previousUser = mService.getPreviousUserToEnterForeground();
            if (previousUser == UserHandle.USER_NULL) {
                return null;
            }
+5 −5
Original line number Diff line number Diff line
@@ -1001,7 +1001,7 @@ public class UserManagerService extends IUserManager.Stub {
                if (user != null) {
                    user.startRealtime = SystemClock.elapsedRealtime();
                    if (targetUser.getUserIdentifier() == UserHandle.USER_SYSTEM
                            && targetUser.isFull()) {
                            && user.info.supportsSwitchTo()) {
                        mUms.setLastEnteredForegroundTimeToNow(user);
                    }
                }
@@ -1442,7 +1442,7 @@ public class UserManagerService extends IUserManager.Stub {
    private @UserIdInt int getPreviousOrFirstSwitchableUser()
            throws UserManager.CheckedUserOperationException {
        // Return the previous foreground user, if there is one.
        final int previousUser = getPreviousFullUserToEnterForeground();
        final int previousUser = getPreviousUserToEnterForeground();
        if (previousUser != UserHandle.USER_NULL) {
            Slogf.i(LOG_TAG, "Boot user is previous user %d", previousUser);
            return previousUser;
@@ -1475,7 +1475,7 @@ public class UserManagerService extends IUserManager.Stub {
   }

    @Override
    public @CanBeNULL @UserIdInt int getPreviousFullUserToEnterForeground() {
    public @CanBeNULL @UserIdInt int getPreviousUserToEnterForeground() {
        checkQueryOrCreateUsersPermission("get previous user");
        int previousUser = UserHandle.USER_NULL;
        long latestEnteredTime = 0;
@@ -1485,8 +1485,8 @@ public class UserManagerService extends IUserManager.Stub {
            for (int i = 0; i < userSize; i++) {
                final UserData userData = mUsers.valueAt(i);
                final int userId = userData.info.id;
                if (userId != currentUser && userData.info.isFull() && !userData.info.partial
                        && userData.info.isEnabled() && !mRemovingUserIds.get(userId)) {
                if (userId != currentUser && !userData.info.partial && userData.info.isEnabled()
                        && !mRemovingUserIds.get(userId)) {
                    final long userEnteredTime = userData.mLastEnteredForegroundTimeMillis;
                    if (userEnteredTime > latestEnteredTime) {
                        latestEnteredTime = userEnteredTime;
+25 −25
Original line number Diff line number Diff line
@@ -437,80 +437,80 @@ public final class UserManagerServiceMockedTest {
    }

    @Test
    public void testGetPreviousFullUserToEnterForeground() throws Exception {
    public void testGetPreviousUserToEnterForeground() throws Exception {
        addUser(USER_ID);
        setLastForegroundTime(USER_ID, 1_000_000L);
        addUser(OTHER_USER_ID);
        setLastForegroundTime(OTHER_USER_ID, 2_000_000L);

        assertWithMessage("getPreviousFullUserToEnterForeground")
                .that(mUms.getPreviousFullUserToEnterForeground())
        assertWithMessage("getPreviousUserToEnterForeground")
                .that(mUms.getPreviousUserToEnterForeground())
                .isEqualTo(OTHER_USER_ID);
    }

    @Test
    public void testGetPreviousFullUserToEnterForeground_SkipsCurrentUser() throws Exception {
    public void testGetPreviousUserToEnterForeground_SkipsCurrentUser() throws Exception {
        addUser(USER_ID);
        setLastForegroundTime(USER_ID, 1_000_000L);
        addUser(OTHER_USER_ID);
        setLastForegroundTime(OTHER_USER_ID, 2_000_000L);

        mockCurrentUser(OTHER_USER_ID);
        assertWithMessage("getPreviousFullUserToEnterForeground should skip current user")
                .that(mUms.getPreviousFullUserToEnterForeground())
        assertWithMessage("getPreviousUserToEnterForeground")
                .that(mUms.getPreviousUserToEnterForeground())
                .isEqualTo(USER_ID);
    }

    @Test
    public void testGetPreviousFullUserToEnterForeground_SkipsNonFullUsers() throws Exception {
    public void testGetPreviousUserToEnterForeground_SkipsPartialUsers() throws Exception {
        addUser(USER_ID);
        setLastForegroundTime(USER_ID, 1_000_000L);
        addUser(OTHER_USER_ID);
        setLastForegroundTime(OTHER_USER_ID, 2_000_000L);

        mUsers.get(OTHER_USER_ID).info.flags &= ~UserInfo.FLAG_FULL;
        assertWithMessage("getPreviousFullUserToEnterForeground should skip non-full users")
                .that(mUms.getPreviousFullUserToEnterForeground())
        mUsers.get(OTHER_USER_ID).info.partial = true;
        assertWithMessage("getPreviousUserToEnterForeground")
                .that(mUms.getPreviousUserToEnterForeground())
                .isEqualTo(USER_ID);
    }

    @Test
    public void testGetPreviousFullUserToEnterForeground_SkipsPartialUsers() throws Exception {
    public void testGetPreviousUserToEnterForeground_SkipsDisabledUsers() throws Exception {
        addUser(USER_ID);
        setLastForegroundTime(USER_ID, 1_000_000L);
        addUser(OTHER_USER_ID);
        setLastForegroundTime(OTHER_USER_ID, 2_000_000L);

        mUsers.get(OTHER_USER_ID).info.partial = true;
        assertWithMessage("getPreviousFullUserToEnterForeground should skip partial users")
                .that(mUms.getPreviousFullUserToEnterForeground())
        mUsers.get(OTHER_USER_ID).info.flags |= UserInfo.FLAG_DISABLED;
        assertWithMessage("getPreviousUserToEnterForeground")
                .that(mUms.getPreviousUserToEnterForeground())
                .isEqualTo(USER_ID);
    }

    @Test
    public void testGetPreviousFullUserToEnterForeground_SkipsDisabledUsers() throws Exception {
    public void testGetPreviousUserToEnterForeground_SkipsRemovingUsers() throws Exception {
        addUser(USER_ID);
        setLastForegroundTime(USER_ID, 1_000_000L);
        addUser(OTHER_USER_ID);
        setLastForegroundTime(OTHER_USER_ID, 2_000_000L);

        mUsers.get(OTHER_USER_ID).info.flags |= UserInfo.FLAG_DISABLED;
        assertWithMessage("getPreviousFullUserToEnterForeground should skip disabled users")
                .that(mUms.getPreviousFullUserToEnterForeground())
        mUms.addRemovingUserId(OTHER_USER_ID);
        assertWithMessage("getPreviousUserToEnterForeground")
                .that(mUms.getPreviousUserToEnterForeground())
                .isEqualTo(USER_ID);
    }

    @Test
    public void testGetPreviousFullUserToEnterForeground_SkipsRemovingUsers() throws Exception {
    public void testGetPreviousUserToEnterForeground_ReturnsHeadlessSystemUser() throws Exception {
        addUser(USER_ID);
        setLastForegroundTime(USER_ID, 1_000_000L);
        addUser(OTHER_USER_ID);
        setLastForegroundTime(OTHER_USER_ID, 2_000_000L);
        setSystemUserHeadless(true);
        mockCanSwitchToHeadlessSystemUser(true);
        setLastForegroundTime(UserHandle.USER_SYSTEM, 2_000_000L);

        mUms.addRemovingUserId(OTHER_USER_ID);
        assertWithMessage("getPreviousFullUserToEnterForeground should skip removing users")
                .that(mUms.getPreviousFullUserToEnterForeground())
                .isEqualTo(USER_ID);
        assertWithMessage("getPreviousUserToEnterForeground")
                .that(mUms.getPreviousUserToEnterForeground())
                .isEqualTo(UserHandle.USER_SYSTEM);
    }

    @Test