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

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

Merge "Renamed user cmds that change admin privileges." into main

parents 47c1d293 176ca137
Loading
Loading
Loading
Loading
+30 −8
Original line number Diff line number Diff line
@@ -2390,6 +2390,11 @@ public class UserManagerService extends IUserManager.Stub {

    @Override
    public void setUserAdmin(@UserIdInt int userId) {
        setUserAdminInternal(userId);
    }

    // NOTE: split in 2 methods because cmd user needs a boolean but the AIDL one doesn't
    boolean setUserAdminInternal(@UserIdInt int userId) {
        checkManageUserAndAcrossUsersFullPermission("set user admin");
        if (Flags.unicornModeRefactoringForHsumReadOnly()) {
            checkAdminStatusChangeAllowed(userId);
@@ -2405,30 +2410,41 @@ public class UserManagerService extends IUserManager.Stub {
                    // Exit if no user found with that id,
                    mUserJourneyLogger.logNullUserJourneyError(USER_JOURNEY_GRANT_ADMIN,
                            currentUserId, userId, /* userType */ "", /* userFlags */ -1);
                    return;
                    Slogf.w(LOG_TAG, "setUserAdmin(%d) failed: user not found", userId);
                    return false;
                } else if (user.info.isAdmin()) {
                    // Exit if the user is already an admin.
                    mUserJourneyLogger.logUserJourneyFinishWithError(currentUserId,
                        user.info, USER_JOURNEY_GRANT_ADMIN,
                        ERROR_CODE_USER_ALREADY_AN_ADMIN);
                    return;
                    Slogf.w(LOG_TAG, "setUserAdmin(%d): not changed, already admin", userId);
                    return true;
                } else if (user.info.isProfile() || user.info.isGuest()
                        || user.info.isRestricted()) {
                    // Profiles, guest users or restricted profiles cannot become an admin.
                    mUserJourneyLogger.logUserJourneyFinishWithError(currentUserId,
                            user.info, USER_JOURNEY_GRANT_ADMIN, ERROR_CODE_INVALID_USER_TYPE);
                    return;
                    Slogf.w(LOG_TAG, "setUserAdmin(%d) failed: profile, guest, and restricted users"
                            + " cannot be admins (user: %s) ", userId, user.info.toFullString());
                    return false;
                }
                user.info.flags ^= UserInfo.FLAG_ADMIN;
                writeUserLP(user);
            }
        }
        Slogf.i(LOG_TAG, "setUserAdmin(%d): succeeded", userId);
        mUserJourneyLogger.logUserJourneyFinishWithError(currentUserId, user.info,
                USER_JOURNEY_GRANT_ADMIN, ERROR_CODE_UNSPECIFIED);
        return true;
    }

    @Override
    public void revokeUserAdmin(@UserIdInt int userId) {
        revokeUserAdminInternal(userId);
    }

    // NOTE: split in 2 methods because cmd user needs a boolean but the AIDL one doesn't
    boolean revokeUserAdminInternal(@UserIdInt int userId) {
        checkManageUserAndAcrossUsersFullPermission("revoke admin privileges");
        if (Flags.unicornModeRefactoringForHsumReadOnly()) {
            checkAdminStatusChangeAllowed(userId);
@@ -2444,23 +2460,27 @@ public class UserManagerService extends IUserManager.Stub {
                    // Exit if no user found with that id
                    mUserJourneyLogger.logNullUserJourneyError(
                            USER_JOURNEY_REVOKE_ADMIN, currentUserId, userId, "", -1);
                    return;
                    Slogf.w(LOG_TAG, "revokeUserAdmin(%d) failed: user not found", userId);
                    return false;
                } else if (!user.info.isAdmin()) {
                    // Exit if user is not an admin.
                    mUserJourneyLogger.logUserJourneyFinishWithError(currentUserId, user.info,
                            USER_JOURNEY_REVOKE_ADMIN, ERROR_CODE_USER_IS_NOT_AN_ADMIN);
                    return;
                    Slogf.w(LOG_TAG, "revokeUserAdmin(%d): not changed, already not admin", userId);
                    return true;
                } else if ((user.info.flags & UserInfo.FLAG_SYSTEM) != 0) {
                      // System user cannot lose its admin status.
                    Slogf.w(LOG_TAG, "revokeUserAdmin(%d) failed: system user", userId);
                    mUserJourneyLogger.logUserJourneyFinishWithError(currentUserId, user.info,
                            USER_JOURNEY_REVOKE_ADMIN, ERROR_CODE_INVALID_USER_TYPE);
                    return;
                    return false;
                } else if (isNonRemovableLastAdminUserLU(user.info)) {
                    // This is the last admin user and this device requires that it not lose its
                    // admin status.
                    Slogf.w(LOG_TAG, "revokeUserAdmin(%d) failed: user is last admin", userId);
                    mUserJourneyLogger.logUserJourneyFinishWithError(currentUserId, user.info,
                            USER_JOURNEY_REVOKE_ADMIN, ERROR_CODE_USER_IS_LAST_ADMIN);
                    return;
                    return false;
                }
                user.info.flags ^= UserInfo.FLAG_ADMIN;
                writeUserLP(user);
@@ -2468,6 +2488,8 @@ public class UserManagerService extends IUserManager.Stub {
        }
        mUserJourneyLogger.logUserJourneyFinishWithError(currentUserId, user.info,
                USER_JOURNEY_REVOKE_ADMIN, ERROR_CODE_UNSPECIFIED);
        Slogf.i(LOG_TAG, "revokeUserAdmin(%d): succeeded", userId);
        return true;
    }

    /**
+24 −18
Original line number Diff line number Diff line
@@ -126,11 +126,11 @@ public class UserManagerServiceShellCommand extends ShellCommand {
        pw.println("  get-main-user ");
        pw.println("    Displays main user id or message if there is no main user");
        pw.println();
        pw.println("  set-user-admin <USER_ID>");
        pw.println("    Sets the given user as an admin");
        pw.println("  grant-admin <USER_ID>");
        pw.println("    Grants admin privileges to the given user (requires adb root)");
        pw.println();
        pw.println("  revoke-user-admin <USER_ID>");
        pw.println("    Revokes the given user as an admin");
        pw.println("  revoke-admin <USER_ID>");
        pw.println("    Revokes admin privileges from the given user (requires adb root)");
        pw.println();
    }

@@ -162,10 +162,10 @@ public class UserManagerServiceShellCommand extends ShellCommand {
                    return runCanSwitchToHeadlessSystemUser();
                case "is-main-user-permanent-admin":
                    return runIsMainUserPermanentAdmin();
                case "set-user-admin":
                    return runSetUserAdmin();
                case "revoke-user-admin":
                    return runRevokeUserAdmin();
                case "grant-admin":
                    return runGrantAdmin();
                case "revoke-admin":
                    return runRevokeAdmin();
                default:
                    return handleDefaultCommands(cmd);
            }
@@ -570,15 +570,15 @@ public class UserManagerServiceShellCommand extends ShellCommand {
        return 0;
    }

    private int runSetUserAdmin() throws RemoteException {
        return setOrRevokeAdmin(/* set= */ true);
    private int runGrantAdmin() throws RemoteException {
        return grantOrRevokeAdmin(/* grant= */ true);
    }

    private int runRevokeUserAdmin() throws RemoteException {
        return setOrRevokeAdmin(/* set= */ false);
    private int runRevokeAdmin() throws RemoteException {
        return grantOrRevokeAdmin(/* grant= */ false);
    }

    private int setOrRevokeAdmin(boolean set) {
    private int grantOrRevokeAdmin(boolean grant) {
        if (!confirmBuildIsDebuggable() || !confirmIsCalledByRoot()) {
            return -1;
        }
@@ -586,15 +586,21 @@ public class UserManagerServiceShellCommand extends ShellCommand {
        if (userId == UserHandle.USER_NULL) {
            return -1;
        }
        if (set) {
        boolean success;
        if (grant) {
            Slogf.i(LOG_TAG, "Calling setUserAdmin(%d)", userId);
            mService.setUserAdmin(userId);
            success = mService.setUserAdminInternal(userId);
        } else {
            Slogf.i(LOG_TAG, "Calling revokeUserAdmin(%d)", userId);
            mService.revokeUserAdmin(userId);
            success = mService.revokeUserAdminInternal(userId);
        }
        if (success) {
            getOutPrintWriter().println("Success");
            return 0;
        } else {
            getOutPrintWriter().println("Failed");
            return -1;
        }
    }

    /**
+39 −14
Original line number Diff line number Diff line
@@ -1789,9 +1789,9 @@ public final class UserManagerServiceMockedTest {
    public void testSetUserAdmin() {
        addSecondaryUser(USER_ID);

        mUms.setUserAdmin(USER_ID);
        expect.that(mUms.setUserAdminInternal(USER_ID)).isTrue();

        assertThat(mUsers.get(USER_ID).info.isAdmin()).isTrue();
        expect.that(mUsers.get(USER_ID).info.isAdmin()).isTrue();
    }

    @Test
@@ -1815,9 +1815,9 @@ public final class UserManagerServiceMockedTest {
    public void testSetUserAdminFailsForGuest() {
        addGuestUser(USER_ID);

        mUms.setUserAdmin(USER_ID);
        expect.that(mUms.setUserAdminInternal(USER_ID)).isFalse();

        assertThat(mUsers.get(USER_ID).info.isAdmin()).isFalse();
        expect.that(mUsers.get(USER_ID).info.isAdmin()).isFalse();
    }

    @Test
@@ -1825,34 +1825,34 @@ public final class UserManagerServiceMockedTest {
        addSecondaryUser(PARENT_USER_ID);
        addProfile(PROFILE_USER_ID, PARENT_USER_ID, USER_TYPE_PROFILE_MANAGED);

        mUms.setUserAdmin(PROFILE_USER_ID);
        expect.that(mUms.setUserAdminInternal(PROFILE_USER_ID)).isFalse();

        assertThat(mUsers.get(PROFILE_USER_ID).info.isAdmin()).isFalse();
        expect.that(mUsers.get(PROFILE_USER_ID).info.isAdmin()).isFalse();
    }

    @Test
    public void testSetUserAdminFailsForRestrictedProfile() {
        addRestrictedProfile(USER_ID);

        mUms.setUserAdmin(USER_ID);
        expect.that(mUms.setUserAdminInternal(USER_ID)).isFalse();

        assertThat(mUsers.get(USER_ID).info.isAdmin()).isFalse();
        expect.that(mUsers.get(USER_ID).info.isAdmin()).isFalse();
    }

    @Test
    public void testRevokeUserAdmin() {
        addAdminUser(USER_ID);

        mUms.revokeUserAdmin(USER_ID);
        expect.that(mUms.revokeUserAdminInternal(USER_ID)).isTrue();

        assertThat(mUsers.get(USER_ID).info.isAdmin()).isFalse();
        expect.that(mUsers.get(USER_ID).info.isAdmin()).isFalse();
    }

    @Test
    public void testRevokeUserAdminFromNonAdmin() {
        addSecondaryUser(USER_ID);

        mUms.revokeUserAdmin(USER_ID);
        expect.that(mUms.revokeUserAdminInternal(USER_ID)).isTrue();

        assertThat(mUsers.get(USER_ID).info.isAdmin()).isFalse();
    }
@@ -1877,16 +1877,41 @@ public final class UserManagerServiceMockedTest {
    @Test
    @EnableFlags(FLAG_HSU_NOT_ADMIN)
    public void testRevokeUserAdminFailsForSystemUser_nonHsum_hsuNotAdmin() {
        testRevokeUserAdminFailsForSystemUser_nonHsum();
        setSystemUserHeadless(false);
        testRevokeAdminFromSystemUser(/* allowed= */ false);
    }

    @Test
    @DisableFlags(FLAG_HSU_NOT_ADMIN)
    public void testRevokeUserAdminFailsForSystemUser_nonHsum() {
        setSystemUserHeadless(false);
        mUms.revokeUserAdmin(UserHandle.USER_SYSTEM);
        testRevokeAdminFromSystemUser(/* allowed= */ false);
    }

    @Test
    @EnableFlags(FLAG_HSU_NOT_ADMIN)
    public void testRevokeUserAdminSucceedsForSystemUser_hsum_hsuNotAdmin() {
        setSystemUserHeadless(true);
        testRevokeAdminFromSystemUser(/* allowed= */ true);
    }

    @Test
    @DisableFlags(FLAG_HSU_NOT_ADMIN)
    public void testRevokeUserAdminFailsForSystemUser_hsum() {
        setSystemUserHeadless(true);
        testRevokeAdminFromSystemUser(/* allowed= */ false);
    }

    private void testRevokeAdminFromSystemUser(boolean allowed) {
        UserInfo info = mUsers.get(UserHandle.USER_SYSTEM).info;
        // Whether or not it's and admin depends on FLAG_HSU_NOT_ADMIN
        boolean isAdminBefore = info.isAdmin();

        boolean result = mUms.revokeUserAdminInternal(UserHandle.USER_SYSTEM);

        assertThat(mUsers.get(UserHandle.USER_SYSTEM).info.isAdmin()).isTrue();
        expect.withMessage("revokeUserAdmin(USER_SYSTEM)").that(result).isEqualTo(allowed);
        expect.withMessage("USER_SYSTEM.isAdmin() after revokeUserAdmin(...)")
                .that(info.isAdmin()).isEqualTo(isAdminBefore);
    }

    @Test