Slate ephemeral user deletion in systemReady()

After a reboot,
ephemeral users are currently slated for deletion upon
UserManager.onBootPhase(PHASE_ACTIVITY_MANAGER_READY).
However, ephemeral users are already somewhat removed prior
to this, without it being reported, which can cause severe
problems.

Here, we slate ephemeral users for deletion slightly earlier,
in UserManager.systemReady().

Bug: 181291095

Test: atest android.host.multiuser.EphemeralTest#testRebootAndRemoveEphemeralUser_withAccount

Test: manual:
adb shell pm create-user --ephemeral Ephy
switch to the user, connect to the internet, and set up an account
reboot the device (from within that ephemeral user)
observe no boot-loop

Change-Id: I0f60785a1e67945f42d8332ca4d09d06145a3347
This commit is contained in:
Adam Bookatz
2021-05-14 12:36:49 -07:00
parent 87d4c9a9ca
commit ef4023a308
2 changed files with 29 additions and 5 deletions

View File

@@ -23578,7 +23578,13 @@ public class PackageManagerService extends IPackageManager.Stub
mPermissionManager.onSystemReady();
int[] grantPermissionsUserIds = EMPTY_INT_ARRAY;
for (int userId : UserManagerService.getInstance().getUserIds()) {
final List<UserInfo> livingUsers = mInjector.getUserManagerInternal().getUsers(
/* excludePartial= */ true,
/* excludeDying= */ true,
/* excludePreCreated= */ false);
final int livingUserCount = livingUsers.size();
for (int i = 0; i < livingUserCount; i++) {
final int userId = livingUsers.get(i).id;
if (mPmInternal.isPermissionUpgradeNeeded(userId)) {
grantPermissionsUserIds = ArrayUtils.appendInt(
grantPermissionsUserIds, userId);

View File

@@ -699,6 +699,8 @@ public class UserManagerService extends IUserManager.Stub {
mContext.registerReceiver(mConfigurationChangeReceiver,
new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED),
null, mHandler);
markEphemeralUsersForRemoval();
}
/**
@@ -709,17 +711,33 @@ public class UserManagerService extends IUserManager.Stub {
return mLocalService;
}
/** Marks all ephemeral users as slated for deletion. **/
private void markEphemeralUsersForRemoval() {
synchronized (mUsersLock) {
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
final UserInfo ui = mUsers.valueAt(i).info;
if (ui.isEphemeral() && !ui.preCreated && ui.id != UserHandle.USER_SYSTEM) {
addRemovingUserIdLocked(ui.id);
ui.partial = true;
ui.flags |= UserInfo.FLAG_DISABLED;
}
}
}
}
/* Prunes out any partially created or partially removed users. */
void cleanupPartialUsers() {
// Prune out any partially created, partially removed and ephemeral users.
ArrayList<UserInfo> partials = new ArrayList<>();
synchronized (mUsersLock) {
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
UserInfo ui = mUsers.valueAt(i).info;
if ((ui.partial || ui.guestToRemove || (ui.isEphemeral() && !ui.preCreated))
&& i != 0) {
if ((ui.partial || ui.guestToRemove) && ui.id != UserHandle.USER_SYSTEM) {
partials.add(ui);
addRemovingUserIdLocked(ui.id);
if (!mRemovingUserIds.get(ui.id)) {
addRemovingUserIdLocked(ui.id);
}
ui.partial = true;
}
}