Add restriction to remove main user
Add restriction to remove main user when system property MAIN_USER_PERMANENT_ADMIN is set to true. Bug: 260200162 Test: atest UserManagerTest -c Change-Id: Ibce0d8275eed131fad794503924d52ad31b540c2
This commit is contained in:
@@ -10380,6 +10380,7 @@ package android.os {
|
||||
field public static final String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background";
|
||||
field public static final int REMOVE_RESULT_ALREADY_BEING_REMOVED = 2; // 0x2
|
||||
field public static final int REMOVE_RESULT_DEFERRED = 1; // 0x1
|
||||
field public static final int REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN = -5; // 0xfffffffb
|
||||
field public static final int REMOVE_RESULT_ERROR_SYSTEM_USER = -4; // 0xfffffffc
|
||||
field public static final int REMOVE_RESULT_ERROR_UNKNOWN = -1; // 0xffffffff
|
||||
field public static final int REMOVE_RESULT_ERROR_USER_NOT_FOUND = -3; // 0xfffffffd
|
||||
|
||||
@@ -1823,6 +1823,15 @@ public class UserManager {
|
||||
@SystemApi
|
||||
public static final int REMOVE_RESULT_ERROR_SYSTEM_USER = -4;
|
||||
|
||||
/**
|
||||
* A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
|
||||
* user being removed is a {@link UserInfo#FLAG_MAIN} user and can't be removed because
|
||||
* system property {@link com.android.internal.R.bool.isMainUserPermanentAdmin} is true.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public static final int REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN = -5;
|
||||
|
||||
/**
|
||||
* Possible response codes from {@link #removeUserWhenPossible(UserHandle, boolean)}.
|
||||
*
|
||||
@@ -1835,6 +1844,7 @@ public class UserManager {
|
||||
REMOVE_RESULT_ERROR_USER_RESTRICTION,
|
||||
REMOVE_RESULT_ERROR_USER_NOT_FOUND,
|
||||
REMOVE_RESULT_ERROR_SYSTEM_USER,
|
||||
REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN,
|
||||
REMOVE_RESULT_ERROR_UNKNOWN,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@@ -5224,8 +5234,9 @@ public class UserManager {
|
||||
* @return the {@link RemoveResult} code: {@link #REMOVE_RESULT_REMOVED},
|
||||
* {@link #REMOVE_RESULT_DEFERRED}, {@link #REMOVE_RESULT_ALREADY_BEING_REMOVED},
|
||||
* {@link #REMOVE_RESULT_ERROR_USER_RESTRICTION}, {@link #REMOVE_RESULT_ERROR_USER_NOT_FOUND},
|
||||
* {@link #REMOVE_RESULT_ERROR_SYSTEM_USER}, or {@link #REMOVE_RESULT_ERROR_UNKNOWN}. All error
|
||||
* codes have negative values.
|
||||
* {@link #REMOVE_RESULT_ERROR_SYSTEM_USER},
|
||||
* {@link #REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN}, or
|
||||
* {@link #REMOVE_RESULT_ERROR_UNKNOWN}. All error codes have negative values.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -3012,6 +3012,10 @@ class PackageManagerShellCommand extends ShellCommand {
|
||||
case UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED:
|
||||
getOutPrintWriter().printf("Success: user %d is already being removed\n", userId);
|
||||
return 0;
|
||||
case UserManager.REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN:
|
||||
getOutPrintWriter().printf("Error: user %d is a permanent admin main user\n",
|
||||
userId);
|
||||
return 1;
|
||||
default:
|
||||
getErrPrintWriter().printf("Error: couldn't remove or mark ephemeral user id %d\n",
|
||||
userId);
|
||||
|
||||
@@ -5426,6 +5426,12 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isNonRemovableMainUser(userData.info)) {
|
||||
Slog.e(LOG_TAG, "Main user cannot be removed when "
|
||||
+ "it's a permanent admin user.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mRemovingUserIds.get(userId)) {
|
||||
Slog.e(LOG_TAG, TextUtils.formatSimple(
|
||||
"User %d is already scheduled for removal.", userId));
|
||||
@@ -5530,6 +5536,12 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
return UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (isNonRemovableMainUser(userData.info)) {
|
||||
Slog.e(LOG_TAG, "Main user cannot be removed when "
|
||||
+ "it's a permanent admin user.");
|
||||
return UserManager.REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN;
|
||||
}
|
||||
|
||||
if (mRemovingUserIds.get(userId)) {
|
||||
Slog.e(LOG_TAG, "User " + userId + " is already scheduled for removal.");
|
||||
return UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED;
|
||||
@@ -6748,7 +6760,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
public void removeAllUsers() {
|
||||
if (UserHandle.USER_SYSTEM == getCurrentUserId()) {
|
||||
// Remove the non-system users straight away.
|
||||
removeNonSystemUsers();
|
||||
removeAllUsersExceptSystemAndPermanentAdminMain();
|
||||
} else {
|
||||
// Switch to the system user first and then remove the other users.
|
||||
BroadcastReceiver userSwitchedReceiver = new BroadcastReceiver() {
|
||||
@@ -6760,7 +6772,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
return;
|
||||
}
|
||||
mContext.unregisterReceiver(this);
|
||||
removeNonSystemUsers();
|
||||
removeAllUsersExceptSystemAndPermanentAdminMain();
|
||||
}
|
||||
};
|
||||
IntentFilter userSwitchedFilter = new IntentFilter();
|
||||
@@ -7113,14 +7125,14 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
throw new UserManager.CheckedUserOperationException(message, userOperationResult);
|
||||
}
|
||||
|
||||
/* Remove all the users except of the system one. */
|
||||
private void removeNonSystemUsers() {
|
||||
/* Remove all the users except the system and permanent admin main.*/
|
||||
private void removeAllUsersExceptSystemAndPermanentAdminMain() {
|
||||
ArrayList<UserInfo> usersToRemove = new ArrayList<>();
|
||||
synchronized (mUsersLock) {
|
||||
final int userSize = mUsers.size();
|
||||
for (int i = 0; i < userSize; i++) {
|
||||
UserInfo ui = mUsers.valueAt(i).info;
|
||||
if (ui.id != UserHandle.USER_SYSTEM) {
|
||||
if (ui.id != UserHandle.USER_SYSTEM && !isNonRemovableMainUser(ui)) {
|
||||
usersToRemove.add(ui);
|
||||
}
|
||||
}
|
||||
@@ -7249,4 +7261,22 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
return mAmInternal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, when user has {@link UserInfo#FLAG_MAIN} and system property
|
||||
* {@link com.android.internal.R.bool.isMainUserPermanentAdmin} is true.
|
||||
*/
|
||||
private boolean isNonRemovableMainUser(UserInfo userInfo) {
|
||||
return userInfo.isMain() && isMainUserPermanentAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, when {@link com.android.internal.R.bool.isMainUserPermanentAdmin} is true.
|
||||
* If the main user is a permanent admin user it can't be deleted
|
||||
* or downgraded to non-admin status.
|
||||
*/
|
||||
private static boolean isMainUserPermanentAdmin() {
|
||||
return Resources.getSystem()
|
||||
.getBoolean(com.android.internal.R.bool.config_isMainUserPermanentAdmin);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -371,6 +371,29 @@ public final class UserManagerTest {
|
||||
assertThat(hasUser(UserHandle.USER_SYSTEM)).isTrue();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
@Test
|
||||
public void testRemoveUserWhenPossible_permanentAdminMainUserReturnsError() throws Exception {
|
||||
assumeHeadlessModeEnabled();
|
||||
assumeTrue("Main user is not permanent admin", isMainUserPermanentAdmin());
|
||||
|
||||
int currentUser = ActivityManager.getCurrentUser();
|
||||
final UserInfo otherUser = createUser("User 1", /* flags= */ UserInfo.FLAG_ADMIN);
|
||||
UserHandle mainUser = mUserManager.getMainUser();
|
||||
|
||||
switchUser(otherUser.id, null, true);
|
||||
|
||||
assertThat(mUserManager.removeUserWhenPossible(mainUser,
|
||||
/* overrideDevicePolicy= */ false))
|
||||
.isEqualTo(UserManager.REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN);
|
||||
|
||||
|
||||
assertThat(hasUser(mainUser.getIdentifier())).isTrue();
|
||||
|
||||
// Switch back to the starting user.
|
||||
switchUser(currentUser, null, true);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
@Test
|
||||
public void testRemoveUserWhenPossible_invalidUserReturnsError() throws Exception {
|
||||
@@ -1420,4 +1443,10 @@ public final class UserManagerTest {
|
||||
private static UserHandle asHandle(int userId) {
|
||||
return new UserHandle(userId);
|
||||
}
|
||||
|
||||
private boolean isMainUserPermanentAdmin() {
|
||||
return Resources.getSystem()
|
||||
.getBoolean(com.android.internal.R.bool.config_isMainUserPermanentAdmin);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user