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

Commit 6ad393d8 authored by Felipe Leme's avatar Felipe Leme
Browse files

Added evenWhenDisallowed param to removeUserOrSetEphemeral().

UserManager.removeUserOrSetEphemeral() was added primarily to
be used by CarDevicePolicyManager, in which case it should ignore
the no_remove_user restriction. But as it's also used in other
places, it needs a new parameter to define this behavior.

Test: atest FrameworksServicesTests:com.android.server.pm.UserManagerTest#testRemoveUserOrSetEphemeral_evenWhenRestricted
Test: atest FrameworksServicesTests:com.android.server.pm.UserManagerTest # to make sure it didn't break anything
Test: atest android.car.apitest.CarDevicePolicyManagerTest#testRemoveUser_whenDisallowed # on automotive

Bug: 170887769

Change-Id: If797ace64c0fa0262116f649212bbcb1d61e2046
parent 596a4ea4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -86,7 +86,7 @@ interface IUserManager {
    Bundle getApplicationRestrictionsForUser(in String packageName, int userId);
    void setDefaultGuestRestrictions(in Bundle restrictions);
    Bundle getDefaultGuestRestrictions();
    int removeUserOrSetEphemeral(int userId);
    int removeUserOrSetEphemeral(int userId, boolean evenWhenDisallowed);
    boolean markGuestForDeletion(int userId);
    UserInfo findCurrentGuestUser();
    boolean isQuietModeEnabled(int userId);
+6 −2
Original line number Diff line number Diff line
@@ -4036,14 +4036,18 @@ public class UserManager {
     * the current user, then set the user as ephemeral so that it will be removed when it is
     * stopped.
     *
     * @param evenWhenDisallowed when {@code true}, user is removed even if the caller user has the
     * {@link #DISALLOW_REMOVE_USER} or {@link #DISALLOW_REMOVE_MANAGED_PROFILE} restriction
     *
     * @return the {@link RemoveResult} code
     * @hide
     */
    @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
            Manifest.permission.CREATE_USERS})
    public @RemoveResult int removeUserOrSetEphemeral(@UserIdInt int userId) {
    public @RemoveResult int removeUserOrSetEphemeral(@UserIdInt int userId,
            boolean evenWhenDisallowed) {
        try {
            return mService.removeUserOrSetEphemeral(userId);
            return mService.removeUserOrSetEphemeral(userId, evenWhenDisallowed);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
+1 −1
Original line number Diff line number Diff line
@@ -2732,7 +2732,7 @@ class PackageManagerShellCommand extends ShellCommand {
    private int removeUserOrSetEphemeral(IUserManager um, @UserIdInt int userId)
            throws RemoteException {
        Slog.i(TAG, "Removing " + userId + " or set as ephemeral if in use.");
        int result = um.removeUserOrSetEphemeral(userId);
        int result = um.removeUserOrSetEphemeral(userId, /* evenWhenDisallowed= */ false);
        switch (result) {
            case UserManager.REMOVE_RESULT_REMOVED:
                getOutPrintWriter().printf("Success: user %d removed\n", userId);
+10 −8
Original line number Diff line number Diff line
@@ -3842,7 +3842,6 @@ public class UserManagerService extends IUserManager.Stub {
     */
    @Override
    public boolean removeUser(@UserIdInt int userId) {
        Slog.i(LOG_TAG, "removeUser u" + userId, new Exception());
        checkManageOrCreateUsersPermission("Only the system can remove users");

        final String restriction = getUserRemovalRestriction(userId);
@@ -3967,14 +3966,17 @@ public class UserManagerService extends IUserManager.Stub {
    }

    @Override
    public @UserManager.RemoveResult int removeUserOrSetEphemeral(@UserIdInt int userId) {
        Slog.i(LOG_TAG, "removeUserOrSetEphemeral u" + userId);
    public @UserManager.RemoveResult int removeUserOrSetEphemeral(@UserIdInt int userId,
            boolean evenWhenDisallowed) {
        checkManageOrCreateUsersPermission("Only the system can remove users");

        if (!evenWhenDisallowed) {
            final String restriction = getUserRemovalRestriction(userId);
            if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(restriction, false)) {
                Slog.w(LOG_TAG, "Cannot remove user. " + restriction + " is enabled.");
                return UserManager.REMOVE_RESULT_ERROR;
            }
        }
        if (userId == UserHandle.USER_SYSTEM) {
            Slog.e(LOG_TAG, "System user cannot be removed.");
            return UserManager.REMOVE_RESULT_ERROR;
@@ -4002,7 +4004,7 @@ public class UserManagerService extends IUserManager.Stub {
                final int currentUser = ActivityManager.getCurrentUser();
                if (currentUser != userId) {
                    // Attempt to remove the user. This will fail if the user is the current user
                    if (removeUser(userId)) {
                    if (removeUserUnchecked(userId)) {
                        return UserManager.REMOVE_RESULT_REMOVED;
                    }
                }
+33 −10
Original line number Diff line number Diff line
@@ -219,8 +219,8 @@ public final class UserManagerTest {
        mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_USER, /* value= */ true,
                asHandle(currentUser));
        try {
            assertThat(mUserManager.removeUserOrSetEphemeral(user1.id)).isEqualTo(
                    UserManager.REMOVE_RESULT_ERROR);
            assertThat(mUserManager.removeUserOrSetEphemeral(user1.id,
                    /* evenWhenDisallowed= */ false)).isEqualTo(UserManager.REMOVE_RESULT_ERROR);
        } finally {
            mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_USER, /* value= */ false,
                    asHandle(currentUser));
@@ -230,11 +230,34 @@ public final class UserManagerTest {
        assertThat(getUser(user1.id).isEphemeral()).isFalse();
    }

    @MediumTest
    @Test
    public void testRemoveUserOrSetEphemeral_evenWhenRestricted() throws Exception {
        final int currentUser = ActivityManager.getCurrentUser();
        final UserInfo user1 = createUser("User 1", /* flags= */ 0);
        mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_USER, /* value= */ true,
                asHandle(currentUser));
        try {
            synchronized (mUserRemoveLock) {
                assertThat(mUserManager.removeUserOrSetEphemeral(user1.id,
                        /* evenWhenDisallowed= */ true))
                                .isEqualTo(UserManager.REMOVE_RESULT_REMOVED);
                waitForUserRemovalLocked(user1.id);
            }

        } finally {
            mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_USER, /* value= */ false,
                    asHandle(currentUser));
        }

        assertThat(hasUser(user1.id)).isFalse();
    }

    @MediumTest
    @Test
    public void testRemoveUserOrSetEphemeral_systemUserReturnsError() throws Exception {
        assertThat(mUserManager.removeUserOrSetEphemeral(UserHandle.USER_SYSTEM)).isEqualTo(
                UserManager.REMOVE_RESULT_ERROR);
        assertThat(mUserManager.removeUserOrSetEphemeral(UserHandle.USER_SYSTEM,
                /* evenWhenDisallowed= */ false)).isEqualTo(UserManager.REMOVE_RESULT_ERROR);

        assertThat(hasUser(UserHandle.USER_SYSTEM)).isTrue();
    }
@@ -243,8 +266,8 @@ public final class UserManagerTest {
    @Test
    public void testRemoveUserOrSetEphemeral_invalidUserReturnsError() throws Exception {
        assertThat(hasUser(Integer.MAX_VALUE)).isFalse();
        assertThat(mUserManager.removeUserOrSetEphemeral(Integer.MAX_VALUE)).isEqualTo(
                UserManager.REMOVE_RESULT_ERROR);
        assertThat(mUserManager.removeUserOrSetEphemeral(Integer.MAX_VALUE,
                /* evenWhenDisallowed= */ false)).isEqualTo(UserManager.REMOVE_RESULT_ERROR);
    }

    @MediumTest
@@ -255,8 +278,8 @@ public final class UserManagerTest {
        // Switch to the user just created.
        switchUser(user1.id, null, /* ignoreHandle= */ true);

        assertThat(mUserManager.removeUserOrSetEphemeral(user1.id)).isEqualTo(
                UserManager.REMOVE_RESULT_SET_EPHEMERAL);
        assertThat(mUserManager.removeUserOrSetEphemeral(user1.id, /* evenWhenDisallowed= */ false))
                .isEqualTo(UserManager.REMOVE_RESULT_SET_EPHEMERAL);

        assertThat(hasUser(user1.id)).isTrue();
        assertThat(getUser(user1.id).isEphemeral()).isTrue();
@@ -276,8 +299,8 @@ public final class UserManagerTest {
    public void testRemoveUserOrSetEphemeral_nonCurrentUserRemoved() throws Exception {
        final UserInfo user1 = createUser("User 1", /* flags= */ 0);
        synchronized (mUserRemoveLock) {
            assertThat(mUserManager.removeUserOrSetEphemeral(user1.id)).isEqualTo(
                    UserManager.REMOVE_RESULT_REMOVED);
            assertThat(mUserManager.removeUserOrSetEphemeral(user1.id,
                    /* evenWhenDisallowed= */ false)).isEqualTo(UserManager.REMOVE_RESULT_REMOVED);
            waitForUserRemovalLocked(user1.id);
        }