diff options
| author | 2023-02-01 19:38:08 -0800 | |
|---|---|---|
| committer | 2023-02-02 10:38:29 -0800 | |
| commit | e5a06ca619fb37bc20e5b8d38ab8f2c19f9257cb (patch) | |
| tree | 6a1cbef2964885a8eb6c67923b2aaff418c405f1 /services/java | |
| parent | c0bcd9afb8a79393ece6d920f0e3631ff93f7fc0 (diff) | |
HsumBootUserInitializer creates MainUser earlier
Previously, on first boot, an HSUM device would unlock the system user,
then create the MainUser (if needed), and then switch to the boot user,
all at around the same time.
This cl reorders these events and spreads them out:
* first, early on (just prior to PHASE_SYSTEM_SERVICES_READY), the
MainUser is created (if needed)
* later (after PHASE_THIRD_PARTY_APPS_CAN_START), the system user is
unlocked
* then we promptly switch to the boot user. This needs to be after
PHASE_THIRD_PARTY_APPS_CAN_START since special apps may designate a
different boot user.
This will ensure that the MainUser can be retrieved much earlier on by
system services whose operations may depend on it.
Also, the structure of BootUserInitializer is renamed to better reflect
its role, and its structure is modified slightly to allow SystemServer
to use it more easily.
Bug: 262438904
Bug: 266098768
Test: flashed HSUM and confirmed that MainUser was created as needed
Test: atest FrameworksMockingServicesTests:com.android.server.pm.UserManagerServiceTest
Change-Id: Ic84b1be538234b2bfde3ae792c9a923ace55f24c
Diffstat (limited to 'services/java')
| -rw-r--r-- | services/java/com/android/server/HsumBootUserInitializer.java (renamed from services/java/com/android/server/BootUserInitializer.java) | 80 | ||||
| -rw-r--r-- | services/java/com/android/server/SystemServer.java | 21 |
2 files changed, 87 insertions, 14 deletions
diff --git a/services/java/com/android/server/BootUserInitializer.java b/services/java/com/android/server/HsumBootUserInitializer.java index 3d71739924f7..cc6c36ef1ed5 100644 --- a/services/java/com/android/server/BootUserInitializer.java +++ b/services/java/com/android/server/HsumBootUserInitializer.java @@ -15,8 +15,10 @@ */ package com.android.server; +import android.annotation.Nullable; import android.annotation.UserIdInt; import android.content.ContentResolver; +import android.content.pm.UserInfo; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -30,22 +32,43 @@ import com.android.server.utils.TimingsTraceAndSlog; * Class responsible for booting the device in the proper user on headless system user mode. * */ -// TODO(b/204091126): STOPSHIP - provide proper APIs -final class BootUserInitializer { +final class HsumBootUserInitializer { - private static final String TAG = BootUserInitializer.class.getSimpleName(); - - // TODO(b/204091126): STOPSHIP - set to false or dynamic value - private static final boolean DEBUG = true; + private static final String TAG = HsumBootUserInitializer.class.getSimpleName(); + private final UserManagerInternal mUmi; private final ActivityManagerService mAms; private final ContentResolver mContentResolver; - BootUserInitializer(ActivityManagerService am, ContentResolver contentResolver) { + /** Whether this device should always have a non-removable MainUser, including at first boot. */ + private final boolean mShouldAlwaysHaveMainUser; + + /** Static factory method for creating a {@link HsumBootUserInitializer} instance. */ + public static @Nullable HsumBootUserInitializer createInstance(ActivityManagerService am, + ContentResolver contentResolver, boolean shouldAlwaysHaveMainUser) { + + if (!UserManager.isHeadlessSystemUserMode()) { + return null; + } + return new HsumBootUserInitializer( + LocalServices.getService(UserManagerInternal.class), + am, contentResolver, shouldAlwaysHaveMainUser); + } + + private HsumBootUserInitializer(UserManagerInternal umi, ActivityManagerService am, + ContentResolver contentResolver, boolean shouldAlwaysHaveMainUser) { + mUmi = umi; mAms = am; mContentResolver = contentResolver; + this.mShouldAlwaysHaveMainUser = shouldAlwaysHaveMainUser; } + /** + * Initialize this object, and create MainUser if needed. + * + * Should be called before PHASE_SYSTEM_SERVICES_READY as services' setups may require MainUser, + * but probably after PHASE_LOCK_SETTINGS_READY since that may be needed for user creation. + */ public void init(TimingsTraceAndSlog t) { Slogf.i(TAG, "init())"); @@ -53,17 +76,56 @@ final class BootUserInitializer { // this class or the setup wizard app provisionHeadlessSystemUser(); + if (mShouldAlwaysHaveMainUser) { + t.traceBegin("createMainUserIfNeeded"); + createMainUserIfNeeded(); + t.traceEnd(); + } + } + + private void createMainUserIfNeeded() { + int mainUser = mUmi.getMainUserId(); + if (mainUser != UserHandle.USER_NULL) { + Slogf.d(TAG, "Found existing MainUser, userId=%d", mainUser); + return; + } + + Slogf.d(TAG, "Creating a new MainUser"); + try { + final UserInfo newInitialUser = mUmi.createUserEvenWhenDisallowed( + /* name= */ null, // null will appear as "Owner" in on-demand localisation + UserManager.USER_TYPE_FULL_SECONDARY, + UserInfo.FLAG_ADMIN | UserInfo.FLAG_MAIN, + /* disallowedPackages= */ null, + /* token= */ null); + if (newInitialUser == null) { + Slogf.wtf(TAG, "Initial bootable MainUser creation failed: returned null"); + } else { + Slogf.i(TAG, "Successfully created MainUser, userId=%d", newInitialUser.id); + } + } catch (UserManager.CheckedUserOperationException e) { + Slogf.wtf(TAG, "Initial bootable MainUser creation failed", e); + } + } + + /** + * Put the device into the correct user state: unlock the system and switch to the boot user. + * + * Should only call once PHASE_THIRD_PARTY_APPS_CAN_START is reached to ensure that privileged + * apps have had the chance to set the boot user, if applicable. + */ + public void systemRunning(TimingsTraceAndSlog t) { unlockSystemUser(t); try { t.traceBegin("getBootUser"); - int bootUser = LocalServices.getService(UserManagerInternal.class).getBootUser(); + final int bootUser = mUmi.getBootUser(); t.traceEnd(); t.traceBegin("switchToBootUser-" + bootUser); switchToBootUser(bootUser); t.traceEnd(); } catch (UserManager.CheckedUserOperationException e) { - Slogf.wtf(TAG, "Failed to created boot user", e); + Slogf.wtf(TAG, "Failed to switch to boot user since there isn't one."); } } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index a15c6d288cfd..d22be9ec01d0 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -75,7 +75,6 @@ import android.os.StrictMode; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; -import android.os.UserManager; import android.os.storage.IStorageManager; import android.provider.DeviceConfig; import android.provider.Settings; @@ -2694,6 +2693,18 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startBootPhase(t, SystemService.PHASE_LOCK_SETTINGS_READY); t.traceEnd(); + // Create initial user if needed, which should be done early since some system services rely + // on it in their setup, but likely needs to be done after LockSettingsService is ready. + final HsumBootUserInitializer hsumBootUserInitializer = + HsumBootUserInitializer.createInstance( + mActivityManagerService, mContentResolver, + context.getResources().getBoolean(R.bool.config_isMainUserPermanentAdmin)); + if (hsumBootUserInitializer != null) { + t.traceBegin("HsumBootUserInitializer.init"); + hsumBootUserInitializer.init(t); + t.traceEnd(); + } + t.traceBegin("StartBootPhaseSystemServicesReady"); mSystemServiceManager.startBootPhase(t, SystemService.PHASE_SYSTEM_SERVICES_READY); t.traceEnd(); @@ -2961,10 +2972,10 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startBootPhase(t, SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); t.traceEnd(); - if (UserManager.isHeadlessSystemUserMode() && !isAutomotive) { - // TODO(b/204091126): remove isAutomotive check once the workflow is finalized - t.traceBegin("BootUserInitializer"); - new BootUserInitializer(mActivityManagerService, mContentResolver).init(t); + if (hsumBootUserInitializer != null && !isAutomotive) { + // TODO(b/261924826): remove isAutomotive check once the workflow is finalized + t.traceBegin("HsumBootUserInitializer.systemRunning"); + hsumBootUserInitializer.systemRunning(t); t.traceEnd(); } |