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

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

Merge "Add getUserRemovability() to UserManager" into main

parents dbaa1aa9 a0b86b17
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ interface IUserManager {
    void evictCredentialEncryptionKey(int userId);
    boolean removeUser(int userId);
    boolean removeUserEvenWhenDisallowed(int userId);
    int getUserRemovability(int userId);
    void setUserName(int userId, String name);
    void setUserIcon(int userId, in Bitmap icon);
    ParcelFileDescriptor getUserIcon(int userId);
+30 −0
Original line number Diff line number Diff line
@@ -6442,6 +6442,36 @@ public class UserManager {
        return result >= 0;
    }

    /**
     * Returns whether the specified user is removable.
     *
     * <p>Removing a user is not allowed in the following cases:
     * <ol>
     * <li>the user is system user
     * <li>the user is not found
     * <li>the user is permanent admin main user
     * <li>the user is already being removed
     * <li>the user is a non-removable last admin user
     *
     * </ol>
     *
     * @return A {@link RemoveResult} flag indicating if the user can be removed, one of
     * {@link #REMOVE_RESULT_USER_IS_REMOVABLE},
     * {@link #REMOVE_RESULT_ERROR_SYSTEM_USER},
     * {@link #REMOVE_RESULT_ERROR_USER_NOT_FOUND},
     * {@link #REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN},
     * {@link #REMOVE_RESULT_ALREADY_BEING_REMOVED},
     * {@link #REMOVE_RESULT_ERROR_LAST_ADMIN_USER}.
     * @hide
     */
    public @RemoveResult int getUserRemovability(@UserIdInt int userId) {
        try {
            return mService.getUserRemovability(userId);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Updates the user's name.
     *
+40 −13
Original line number Diff line number Diff line
@@ -3505,8 +3505,8 @@ public class UserManagerService extends IUserManager.Stub {
        synchronized (mPackagesLock) {
            final UserData userData;
            synchronized (mUsersLock) {
                final int userRemovability =
                        getUserRemovabilityLockedLU(userId, "set as ephemeral");
                final int userRemovability = getUserRemovabilityLockedLU(userId);
                logRemoveResultError(userRemovability, userId, "set as ephemeral");
                if (userRemovability != UserManager.REMOVE_RESULT_USER_IS_REMOVABLE) {
                    return userRemovability;
                }
@@ -6942,7 +6942,8 @@ public class UserManagerService extends IUserManager.Stub {
        final boolean isProfile;
        final IntArray profileIds;
        synchronized (mUsersLock) {
            final int userRemovability = getUserRemovabilityLockedLU(userId, "removed");
            final int userRemovability = getUserRemovabilityLockedLU(userId);
            logRemoveResultError(userRemovability, userId, "removed");
            if (userRemovability != UserManager.REMOVE_RESULT_USER_IS_REMOVABLE) {
                return UserManager.isRemoveResultSuccessful(userRemovability);
            }
@@ -7028,7 +7029,8 @@ public class UserManagerService extends IUserManager.Stub {
            final UserData userData;
            synchronized (mPackagesLock) {
                synchronized (mUsersLock) {
                    final int userRemovability = getUserRemovabilityLockedLU(userId, "removed");
                    final int userRemovability = getUserRemovabilityLockedLU(userId);
                    logRemoveResultError(userRemovability, userId, "removed");
                    if (userRemovability != UserManager.REMOVE_RESULT_USER_IS_REMOVABLE) {
                        return UserManager.isRemoveResultSuccessful(userRemovability);
                    }
@@ -7156,34 +7158,48 @@ public class UserManagerService extends IUserManager.Stub {
     */
    @GuardedBy("mUsersLock")
    @VisibleForTesting
    @UserManager.RemoveResult int getUserRemovabilityLockedLU(@UserIdInt int userId, String msg) {
    @UserManager.RemoveResult int getUserRemovabilityLockedLU(@UserIdInt int userId) {
        if (userId == UserHandle.USER_SYSTEM) {
            Slogf.e(LOG_TAG, "User %d can not be %s, system user cannot be removed.", userId, msg);
            return UserManager.REMOVE_RESULT_ERROR_SYSTEM_USER;
        }
        final UserData userData = mUsers.get(userId);
        if (userData == null) {
            Slogf.e(LOG_TAG, "User %d can not be %s, invalid user id provided.", userId, msg);
            return UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND;
        }
        if (isNonRemovableMainUser(userData.info)) {
            Slogf.e(LOG_TAG, "User %d can not be %s, main user cannot be removed when it's a"
                    + " permanent admin user.", userId, msg);
            return UserManager.REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN;
        }
        if (mRemovingUserIds.get(userId)) {
            Slogf.w(LOG_TAG, "User %d can not be %s, it is already scheduled for removal.", userId,
                    msg);
            return UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED;
        }
        if (isNonRemovableLastAdminUserLU(userData.info)) {
            Slogf.e(LOG_TAG, "User %d can not be %s, last admin user cannot be removed.", userId,
                    msg);
            return UserManager.REMOVE_RESULT_ERROR_LAST_ADMIN_USER;
        }
        return UserManager.REMOVE_RESULT_USER_IS_REMOVABLE;
    }

    private void logRemoveResultError(@UserManager.RemoveResult int result, @UserIdInt int userId,
            String action) {
        switch (result) {
            case UserManager.REMOVE_RESULT_ERROR_SYSTEM_USER ->
                Slogf.e(LOG_TAG, "User %d can not be %s, system user cannot be removed.", userId,
                        action);
            case UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND ->
                Slogf.e(LOG_TAG, "User %d can not be %s, invalid user id provided.", userId,
                        action);
            case UserManager.REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN ->
                Slogf.e(LOG_TAG, "User %d can not be %s, main user cannot be removed when it's a"
                        + " permanent admin user.", userId, action);
            case UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED ->
                Slogf.w(LOG_TAG, "User %d can not be %s, it is already scheduled for removal.",
                        userId, action);
            case UserManager.REMOVE_RESULT_ERROR_LAST_ADMIN_USER ->
                Slogf.e(LOG_TAG, "User %d can not be %s, last admin user cannot be removed.",
                        userId, action);
            default -> {}
        }
    }

    private void finishRemoveUser(final @UserIdInt int userId) {
        Slog.i(LOG_TAG, "finishRemoveUser " + userId);

@@ -9053,6 +9069,17 @@ public class UserManagerService extends IUserManager.Stub {
        return userInfo.isMain() && isMainUserPermanentAdmin();
    }

    @Override
    public @UserManager.RemoveResult int getUserRemovability(@UserIdInt int userId) {
        if (!Flags.disallowRemovingLastAdminUser()) {
            throw new UnsupportedOperationException(
                    "aconfig flag android.multiuser.disallow_removing_last_admin_user not enabled");
        }
        synchronized (mUsersLock) {
            return getUserRemovabilityLockedLU(userId);
        }
    }

    /**
     * Returns true if we must not delete this user or revoke its admin status because it is the
     * last admin user on a device that requires there to always be at least one admin.
+1 −1
Original line number Diff line number Diff line
@@ -2425,7 +2425,7 @@ public final class UserManagerServiceMockedTest {

    private void expectGetUserRemovability(String who, @UserIdInt int userId,
            @RemoveResult int expectedResult) {
        int actualResult = mUms.getUserRemovabilityLockedLU(userId, /* msg= */ "not used");
        int actualResult = mUms.getUserRemovabilityLockedLU(userId);
        expect.withMessage("getUserRemovabilityLockedLU(%s) (where user is %s, %s=%s, and %s=%s)",
                who, userId,
                expectedResult, removeResultToString(expectedResult),