From ef4023a3087d9ffb66639fe5bb380d312d11deb6 Mon Sep 17 00:00:00 2001 From: Adam Bookatz Date: Fri, 14 May 2021 12:36:49 -0700 Subject: [PATCH] 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 --- .../server/pm/PackageManagerService.java | 8 +++++- .../android/server/pm/UserManagerService.java | 26 ++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 14861c2ddf4c4..2831d24a7c719 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -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 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); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index cf181565c82f5..e8897cab14ffc 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -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 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; } }