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

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

Merge "Reschedule stop background users if Guest current" into main

parents e2a808a3 bf7a9aca
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -2335,6 +2335,14 @@ class UserController implements Handler.Callback {
            // Never stop system user
            return;
        }
        synchronized(mLock) {
            final UserState uss = mStartedUsers.get(oldUserId);
            if (uss == null || uss.state == UserState.STATE_STOPPING
                    || uss.state == UserState.STATE_SHUTDOWN) {
                // We've stopped (or are stopping) the user anyway, so don't bother scheduling.
                return;
            }
        }
        if (oldUserId == mInjector.getUserManagerInternal().getMainUserId()) {
            // MainUser is currently special for things like Docking, so we'll exempt it for now.
            Slogf.i(TAG, "Exempting user %d from being stopped due to inactivity by virtue "
@@ -2371,6 +2379,12 @@ class UserController implements Handler.Callback {
                // We'll soon want to switch to this user, so don't kill it now.
                return;
            }
            final UserInfo currentOrTargetUser = getCurrentUserLU();
            if (currentOrTargetUser != null && currentOrTargetUser.isGuest()) {
                // Don't kill any background users for the sake of a Guest. Just reschedule instead.
                scheduleStopOfBackgroundUser(userId);
                return;
            }
            Slogf.i(TAG, "Stopping background user %d due to inactivity", userId);
            stopUsersLU(userId, /* allowDelayedLocking= */ true, null, null);
        }
+1 −0
Original line number Diff line number Diff line
@@ -5918,6 +5918,7 @@ public class UserManagerService extends IUserManager.Stub {
        return userData;
    }

    /** For testing only! Directly, unnaturally removes userId from list of users. */
    @VisibleForTesting
    void removeUserInfo(@UserIdInt int userId) {
        synchronized (mUsersLock) {
+67 −5
Original line number Diff line number Diff line
@@ -672,6 +672,61 @@ public class UserControllerTest {
                new HashSet<>(mUserController.getRunningUsersLU()));
    }

    /** Test scheduling stopping of background users - reschedule if current user is a guest. */
    @Test
    public void testScheduleStopOfBackgroundUser_rescheduleWhenGuest() throws Exception {
        mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_SCHEDULE_STOP_OF_BACKGROUND_USER);

        mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
                /* maxRunningUsers= */ 10, /* delayUserDataLocking= */ false,
                /* backgroundUserScheduledStopTimeSecs= */ 2);

        final int TEST_USER_GUEST = 902;
        setUpUser(TEST_USER_GUEST, UserInfo.FLAG_GUEST);

        setUpUser(TEST_USER_ID2, NO_USERINFO_FLAGS);

        // Switch to TEST_USER_ID from user 0
        int numberOfUserSwitches = 0;
        addForegroundUserAndContinueUserSwitch(TEST_USER_ID, UserHandle.USER_SYSTEM,
                ++numberOfUserSwitches, false,
                /* expectScheduleBackgroundUserStopping= */ false);
        assertEquals(Arrays.asList(SYSTEM_USER_ID, TEST_USER_ID),
                mUserController.getRunningUsersLU());

        // Switch to TEST_USER_GUEST from TEST_USER_ID
        addForegroundUserAndContinueUserSwitch(TEST_USER_GUEST, TEST_USER_ID,
                ++numberOfUserSwitches, false,
                /* expectScheduleBackgroundUserStopping= */ true);
        assertEquals(Arrays.asList(SYSTEM_USER_ID, TEST_USER_ID, TEST_USER_GUEST),
                mUserController.getRunningUsersLU());

        // Allow the post-switch processing to complete.
        // TEST_USER_ID may be scheduled for stopping, but it shouldn't actually stop since the
        // current user is a Guest.
        assertAndProcessScheduledStopBackgroundUser(true, TEST_USER_ID);
        assertAndProcessScheduledStopBackgroundUser(false, TEST_USER_GUEST);
        assertEquals(Arrays.asList(SYSTEM_USER_ID, TEST_USER_ID, TEST_USER_GUEST),
                mUserController.getRunningUsersLU());

        // Switch to TEST_USER_ID2 from TEST_USER_GUEST
        // Guests are automatically stopped in the background, so it won't be scheduled.
        addForegroundUserAndContinueUserSwitch(TEST_USER_ID2, TEST_USER_GUEST,
                ++numberOfUserSwitches, true,
                /* expectScheduleBackgroundUserStopping= */ false);
        assertEquals(Arrays.asList(SYSTEM_USER_ID, TEST_USER_ID, TEST_USER_ID2),
                mUserController.getRunningUsersLU());

        // Allow the post-switch processing to complete.
        // TEST_USER_ID should *still* be scheduled for stopping, since we skipped stopping it
        // earlier.
        assertAndProcessScheduledStopBackgroundUser(true, TEST_USER_ID);
        assertAndProcessScheduledStopBackgroundUser(false, TEST_USER_GUEST);
        assertAndProcessScheduledStopBackgroundUser(false, TEST_USER_ID2);
        assertEquals(Arrays.asList(SYSTEM_USER_ID, TEST_USER_ID2),
                mUserController.getRunningUsersLU());
    }

    /**
     * Process queued SCHEDULED_STOP_BACKGROUND_USER_MSG message, if expected.
     * @param userId the user we are checking to see whether it is scheduled.
@@ -682,11 +737,11 @@ public class UserControllerTest {
            boolean expectScheduled, @Nullable Integer userId) {
        TestHandler handler = mInjector.mHandler;
        if (expectScheduled) {
            assertTrue(handler.hasMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, userId));
            assertTrue(handler.hasEqualMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, userId));
            handler.removeMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, userId);
            mUserController.processScheduledStopOfBackgroundUser(userId);
        } else {
            assertFalse(handler.hasMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, userId));
            assertFalse(handler.hasEqualMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, userId));
        }
    }

@@ -1534,9 +1589,9 @@ public class UserControllerTest {
        mInjector.mHandler.clearAllRecordedMessages();
        // Verify that continueUserSwitch worked as expected
        continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
        assertEquals(mInjector.mHandler
                        .hasMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, expectedOldUserId),
                expectScheduleBackgroundUserStopping);
        assertEquals(expectScheduleBackgroundUserStopping,
                mInjector.mHandler
                        .hasEqualMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, expectedOldUserId));
        verify(mInjector, times(expectedNumberOfCalls)).dismissUserSwitchingDialog(any());
        continueUserSwitchAssertions(oldUserId, newUserId, expectOldUserStopping,
                expectScheduleBackgroundUserStopping);
@@ -1810,6 +1865,13 @@ public class UserControllerTest {
    }

    private static class TestHandler extends Handler {
        /**
         * Keeps an accessible copy of messages that were queued for us to query.
         *
         * WARNING: queued messages get added to this, but processed/removed messages to NOT
         * automatically get removed. This can lead to confusing bugs. Maybe one day someone will
         * fix this, but in the meantime, this is your warning.
         */
        private final List<Message> mMessages = new ArrayList<>();

        TestHandler(Looper looper) {