summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Oli Lan <olilan@google.com> 2023-04-28 18:19:05 +0100
committer Oli Lan <olilan@google.com> 2023-05-02 18:50:17 +0100
commit77660a446bf86ed6c587920cd586b14b2c75afc3 (patch)
treefe9c5a3857f847dad5fd22f32243bc9b78e738fd
parent348bb0e22c5f81e1ce4e5f91abda3752bed969ed (diff)
Delay boot complete broadcast for main user on HSUM.
This fixes an issue where on a HSUM device, the LOCKED_BOOT_COMPLETE broadcast occurs before boot actually completes. We already delay the sending of this broadcast for user 0, but we need to do the same for the main user because otherwise the broadcast is sent at the end of user switch, and the switch to the main user occurs before boot complete. Bug: 279983151 Test: atest UserControllerTest Test: build & flash; observe logs during boot Change-Id: I885954ae57b3c7bc27b2f03b2d2bfa8583c79293
-rw-r--r--services/core/java/com/android/server/am/UserController.java15
-rw-r--r--services/tests/servicestests/src/com/android/server/am/UserControllerTest.java26
2 files changed, 33 insertions, 8 deletions
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index b2fdee7a6f89..419962aa8c38 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -646,7 +646,10 @@ class UserController implements Handler.Callback {
// 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 (!(mInjector.isHeadlessSystemUserMode() && uss.mHandle.isSystem())) {
+ // Similarly, this occurs after a user switch, but in HSUM we switch to the main
+ // user before boot is complete, so again this should be delayed until
+ // onBootComplete if boot has not yet completed.
+ if (mAllowUserUnlocking) {
// ACTION_LOCKED_BOOT_COMPLETED
sendLockedBootCompletedBroadcast(resultTo, userId);
}
@@ -2617,9 +2620,9 @@ class UserController implements Handler.Callback {
// 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.
+ // 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);
@@ -2629,9 +2632,7 @@ class UserController implements Handler.Callback {
if (!mInjector.isHeadlessSystemUserMode()) {
finishUserBoot(uss, resultTo);
} else {
- if (userId == UserHandle.USER_SYSTEM) {
- sendLockedBootCompletedBroadcast(resultTo, userId);
- }
+ 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 d12741ac8bd6..fe838e4ebd74 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -199,6 +199,7 @@ public class UserControllerTest {
mUserController.setAllowUserUnlocking(true);
setUpUser(TEST_USER_ID, NO_USERINFO_FLAGS);
setUpUser(TEST_PRE_CREATED_USER_ID, NO_USERINFO_FLAGS, /* preCreated= */ true, null);
+ mInjector.mRelevantUser = null;
});
}
@@ -232,6 +233,25 @@ public class UserControllerTest {
}
@Test
+ public void testStartUser_background_duringBootHsum() {
+ mockIsHeadlessSystemUserMode(true);
+ mUserController.setAllowUserUnlocking(false);
+ mInjector.mRelevantUser = TEST_USER_ID;
+ boolean started = mUserController.startUser(TEST_USER_ID, USER_START_MODE_BACKGROUND);
+ assertWithMessage("startUser(%s, foreground=false)", TEST_USER_ID).that(started).isTrue();
+
+ // ACTION_LOCKED_BOOT_COMPLETED not sent yet
+ startUserAssertions(newArrayList(Intent.ACTION_USER_STARTED, Intent.ACTION_USER_STARTING),
+ START_BACKGROUND_USER_MESSAGE_CODES);
+
+ mUserController.onBootComplete(null);
+
+ startUserAssertions(newArrayList(Intent.ACTION_USER_STARTED, Intent.ACTION_USER_STARTING,
+ Intent.ACTION_LOCKED_BOOT_COMPLETED),
+ START_BACKGROUND_USER_MESSAGE_CODES);
+ }
+
+ @Test
public void testStartUser_sendsNoBroadcastsForSystemUserInNonHeadlessMode() {
setUpUser(SYSTEM_USER_ID, UserInfo.FLAG_SYSTEM, /* preCreated= */ false,
UserManager.USER_TYPE_FULL_SYSTEM);
@@ -1076,6 +1096,8 @@ public class UserControllerTest {
private final Context mCtx;
+ private Integer mRelevantUser;
+
TestInjector(Context ctx) {
super(null);
mCtx = ctx;
@@ -1162,7 +1184,9 @@ public class UserControllerTest {
boolean sticky, int callingPid, int callingUid, int realCallingUid,
int realCallingPid, int userId) {
Log.i(TAG, "broadcastIntentLocked " + intent);
- mSentIntents.add(intent);
+ if (mRelevantUser == null || mRelevantUser == userId || userId == UserHandle.USER_ALL) {
+ mSentIntents.add(intent);
+ }
return 0;
}