summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java2
-rw-r--r--services/core/java/com/android/server/am/UserController.java78
-rw-r--r--services/tests/servicestests/src/com/android/server/am/UserControllerTest.java5
3 files changed, 34 insertions, 51 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b34fe69f5a3e..ee13118f3e5c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5285,7 +5285,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// Tell anyone interested that we are done booting!
SystemProperties.set("sys.boot_completed", "1");
SystemProperties.set("dev.bootcomplete", "1");
- mUserController.sendBootCompleted(
+ mUserController.onBootComplete(
new IIntentReceiver.Stub() {
@Override
public void performReceive(Intent intent, int resultCode,
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 226c63862226..216a48ec699c 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -439,11 +439,6 @@ class UserController implements Handler.Callback {
mUserLru.add(UserHandle.USER_SYSTEM);
mLockPatternUtils = mInjector.getLockPatternUtils();
updateStartedUserArrayLU();
-
- // TODO(b/232452368): currently mAllowUserUnlocking is only used on devices with HSUM
- // (Headless System User Mode), but on master it will be used by all devices (and hence this
- // initial assignment should be removed).
- mAllowUserUnlocking = !UserManager.isHeadlessSystemUserMode();
}
void setInitialConfig(boolean userSwitchUiEnabled, int maxRunningUsers,
@@ -602,8 +597,11 @@ class UserController implements Handler.Callback {
if (!mInjector.getUserManager().isPreCreated(userId)) {
mHandler.sendMessage(mHandler.obtainMessage(REPORT_LOCKED_BOOT_COMPLETE_MSG,
userId, 0));
- // In case of headless system user mode, do not send boot complete broadcast for
- // system user as it is sent by sendBootCompleted call.
+ // The "locked boot complete" broadcast for the system user is supposed be sent when
+ // the device has finished booting. Normally, that is the same time that the system
+ // user transitions to RUNNING_LOCKED. However, in "headless system user mode", the
+ // system user is explicitly started before the device has finished booting. In
+ // that case, we need to wait until onBootComplete() to send the broadcast.
if (!(UserManager.isHeadlessSystemUserMode() && uss.mHandle.isSystem())) {
// ACTION_LOCKED_BOOT_COMPLETED
sendLockedBootCompletedBroadcast(resultTo, userId);
@@ -1808,15 +1806,13 @@ class UserController implements Handler.Callback {
*/
private boolean maybeUnlockUser(@UserIdInt int userId, @Nullable IProgressListener listener) {
- // Delay user unlocking for headless system user mode until the system boot
- // completes. When the system boot completes, the {@link #onBootCompleted()}
- // method unlocks all started users for headless system user mode. This is done
- // to prevent unlocking the users too early during the system boot up.
- // Otherwise, emulated volumes are mounted too early during the system
- // boot up. When vold is reset on boot complete, vold kills all apps/services
- // (that use these emulated volumes) before unmounting the volumes(b/241929666).
- // In the past, these killings have caused the system to become too unstable on
- // some occasions.
+ // We cannot allow users to be unlocked before PHASE_BOOT_COMPLETED, for two reasons.
+ // First, emulated volumes aren't supposed to be used until then; StorageManagerService
+ // assumes it can reset everything upon reaching PHASE_BOOT_COMPLETED. Second, on some
+ // devices the Weaver HAL needed to unlock the user's storage isn't available until sometime
+ // shortly before PHASE_BOOT_COMPLETED. The below logic enforces a consistent flow across
+ // all devices, regardless of their Weaver implementation.
+ //
// Any unlocks that get delayed by this will be done by onBootComplete() instead.
if (!mAllowUserUnlocking) {
Slogf.i(TAG, "Not unlocking user %d yet because boot hasn't completed", userId);
@@ -2424,11 +2420,8 @@ class UserController implements Handler.Callback {
}
}
- /**
- * @deprecated TODO(b/232452368): this logic will be merged into sendBootCompleted
- */
- @Deprecated
- private void onBootCompletedOnHeadlessSystemUserModeDevices() {
+ void onBootComplete(IIntentReceiver resultTo) {
+ // Now that PHASE_BOOT_COMPLETED has been reached, user unlocking is allowed.
setAllowUserUnlocking(true);
// Get a copy of mStartedUsers to use outside of lock.
@@ -2436,37 +2429,30 @@ class UserController implements Handler.Callback {
synchronized (mLock) {
startedUsers = mStartedUsers.clone();
}
+ // In non-headless system user mode, call finishUserBoot() to transition the system user
+ // from the BOOTING state to RUNNING_LOCKED, then to RUNNING_UNLOCKED if possible.
+ //
+ // In headless system user mode, additional users may have been started, and all users
+ // (including the system user) that ever get started are started explicitly. In this case,
+ // we should *not* transition users out of the BOOTING state using finishUserBoot(), as that
+ // doesn't handle issuing the needed onUserStarting() call, and it would just race with an
+ // explicit start anyway. We do, however, need to send the "locked boot complete" broadcast
+ // for the system user, as that got skipped earlier due to the *device* boot not being
+ // complete yet. We also need to try to unlock all started users, since until now explicit
+ // user starts didn't proceed to unlocking, due to it being too early in the device boot.
+ //
// USER_SYSTEM must be processed first. It will be first in the array, as its ID is lowest.
Preconditions.checkArgument(startedUsers.keyAt(0) == UserHandle.USER_SYSTEM);
for (int i = 0; i < startedUsers.size(); i++) {
- UserState uss = startedUsers.valueAt(i);
- int userId = uss.mHandle.getIdentifier();
- Slogf.i(TAG, "Attempting to unlock user %d on boot complete", userId);
- maybeUnlockUser(userId);
- }
- }
-
- void sendBootCompleted(IIntentReceiver resultTo) {
- if (UserManager.isHeadlessSystemUserMode()) {
- // Unlocking users is delayed until boot complete for headless system user mode.
- onBootCompletedOnHeadlessSystemUserModeDevices();
- }
-
- // Get a copy of mStartedUsers to use outside of lock
- SparseArray<UserState> startedUsers;
- synchronized (mLock) {
- startedUsers = mStartedUsers.clone();
- }
- for (int i = 0; i < startedUsers.size(); i++) {
+ int userId = startedUsers.keyAt(i);
UserState uss = startedUsers.valueAt(i);
if (!UserManager.isHeadlessSystemUserMode()) {
finishUserBoot(uss, resultTo);
- } else if (uss.mHandle.isSystem()) {
- // In case of headless system user mode, send only locked boot complete broadcast
- // for system user since finishUserBoot call will be made using other code path;
- // for non-system user, do nothing since finishUserBoot will be called elsewhere.
- sendLockedBootCompletedBroadcast(resultTo, uss.mHandle.getIdentifier());
- return;
+ } else {
+ if (userId == UserHandle.USER_SYSTEM) {
+ sendLockedBootCompletedBroadcast(resultTo, userId);
+ }
+ maybeUnlockUser(userId);
}
}
}
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index 2d2c76c40b10..0b776a3e6642 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -181,11 +181,8 @@ public class UserControllerTest {
doNothing().when(mInjector).taskSupervisorRemoveUser(anyInt());
mockIsUsersOnSecondaryDisplaysEnabled(false);
// All UserController params are set to default.
- mUserController = new UserController(mInjector);
- // TODO(b/232452368): need to explicitly call setAllowUserUnlocking(), otherwise most
- // tests would fail. But we might need to disable it for the onBootComplete() test (i.e,
- // to make sure the users are unlocked at the right time)
+ mUserController = new UserController(mInjector);
mUserController.setAllowUserUnlocking(true);
setUpUser(TEST_USER_ID, NO_USERINFO_FLAGS);
setUpUser(TEST_PRE_CREATED_USER_ID, NO_USERINFO_FLAGS, /* preCreated= */ true, null);