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

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

Merge "Changed HsumBootUserInitializer so it promotes an admin to main user." into main

parents 8a8e85c4 238c07cc
Loading
Loading
Loading
Loading
+31 −1
Original line number Diff line number Diff line
@@ -200,7 +200,35 @@ public final class HsumBootUserInitializer {
                }
                return;
            }
            if (!promoteAdminUserToMainUserIfNeeded(t)) {
                createInitialUser(/* isMainUser= */ true);
            }
        } finally {
            t.traceEnd();
        }
    }

    private boolean promoteAdminUserToMainUserIfNeeded(TimingsTraceAndSlog t) {
        t.traceBegin("promoteAdminUserToMainUserIfNeeded");
        try {
            // TODO(b/419086491): use getUsers(Filter)
            var users = mUms.getUsers(/* excludeDying= */ true);
            int numberUsers = users.size();
            for (int i = 0; i < numberUsers; i++) {
                var user = users.get(i);
                if (user.isFull() && user.isAdmin()) {
                    Slogf.i(TAG, "Promoting admin user (%d) as main user", user.id);
                    if (!mUms.setMainUser(user.id)) {
                        Slogf.e(TAG, "Failed to promote admin user (%d) as main user", user.id);
                        continue;
                    }
                    return true;
                }
            }
            if (DEBUG) {
                Slogf.d(TAG, "No existing admin user was promoted as main user (users=%s)", users);
            }
            return false;
        } finally {
            t.traceEnd();
        }
@@ -223,9 +251,11 @@ public final class HsumBootUserInitializer {
            t.traceEnd();
        }
    }

    private void createAdminUserIfNeeded(TimingsTraceAndSlog t) {
        t.traceBegin("createAdminUserIfNeeded");
        try {
            // TODO(b/419086491): use getUsers(Filter)
            int[] userIds = mUms.getUserIds();
            if (userIds != null && userIds.length > 1) {
                if (DEBUG) {
+4 −1
Original line number Diff line number Diff line
@@ -106,6 +106,8 @@ public class UserJourneyLogger {
            FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_LIFECYCLE;
    public static final int USER_JOURNEY_DEMOTE_MAIN_USER =
            FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__DEMOTE_MAIN_USER;
    public static final int USER_JOURNEY_PROMOTE_MAIN_USER =
            FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__PROMOTE_MAIN_USER;

    @IntDef(prefix = {"USER_JOURNEY"}, value = {
            USER_JOURNEY_UNKNOWN,
@@ -118,7 +120,8 @@ public class UserJourneyLogger {
            USER_JOURNEY_GRANT_ADMIN,
            USER_JOURNEY_REVOKE_ADMIN,
            USER_JOURNEY_USER_LIFECYCLE,
            USER_JOURNEY_DEMOTE_MAIN_USER
            USER_JOURNEY_DEMOTE_MAIN_USER,
            USER_JOURNEY_PROMOTE_MAIN_USER
    })
    public @interface UserJourney {
    }
+48 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_USER_ALREADY_AN
import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_USER_IS_NOT_AN_ADMIN;
import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_INVALID_USER_TYPE;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_DEMOTE_MAIN_USER;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_PROMOTE_MAIN_USER;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_GRANT_ADMIN;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_REVOKE_ADMIN;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_CREATE;
@@ -8851,6 +8852,11 @@ public class UserManagerService extends IUserManager.Stub {
        return defaultValue;
    }

    /**
     * "Demotes" the main user to be just an admin.
     *
     * <p>Should be called only by {@link HsumBootUserInitializer} and unit tests
     */
    boolean demoteMainUser() {
        if (!android.multiuser.Flags.demoteMainUser()) {
            Slog.d(LOG_TAG, "demoteMainUser(): ignoring because flag is disabled");
@@ -8877,6 +8883,48 @@ public class UserManagerService extends IUserManager.Stub {
        }
    }

    /**
     * Sets the given user as the main user.
     *
     * <p>User must be an admin (and alive), and the current main user must be {@code null}.
     *
     * <p>Should be called only by {@link HsumBootUserInitializer} and unit tests
     *
     * @return whether it succeeded.
     */
    boolean setMainUser(@UserIdInt int userId) {
        if (!android.multiuser.Flags.demoteMainUser()) {
            Slogf.d(LOG_TAG, "setMainUser(%d): ignoring because flag is disabled", userId);
            return false;
        }
        synchronized (mUsersLock) {
            var mainUser = getMainUserLU();
            if (mainUser != null) {
                Slogf.e(LOG_TAG, "setMainUser(%d): already have a main user (%d)", userId,
                        mainUser.id);
                return false;
            }

            var userData = getUserDataLU(userId);
            if (userData == null) {
                Slogf.e(LOG_TAG, "setMainUser(%d): user not found", userId);
                return false;

            }
            if (!userData.info.isAdmin()) {
                Slogf.e(LOG_TAG, "setMainUser(%d): user is not an admin", userId);
                return false;
            }

            Slogf.i(LOG_TAG, "Setting user %d as main user", userId);
            mUserJourneyLogger.logUserJourneyBegin(userId, USER_JOURNEY_PROMOTE_MAIN_USER);
            userData.info.flags |= UserInfo.FLAG_MAIN;
            writeUserLP(userData);
            return true;
        }

    }

    /**
     * Returns true if {@link com.android.internal.R.bool#config_canSwitchToHeadlessSystemUser}
     * is true. If allowed, headless system user can run in the foreground even though
+142 −20
Original line number Diff line number Diff line
@@ -18,13 +18,21 @@ package com.android.server.pm;
import static android.multiuser.Flags.FLAG_CREATE_INITIAL_USER;
import static android.os.UserHandle.USER_NULL;
import static android.os.UserHandle.USER_SYSTEM;
import static android.content.pm.UserInfo.FLAG_ADMIN;
import static android.content.pm.UserInfo.FLAG_FULL;
import static android.content.pm.UserInfo.FLAG_MAIN;
import static android.content.pm.UserInfo.FLAG_SYSTEM;

import static com.android.server.pm.HsumBootUserInitializerTest.ExpectedResult.ADMIN_USER_CREATED;
import static com.android.server.pm.HsumBootUserInitializerTest.ExpectedResult.FIRST_ADMIN_USER_PROMOTED_TO_MAIN;
import static com.android.server.pm.HsumBootUserInitializerTest.ExpectedResult.MAIN_USER_CREATED;
import static com.android.server.pm.HsumBootUserInitializerTest.ExpectedResult.MAIN_USER_DEMOTED;
import static com.android.server.pm.HsumBootUserInitializerTest.ExpectedResult.NO_USER_CREATED;
import static com.android.server.pm.HsumBootUserInitializerTest.ExpectedResult.SECOND_ADMIN_USER_PROMOTED_TO_MAIN;
import static com.android.server.pm.HsumBootUserInitializerTest.InitialUsers.SYSTEM_AND_MAIN;
import static com.android.server.pm.HsumBootUserInitializerTest.InitialUsers.SYSTEM_AND_NON_MAIN;
import static com.android.server.pm.HsumBootUserInitializerTest.InitialUsers.SYSTEM_AND_ADMINS;
import static com.android.server.pm.HsumBootUserInitializerTest.InitialUsers.SYSTEM_AND_ADMINS_FIRST_ADMIN_UNPROMOTABLE;
import static com.android.server.pm.HsumBootUserInitializerTest.InitialUsers.SYSTEM_AND_REGULAR;
import static com.android.server.pm.HsumBootUserInitializerTest.InitialUsers.SYSTEM_ONLY;

import static org.mockito.ArgumentMatchers.any;
@@ -62,8 +70,10 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

// NOTE: rename to HsumBootUserInitializerInitMethodTest if it needs to test other methods
@RunWith(Parameterized.class)
@@ -72,10 +82,25 @@ public final class HsumBootUserInitializerTest {
    private static final String TAG = HsumBootUserInitializerTest.class.getSimpleName();

    @UserIdInt
    private static final int NON_SYSTEM_USER_ID = 42;

    private static final int MAIN_USER_ID = 4;
    @UserIdInt
    private static final int ADMIN_USER_ID = 8;
    @UserIdInt
    private static final int ANOTHER_ADMIN_USER_ID = 15;
    @UserIdInt
    private static final int MAIN_USER_ID = 108;
    private static final int REGULAR_USER_ID = 16;

    // Pre-defined users. NOTE: only setting basic flags and not setting UserType.
    private final UserInfo mHeadlessSystemUser =
            createUser(USER_SYSTEM, FLAG_SYSTEM | FLAG_ADMIN);
    private final UserInfo mMainUser =
            createUser(MAIN_USER_ID, FLAG_FULL | FLAG_MAIN | FLAG_ADMIN);
    private final UserInfo mAdminUser =
            createUser(ADMIN_USER_ID, FLAG_FULL | FLAG_ADMIN);
    private final UserInfo mAnotherAdminUser =
            createUser(ANOTHER_ADMIN_USER_ID, FLAG_FULL | FLAG_ADMIN);
    private final UserInfo mRegularUser =
            createUser(REGULAR_USER_ID, FLAG_FULL);

    @Rule
    public final Expect expect = Expect.create();
@@ -112,19 +137,28 @@ public final class HsumBootUserInitializerTest {
                // shouldAlwaysHaveMainUser false, shouldCreateInitialUser false
                { false, false, SYSTEM_ONLY, NO_USER_CREATED },
                { false, false, SYSTEM_AND_MAIN, MAIN_USER_DEMOTED },
                { false, false, SYSTEM_AND_NON_MAIN, NO_USER_CREATED },
                { false, false, SYSTEM_AND_ADMINS, NO_USER_CREATED },
                { false, false, SYSTEM_AND_ADMINS_FIRST_ADMIN_UNPROMOTABLE, NO_USER_CREATED },
                { false, false, SYSTEM_AND_REGULAR, NO_USER_CREATED },
                // shouldAlwaysHaveMainUser false, shouldCreateInitialUser true
                { false, true, SYSTEM_ONLY, ADMIN_USER_CREATED},
                { false, true, SYSTEM_AND_MAIN, MAIN_USER_DEMOTED },
                { false, true, SYSTEM_AND_NON_MAIN, NO_USER_CREATED},
                { false, true, SYSTEM_AND_ADMINS, NO_USER_CREATED },
                { false, true, SYSTEM_AND_ADMINS_FIRST_ADMIN_UNPROMOTABLE, NO_USER_CREATED },
                { false, true, SYSTEM_AND_REGULAR, NO_USER_CREATED },
                // shouldAlwaysHaveMainUser true, shouldCreateInitialUser false
                { true, false, SYSTEM_ONLY, MAIN_USER_CREATED },
                { true, false, SYSTEM_AND_MAIN, NO_USER_CREATED },
                { true, false, SYSTEM_AND_NON_MAIN, MAIN_USER_CREATED},
                { true, false, SYSTEM_AND_ADMINS, FIRST_ADMIN_USER_PROMOTED_TO_MAIN },
                { true, false, SYSTEM_AND_ADMINS_FIRST_ADMIN_UNPROMOTABLE,
                    SECOND_ADMIN_USER_PROMOTED_TO_MAIN },
                { true, false, SYSTEM_AND_REGULAR, MAIN_USER_CREATED },
                // shouldAlwaysHaveMainUser true, shouldCreateInitialUser true
                { true, true, SYSTEM_ONLY, MAIN_USER_CREATED },
                { true, true, SYSTEM_AND_MAIN, NO_USER_CREATED },
                { true, true, SYSTEM_AND_NON_MAIN, MAIN_USER_CREATED}
                { true, true, SYSTEM_AND_ADMINS_FIRST_ADMIN_UNPROMOTABLE,
                    SECOND_ADMIN_USER_PROMOTED_TO_MAIN },
                { true, true, SYSTEM_AND_REGULAR, MAIN_USER_CREATED }
        });
    }

@@ -144,22 +178,36 @@ public final class HsumBootUserInitializerTest {
    public void setDefaultExpectations() throws Exception {
        switch (mInitialUsers) {
            case SYSTEM_ONLY:
                mockGetUserIds(USER_SYSTEM);
                mockGetUsers(mHeadlessSystemUser);
                mockGetMainUserId(USER_NULL);
                break;
            case SYSTEM_AND_MAIN:
                mockGetUserIds(USER_SYSTEM, MAIN_USER_ID);
                mockGetUsers(mHeadlessSystemUser, mMainUser);
                mockGetMainUserId(MAIN_USER_ID);
                break;
            case SYSTEM_AND_NON_MAIN:
                mockGetUserIds(USER_SYSTEM, NON_SYSTEM_USER_ID);
            case SYSTEM_AND_ADMINS_FIRST_ADMIN_UNPROMOTABLE:
                mockPromoteToMainUserFails(ADMIN_USER_ID);
                // fall through
            case SYSTEM_AND_ADMINS:
                mockGetUsers(mHeadlessSystemUser, mAdminUser, mAnotherAdminUser);
                mockGetMainUserId(USER_NULL);
                break;
            case SYSTEM_AND_REGULAR:
                mockGetUsers(mHeadlessSystemUser, mRegularUser);
                mockGetMainUserId(USER_NULL);
                break;
        }
        // NOTE: need to mock createNewUser() as the user id is used on Slog.
        switch (mExpectedResult) {
            case ADMIN_USER_CREATED:
                mockCreateNewUser(NON_SYSTEM_USER_ID);
                mockCreateNewUser(ADMIN_USER_ID);
                break;
            case FIRST_ADMIN_USER_PROMOTED_TO_MAIN:
                mockPromoteToMainUser(ADMIN_USER_ID);
                break;
            case SECOND_ADMIN_USER_PROMOTED_TO_MAIN:
                mockPromoteToMainUserFails(ADMIN_USER_ID);
                mockPromoteToMainUser(ANOTHER_ADMIN_USER_ID);
                break;
            case MAIN_USER_CREATED:
                mockCreateNewUser(MAIN_USER_ID);
@@ -195,21 +243,36 @@ public final class HsumBootUserInitializerTest {
        switch (mExpectedResult) {
            case ADMIN_USER_CREATED:
                expectAdminUserCreated();
                expectSetBootUserId(NON_SYSTEM_USER_ID);
                expectSetBootUserId(ADMIN_USER_ID);
                expectMainUserNotDemoted();
                break;
            case FIRST_ADMIN_USER_PROMOTED_TO_MAIN:
                expectNoUserCreated();
                expectSetBootUserIdNeverCalled();
                expectAdminPromotedToMainUser(ADMIN_USER_ID);
                expectAdminNotPromotedToMainUser(ANOTHER_ADMIN_USER_ID);
                break;
            case SECOND_ADMIN_USER_PROMOTED_TO_MAIN:
                expectNoUserCreated();
                expectSetBootUserIdNeverCalled();
                // don't need to verify call to ADMIN_USER_ID - it was mocked to return false
                expectAdminPromotedToMainUser(ANOTHER_ADMIN_USER_ID);
                break;
            case MAIN_USER_CREATED:
                expectMainUserCreated();
                expectSetBootUserId(MAIN_USER_ID);
                expectMainUserNotDemoted();
                expectNoAdminPromotedToMainUser();
                break;
            case NO_USER_CREATED:
                expectNoUserCreated();
                expectMainUserNotDemoted();
                expectNoAdminPromotedToMainUser();
                break;
            case MAIN_USER_DEMOTED:
                expectNoUserCreated();
                expectMainUserDemoted();
                expectNoAdminPromotedToMainUser();
                break;
        }
    }
@@ -279,7 +342,6 @@ public final class HsumBootUserInitializerTest {
        expectSetBootUserIdNeverCalled();
    }


    private void expectMainUserDemoted() {
        try {
            verify(mMockUms).demoteMainUser();
@@ -300,6 +362,36 @@ public final class HsumBootUserInitializerTest {
        }
    }

    private void expectAdminPromotedToMainUser(@UserIdInt int userId) {
        try {
            verify(mMockUms).setMainUser(userId);
        } catch (Exception e) {
            String msg = "should have set main user as " + userId;
            Log.e(TAG, msg, e);
            expect.withMessage(msg).fail();
        }
    }

    private void expectAdminNotPromotedToMainUser(@UserIdInt int userId) {
        try {
            verify(mMockUms, never()).setMainUser(userId);
        } catch (Exception e) {
            String msg = "should have not set main user as " + userId;
            Log.e(TAG, msg, e);
            expect.withMessage(msg).fail();
        }
    }

    private void expectNoAdminPromotedToMainUser() {
        try {
            verify(mMockUms, never()).setMainUser(anyInt());
        } catch (Exception e) {
            String msg = "should not have set main user";
            Log.e(TAG, msg, e);
            expect.withMessage(msg).fail();
        }
    }

    private void expectSetBootUserId(@UserIdInt int userId) {
        try {
            verify(mMockUms).setBootUserIdUnchecked(userId);
@@ -334,23 +426,53 @@ public final class HsumBootUserInitializerTest {
        when(mMockUms.getMainUserId()).thenReturn(userId);
    }

    private void mockGetUserIds(@UserIdInt int... userIds) {
        Log.d(TAG, "mockGetUserIds(): " + Arrays.toString(userIds));
    private void mockGetUsers(UserInfo... users) {
        List<UserInfo> asList = new ArrayList<>(users.length);
        int[] userIds = new int[users.length];
        for (int i = 0; i < users.length; i++) {
            var user = users[i];
            asList.add(user);
            userIds[i] = user.id;
        }
        Log.d(TAG, "mockGetUsers(): returning " + asList + " for getUsers(), and "
                + Arrays.toString(userIds) + " to getUserIds()");

        when(mMockUms.getUsers(/* excludingDying= */ true)).thenReturn(asList);
        when(mMockUms.getUserIds()).thenReturn(userIds);
    }

    private void mockPromoteToMainUser(@UserIdInt int userId) {
        Log.d(TAG, "mockPromoteToMainUser(): " + userId);
        when(mMockUms.setMainUser(userId)).thenReturn(true);
    }

    private void mockPromoteToMainUserFails(@UserIdInt int userId) {
        Log.d(TAG, "mockPromoteToMainUserFails(): " + userId);
        when(mMockUms.setMainUser(userId)).thenReturn(false);
    }

    private static UserInfo createUser(@UserIdInt int userId, @UserInfoFlag int flags) {
        return new UserInfo(userId, /* name= */ null, /* iconPath= */ null, flags,
                // Not using userType (for now)
                /* userType= */ "AB Positive");
    }

    // NOTE: enums below must be public to be static imported

    public enum InitialUsers {
        SYSTEM_ONLY,
        SYSTEM_AND_MAIN,
        SYSTEM_AND_NON_MAIN
        SYSTEM_AND_ADMINS,
        SYSTEM_AND_ADMINS_FIRST_ADMIN_UNPROMOTABLE, // hacky case to mock failure
        SYSTEM_AND_REGULAR
    }

    public enum ExpectedResult {
        NO_USER_CREATED,
        MAIN_USER_CREATED,
        MAIN_USER_DEMOTED,
        FIRST_ADMIN_USER_PROMOTED_TO_MAIN,
        SECOND_ADMIN_USER_PROMOTED_TO_MAIN,
        ADMIN_USER_CREATED
    }
}
+138 −3
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_DEMOTE_MAIN_USER;
import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_PROMOTE_MAIN_USER;
import static com.android.server.pm.UserManagerService.BOOT_TO_HSU_FOR_PROVISIONED_DEVICE;
import static com.android.server.pm.UserManagerService.BOOT_TO_PREVIOUS_OR_FIRST_SWITCHABLE_USER;

@@ -1515,6 +1516,113 @@ public final class UserManagerServiceMockedTest {
        assertDefaultSystemUserName(resolvedNameUsers);
    }

    @Test
    @EnableFlags(FLAG_DEMOTE_MAIN_USER)
    public void testSetMainUser() {
        assumeDoesntHaveMainUser();
        var adminUser = createAdminUser();
        int userId = adminUser.id;
        // Make sure the new user is not the main user
        expect.withMessage("getMainUser() before").that(mUms.getMainUserId()).isNotEqualTo(userId);

        expect.withMessage("setMainUser(%s)", userId).that(mUms.setMainUser(userId)).isTrue();

        // Make sure it changed
        expect.withMessage("getMainUser() after").that(mUms.getMainUserId()).isEqualTo(userId);

        // assert journey logged
        expectUserJourneyLogged(userId, USER_JOURNEY_PROMOTE_MAIN_USER);
    }

    @Test
    @EnableFlags(FLAG_DEMOTE_MAIN_USER)
    public void testSetMainUser_hasMainUser() {
        var mainUserId = assumeHasMainUser();
        var adminUser = createAdminUser();
        int userId = adminUser.id;

        expect.withMessage("setMainUser(%s)", userId).that(mUms.setMainUser(userId)).isFalse();

        // Make sure it didn't change
        expect.withMessage("getMainUser()").that(mUms.getMainUserId()).isEqualTo(mainUserId);

        // assert journey not logged
        expectUserJourneyNotLogged(userId, USER_JOURNEY_PROMOTE_MAIN_USER);
    }

    @Test
    @EnableFlags(FLAG_DEMOTE_MAIN_USER)
    public void testSetMainUser_userNotFound() {
        assumeDoesntHaveMainUser();
        int userId = 666;

        expect.withMessage("setMainUser(%s)", userId).that(mUms.setMainUser(userId)).isFalse();

        // Make sure it didn't change
        expect.withMessage("getMainUser()").that(mUms.getMainUserId())
                .isEqualTo(UserHandle.USER_NULL);

        // assert journey not logged
        expectUserJourneyNotLogged(userId, USER_JOURNEY_PROMOTE_MAIN_USER);
    }

    @Test
    @EnableFlags(FLAG_DEMOTE_MAIN_USER)
    public void testSetMainUser_userNotAdmin() {
        assumeDoesntHaveMainUser();
        var regularUser = createRegularUser();
        int userId = regularUser.id;

        expect.withMessage("setMainUser(%s)", userId).that(mUms.setMainUser(userId)).isFalse();

        // Make sure it didn't change
        expect.withMessage("getMainUser()").that(mUms.getMainUserId())
                .isEqualTo(UserHandle.USER_NULL);

        // assert journey not logged
        expectUserJourneyNotLogged(userId, USER_JOURNEY_PROMOTE_MAIN_USER);
    }

    @Test
    @DisableFlags(FLAG_DEMOTE_MAIN_USER)
    public void testSetMainUser_flagDisabled() {
        assumeDoesntHaveMainUser();
        var adminUser = createAdminUser();
        int userId = adminUser.id;
        // Make sure the new user is not the main user
        expect.withMessage("getMainUser() before").that(mUms.getMainUserId()).isNotEqualTo(userId);

        expect.withMessage("setMainUser(%s)", userId).that(mUms.setMainUser(userId)).isFalse();

        // Make sure it didn't change
        expect.withMessage("getMainUser() after").that(mUms.getMainUserId())
                .isEqualTo(UserHandle.USER_NULL);

        // assert journey logged
        expectUserJourneyNotLogged(userId, USER_JOURNEY_PROMOTE_MAIN_USER);
    }

    @Test
    @DisableFlags(FLAG_DEMOTE_MAIN_USER)
    public void testSetMainUser_hasMainUser_flagDisabled() {
        // Should behave the same as when it's enabled (i.e. be a no-op)
        testSetMainUser_hasMainUser();
    }

    @Test
    @DisableFlags(FLAG_DEMOTE_MAIN_USER)
    public void testSetMainUser_userNotFound_flagDisabled() {
        // Should behave the same as when it's enabled (i.e. be a no-op)
        testSetMainUser_userNotFound();
    }

    @Test
    @DisableFlags(FLAG_DEMOTE_MAIN_USER)
    public void testSetMainUser_userNotAdmin_flagDisabled() {
        // Should behave the same as when it's enabled (i.e. be a no-op)
        testSetMainUser_userNotAdmin();
    }

    /**
     * Returns true if the user's XML file has Default restrictions
     * @param userId Id of the user.
@@ -1693,12 +1801,39 @@ public final class UserManagerServiceMockedTest {
                mainUserId == USER_SYSTEM);
    }

    @UserIdInt
    private int assumeHasMainUser() {
        var mainUserId = mUms.getMainUserId();
        assumeFalse("main user exists (id=" + mainUserId + ")", mainUserId == UserHandle.USER_NULL);
        return mainUserId;
    }

    private void assumeDoesntHaveMainUser() {
        var mainUserId = mUms.getMainUserId();
        assumeTrue("main user doesn't exsit", mainUserId == UserHandle.USER_NULL);
    }

    private UserInfo createMainUser() {
        UserInfo mainUser = mUms.createUserWithThrow("The Name is User, Main User",
        UserInfo user = mUms.createUserWithThrow("The Name is User, Main User",
                USER_TYPE_FULL_SECONDARY,
                UserInfo.FLAG_ADMIN | UserInfo.FLAG_FULL | UserInfo.FLAG_MAIN);
        Log.d(TAG, "created main user: " + mainUser);
        return mainUser;
        Log.d(TAG, "created main user: " + user);
        return user;
    }

    private UserInfo createAdminUser() {
        UserInfo user = mUms.createUserWithThrow("The Name is Admin, Admin User",
                USER_TYPE_FULL_SECONDARY,
                UserInfo.FLAG_ADMIN | UserInfo.FLAG_FULL);
        Log.d(TAG, "created admin user: " + user);
        return user;
    }

    private UserInfo createRegularUser() {
        UserInfo user = mUms.createUserWithThrow("The Name is Regular, Regular User",
                USER_TYPE_FULL_SECONDARY, UserInfo.FLAG_FULL);
        Log.d(TAG, "created regular user: " + user);
        return user;
    }

    private UserInfo getSystemUser() {