summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/pm/UserManagerInternal.java3
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java108
-rw-r--r--services/java/com/android/server/HsumBootUserInitializer.java15
-rw-r--r--services/java/com/android/server/SystemServer.java5
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java15
5 files changed, 94 insertions, 52 deletions
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index b4d467f96091..eb37302817c5 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -573,5 +573,6 @@ public abstract class UserManagerInternal {
* @throws UserManager.CheckedUserOperationException if no switchable user can be found
*/
- public abstract @UserIdInt int getBootUser() throws UserManager.CheckedUserOperationException;
+ public abstract @UserIdInt int getBootUser(boolean waitUntilSet)
+ throws UserManager.CheckedUserOperationException;
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 334317281a1c..cde8bd7447e6 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -161,7 +161,9 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@@ -278,6 +280,8 @@ public class UserManagerService extends IUserManager.Stub {
static final int WRITE_USER_MSG = 1;
static final int WRITE_USER_DELAY = 2*1000; // 2 seconds
+ private static final long BOOT_USER_SET_TIMEOUT_MS = 300_000;
+
// Tron counters
private static final String TRON_GUEST_CREATED = "users_guest_created";
private static final String TRON_USER_CREATED = "users_user_created";
@@ -333,6 +337,8 @@ public class UserManagerService extends IUserManager.Stub {
/** Indicates that this is the 1st boot after the system user mode was changed by emulation. */
private boolean mUpdatingSystemUserMode;
+ /** Count down latch to wait while boot user is not set.*/
+ private final CountDownLatch mBootUserLatch = new CountDownLatch(1);
/**
* Internal non-parcelable wrapper for UserInfo that is not exposed to other system apps.
*/
@@ -952,18 +958,62 @@ public class UserManagerService extends IUserManager.Stub {
Slogf.i(LOG_TAG, "setBootUser %d", userId);
mBootUser = userId;
}
+ mBootUserLatch.countDown();
}
@Override
public @UserIdInt int getBootUser() {
checkCreateUsersPermission("Get boot user");
try {
- return mLocalService.getBootUser();
+ return getBootUserUnchecked();
} catch (UserManager.CheckedUserOperationException e) {
throw e.toServiceSpecificException();
}
}
+ private @UserIdInt int getBootUserUnchecked() throws UserManager.CheckedUserOperationException {
+ synchronized (mUsersLock) {
+ if (mBootUser != UserHandle.USER_NULL) {
+ final UserData userData = mUsers.get(mBootUser);
+ if (userData != null && userData.info.supportsSwitchToByUser()) {
+ Slogf.i(LOG_TAG, "Using provided boot user: %d", mBootUser);
+ return mBootUser;
+ } else {
+ Slogf.w(LOG_TAG,
+ "Provided boot user cannot be switched to: %d", mBootUser);
+ }
+ }
+ }
+
+ if (isHeadlessSystemUserMode()) {
+ // Return the previous foreground user, if there is one.
+ final int previousUser = getPreviousFullUserToEnterForeground();
+ if (previousUser != UserHandle.USER_NULL) {
+ Slogf.i(LOG_TAG, "Boot user is previous user %d", previousUser);
+ return previousUser;
+ }
+ // No previous user. Return the first switchable user if there is one.
+ synchronized (mUsersLock) {
+ final int userSize = mUsers.size();
+ for (int i = 0; i < userSize; i++) {
+ final UserData userData = mUsers.valueAt(i);
+ if (userData.info.supportsSwitchToByUser()) {
+ int firstSwitchable = userData.info.id;
+ Slogf.i(LOG_TAG,
+ "Boot user is first switchable user %d", firstSwitchable);
+ return firstSwitchable;
+ }
+ }
+ }
+ // No switchable users found. Uh oh!
+ throw new UserManager.CheckedUserOperationException(
+ "No switchable users found", USER_OPERATION_ERROR_UNKNOWN);
+ }
+ // Not HSUM, return system user.
+ return UserHandle.USER_SYSTEM;
+ }
+
+
@Override
public int getPreviousFullUserToEnterForeground() {
checkQueryOrCreateUsersPermission("get previous user");
@@ -7182,47 +7232,29 @@ public class UserManagerService extends IUserManager.Stub {
}
@Override
- public @UserIdInt int getBootUser() throws UserManager.CheckedUserOperationException {
- synchronized (mUsersLock) {
- // TODO(b/242195409): On Automotive, block if boot user not provided.
- if (mBootUser != UserHandle.USER_NULL) {
- final UserData userData = mUsers.get(mBootUser);
- if (userData != null && userData.info.supportsSwitchToByUser()) {
- Slogf.i(LOG_TAG, "Using provided boot user: %d", mBootUser);
- return mBootUser;
- } else {
- Slogf.w(LOG_TAG,
- "Provided boot user cannot be switched to: %d", mBootUser);
+ public @UserIdInt int getBootUser(boolean waitUntilSet)
+ throws UserManager.CheckedUserOperationException {
+ if (waitUntilSet) {
+ final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
+ t.traceBegin("wait-boot-user");
+ try {
+ if (mBootUserLatch.getCount() != 0) {
+ Slogf.d(LOG_TAG,
+ "Sleeping for boot user to be set. "
+ + "Max sleep for Time: %d", BOOT_USER_SET_TIMEOUT_MS);
}
- }
- }
-
- if (isHeadlessSystemUserMode()) {
- // Return the previous foreground user, if there is one.
- final int previousUser = getPreviousFullUserToEnterForeground();
- if (previousUser != UserHandle.USER_NULL) {
- Slogf.i(LOG_TAG, "Boot user is previous user %d", previousUser);
- return previousUser;
- }
- // No previous user. Return the first switchable user if there is one.
- synchronized (mUsersLock) {
- final int userSize = mUsers.size();
- for (int i = 0; i < userSize; i++) {
- final UserData userData = mUsers.valueAt(i);
- if (userData.info.supportsSwitchToByUser()) {
- int firstSwitchable = userData.info.id;
- Slogf.i(LOG_TAG,
- "Boot user is first switchable user %d", firstSwitchable);
- return firstSwitchable;
- }
+ if (!mBootUserLatch.await(BOOT_USER_SET_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ Slogf.w(LOG_TAG, "Boot user not set. Timeout: %d",
+ BOOT_USER_SET_TIMEOUT_MS);
}
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ Slogf.w(LOG_TAG, e, "InterruptedException during wait for boot user.");
}
- // No switchable users found. Uh oh!
- throw new UserManager.CheckedUserOperationException(
- "No switchable users found", USER_OPERATION_ERROR_UNKNOWN);
+ t.traceEnd();
}
- // Not HSUM, return system user.
- return UserHandle.USER_SYSTEM;
+
+ return getBootUserUnchecked();
}
} // class LocalService
diff --git a/services/java/com/android/server/HsumBootUserInitializer.java b/services/java/com/android/server/HsumBootUserInitializer.java
index 50113feb558b..b8958128adf5 100644
--- a/services/java/com/android/server/HsumBootUserInitializer.java
+++ b/services/java/com/android/server/HsumBootUserInitializer.java
@@ -18,6 +18,7 @@ package com.android.server;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.ContentResolver;
+import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.os.Handler;
@@ -27,6 +28,7 @@ import android.os.UserManager;
import android.provider.Settings;
import com.android.server.am.ActivityManagerService;
+import com.android.server.pm.PackageManagerService;
import com.android.server.pm.UserManagerInternal;
import com.android.server.utils.Slogf;
import com.android.server.utils.TimingsTraceAndSlog;
@@ -41,6 +43,7 @@ final class HsumBootUserInitializer {
private final UserManagerInternal mUmi;
private final ActivityManagerService mAms;
+ private final PackageManagerService mPms;
private final ContentResolver mContentResolver;
private final ContentObserver mDeviceProvisionedObserver =
@@ -63,20 +66,23 @@ final class HsumBootUserInitializer {
/** Static factory method for creating a {@link HsumBootUserInitializer} instance. */
public static @Nullable HsumBootUserInitializer createInstance(ActivityManagerService am,
- ContentResolver contentResolver, boolean shouldAlwaysHaveMainUser) {
+ PackageManagerService pms, ContentResolver contentResolver,
+ boolean shouldAlwaysHaveMainUser) {
if (!UserManager.isHeadlessSystemUserMode()) {
return null;
}
return new HsumBootUserInitializer(
LocalServices.getService(UserManagerInternal.class),
- am, contentResolver, shouldAlwaysHaveMainUser);
+ am, pms, contentResolver, shouldAlwaysHaveMainUser);
}
private HsumBootUserInitializer(UserManagerInternal umi, ActivityManagerService am,
- ContentResolver contentResolver, boolean shouldAlwaysHaveMainUser) {
+ PackageManagerService pms, ContentResolver contentResolver,
+ boolean shouldAlwaysHaveMainUser) {
mUmi = umi;
mAms = am;
+ mPms = pms;
mContentResolver = contentResolver;
mShouldAlwaysHaveMainUser = shouldAlwaysHaveMainUser;
}
@@ -131,7 +137,8 @@ final class HsumBootUserInitializer {
try {
t.traceBegin("getBootUser");
- final int bootUser = mUmi.getBootUser();
+ final int bootUser = mUmi.getBootUser(/* waitUntilSet= */ mPms
+ .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, /* version= */0));
t.traceEnd();
t.traceBegin("switchToBootUser-" + bootUser);
switchToBootUser(bootUser);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index edfe95efe7f9..460bed9b6cc6 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -2719,7 +2719,7 @@ public final class SystemServer implements Dumpable {
// on it in their setup, but likely needs to be done after LockSettingsService is ready.
final HsumBootUserInitializer hsumBootUserInitializer =
HsumBootUserInitializer.createInstance(
- mActivityManagerService, mContentResolver,
+ mActivityManagerService, mPackageManagerService, mContentResolver,
context.getResources().getBoolean(R.bool.config_isMainUserPermanentAdmin));
if (hsumBootUserInitializer != null) {
t.traceBegin("HsumBootUserInitializer.init");
@@ -3019,8 +3019,7 @@ public final class SystemServer implements Dumpable {
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
t.traceEnd();
- if (hsumBootUserInitializer != null && !isAutomotive) {
- // TODO(b/261924826): remove isAutomotive check once the workflow is finalized
+ if (hsumBootUserInitializer != null) {
t.traceBegin("HsumBootUserInitializer.systemRunning");
hsumBootUserInitializer.systemRunning(t);
t.traceEnd();
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
index 564893c3c629..e7b3e6f88dce 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -260,7 +260,7 @@ public final class UserManagerServiceTest {
mUms.setBootUser(OTHER_USER_ID);
assertWithMessage("getBootUser")
- .that(mUmi.getBootUser()).isEqualTo(OTHER_USER_ID);
+ .that(mUmi.getBootUser(/* waitUntilSet= */ false)).isEqualTo(OTHER_USER_ID);
}
@Test
@@ -273,7 +273,8 @@ public final class UserManagerServiceTest {
mUms.setBootUser(PROFILE_USER_ID);
assertWithMessage("getBootUser")
- .that(mUmi.getBootUser()).isEqualTo(UserHandle.USER_SYSTEM);
+ .that(mUmi.getBootUser(/* waitUntilSet= */ false))
+ .isEqualTo(UserHandle.USER_SYSTEM);
}
@Test
@@ -289,7 +290,7 @@ public final class UserManagerServiceTest {
// Boot user not switchable so return most recently in foreground.
assertWithMessage("getBootUser")
- .that(mUmi.getBootUser()).isEqualTo(OTHER_USER_ID);
+ .that(mUmi.getBootUser(/* waitUntilSet= */ false)).isEqualTo(OTHER_USER_ID);
}
@Test
@@ -299,7 +300,8 @@ public final class UserManagerServiceTest {
addUser(OTHER_USER_ID);
assertWithMessage("getBootUser")
- .that(mUmi.getBootUser()).isEqualTo(UserHandle.USER_SYSTEM);
+ .that(mUmi.getBootUser(/* waitUntilSet= */ false))
+ .isEqualTo(UserHandle.USER_SYSTEM);
}
@Test
@@ -312,14 +314,15 @@ public final class UserManagerServiceTest {
setLastForegroundTime(OTHER_USER_ID, 2_000_000L);
assertWithMessage("getBootUser")
- .that(mUmi.getBootUser()).isEqualTo(OTHER_USER_ID);
+ .that(mUmi.getBootUser(/* waitUntilSet= */ false)).isEqualTo(OTHER_USER_ID);
}
@Test
public void testGetBootUser_Headless_ThrowsIfOnlySystemUserExists() throws Exception {
setSystemUserHeadless(true);
- assertThrows(UserManager.CheckedUserOperationException.class, () -> mUmi.getBootUser());
+ assertThrows(UserManager.CheckedUserOperationException.class,
+ () -> mUmi.getBootUser(/* waitUntilSet= */ false));
}
private void mockCurrentUser(@UserIdInt int userId) {