diff --git a/core/java/com/android/internal/widget/LockSettingsInternal.java b/core/java/com/android/internal/widget/LockSettingsInternal.java index 5b08bb1f42d36..6063c90d6ab9e 100644 --- a/core/java/com/android/internal/widget/LockSettingsInternal.java +++ b/core/java/com/android/internal/widget/LockSettingsInternal.java @@ -53,6 +53,12 @@ public abstract class LockSettingsInternal { public static final int ARM_REBOOT_ERROR_STORE_ESCROW_KEY = 7; // TODO(b/183140900) split store escrow key errors into detailed ones. + /** + * This is called when Weaver is guaranteed to be available (if the device supports Weaver). + * It does any synthetic password related work that was delayed from earlier in the boot. + */ + public abstract void onThirdPartyAppsStarted(); + /** * Unlocks the credential-encrypted storage for the given user if the user is not secured, i.e. * doesn't have an LSKF. diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 92b685c78d980..d02faad1956e9 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -248,14 +248,14 @@ public class LockSettingsService extends ILockSettings.Stub { // Locking order is mUserCreationAndRemovalLock -> mSpManager. private final Object mUserCreationAndRemovalLock = new Object(); - // These two arrays are only used at boot time. To save memory, they are set to null when - // PHASE_BOOT_COMPLETED is reached. + // These two arrays are only used at boot time. To save memory, they are set to null near the + // end of the boot, when onThirdPartyAppsStarted() is called. @GuardedBy("mUserCreationAndRemovalLock") private SparseIntArray mEarlyCreatedUsers = new SparseIntArray(); @GuardedBy("mUserCreationAndRemovalLock") private SparseIntArray mEarlyRemovedUsers = new SparseIntArray(); @GuardedBy("mUserCreationAndRemovalLock") - private boolean mBootComplete; + private boolean mThirdPartyAppsStarted; // Current password metrics for all secured users on the device. Updated when user unlocks the // device or changes password. Removed when user is stopped. @@ -297,16 +297,9 @@ public class LockSettingsService extends ILockSettings.Stub { @Override public void onBootPhase(int phase) { super.onBootPhase(phase); - switch (phase) { - case PHASE_ACTIVITY_MANAGER_READY: - mLockSettingsService.migrateOldDataAfterSystemReady(); - mLockSettingsService.loadEscrowData(); - break; - case PHASE_BOOT_COMPLETED: - mLockSettingsService.bootCompleted(); - break; - default: - break; + if (phase == PHASE_ACTIVITY_MANAGER_READY) { + mLockSettingsService.migrateOldDataAfterSystemReady(); + mLockSettingsService.loadEscrowData(); } } @@ -749,8 +742,8 @@ public class LockSettingsService extends ILockSettings.Stub { *
* This is primarily needed for users that were removed by Android 13 or earlier, which didn't * guarantee removal of LSS state as it relied on the {@code ACTION_USER_REMOVED} intent. It is - * also needed because {@link #removeUser()} delays requests to remove LSS state until the - * {@code PHASE_BOOT_COMPLETED} boot phase, so they can be lost. + * also needed because {@link #removeUser()} delays requests to remove LSS state until Weaver is + * guaranteed to be available, so they can be lost. *
* Stale state is detected by checking whether the user serial number changed. This works * because user serial numbers are never reused. @@ -931,7 +924,9 @@ public class LockSettingsService extends ILockSettings.Stub { return success; } - private void bootCompleted() { + // This is called when Weaver is guaranteed to be available (if the device supports Weaver). + // It does any synthetic password related work that was delayed from earlier in the boot. + private void onThirdPartyAppsStarted() { synchronized (mUserCreationAndRemovalLock) { // Handle delayed calls to LSS.removeUser() and LSS.createNewUser(). for (int i = 0; i < mEarlyRemovedUsers.size(); i++) { @@ -976,7 +971,7 @@ public class LockSettingsService extends ILockSettings.Stub { setString("migrated_all_users_to_sp_and_bound_ce", "true", 0); } - mBootComplete = true; + mThirdPartyAppsStarted = true; } } @@ -2304,14 +2299,14 @@ public class LockSettingsService extends ILockSettings.Stub { private void createNewUser(@UserIdInt int userId, int userSerialNumber) { synchronized (mUserCreationAndRemovalLock) { - // Before PHASE_BOOT_COMPLETED, don't actually create the synthetic password yet, but - // rather automatically delay it to later. We do this because protecting the synthetic + // During early boot, don't actually create the synthetic password yet, but rather + // automatically delay it to later. We do this because protecting the synthetic // password requires the Weaver HAL if the device supports it, and some devices don't // make Weaver available until fairly late in the boot process. This logic ensures a // consistent flow across all devices, regardless of their Weaver implementation. - if (!mBootComplete) { - Slogf.i(TAG, "Delaying locksettings state creation for user %d until boot complete", - userId); + if (!mThirdPartyAppsStarted) { + Slogf.i(TAG, "Delaying locksettings state creation for user %d until third-party " + + "apps are started", userId); mEarlyCreatedUsers.put(userId, userSerialNumber); mEarlyRemovedUsers.delete(userId); return; @@ -2325,14 +2320,14 @@ public class LockSettingsService extends ILockSettings.Stub { private void removeUser(@UserIdInt int userId) { synchronized (mUserCreationAndRemovalLock) { - // Before PHASE_BOOT_COMPLETED, don't actually remove the LSS state yet, but rather - // automatically delay it to later. We do this because deleting synthetic password - // protectors requires the Weaver HAL if the device supports it, and some devices don't - // make Weaver available until fairly late in the boot process. This logic ensures a - // consistent flow across all devices, regardless of their Weaver implementation. - if (!mBootComplete) { - Slogf.i(TAG, "Delaying locksettings state removal for user %d until boot complete", - userId); + // During early boot, don't actually remove the LSS state yet, but rather automatically + // delay it to later. We do this because deleting synthetic password protectors + // requires the Weaver HAL if the device supports it, and some devices don't make Weaver + // available until fairly late in the boot process. This logic ensures a consistent + // flow across all devices, regardless of their Weaver implementation. + if (!mThirdPartyAppsStarted) { + Slogf.i(TAG, "Delaying locksettings state removal for user %d until third-party " + + "apps are started", userId); if (mEarlyCreatedUsers.indexOfKey(userId) >= 0) { mEarlyCreatedUsers.delete(userId); } else { @@ -2634,9 +2629,8 @@ public class LockSettingsService extends ILockSettings.Stub { * protects the user's CE key with a key derived from the SP. *
* This is called just once in the lifetime of the user: at user creation time (possibly delayed - * until {@code PHASE_BOOT_COMPLETED} to ensure that the Weaver HAL is available if the device - * supports it), or when upgrading from Android 13 or earlier where users with no LSKF didn't - * necessarily have an SP. + * until the time when Weaver is guaranteed to be available), or when upgrading from Android 13 + * or earlier where users with no LSKF didn't necessarily have an SP. */ @GuardedBy("mSpManager") @VisibleForTesting @@ -3159,7 +3153,7 @@ public class LockSettingsService extends ILockSettings.Stub { pw.println("PasswordHandleCount: " + mGatekeeperPasswords.size()); synchronized (mUserCreationAndRemovalLock) { - pw.println("BootComplete: " + mBootComplete); + pw.println("ThirdPartyAppsStarted: " + mThirdPartyAppsStarted); } } @@ -3316,6 +3310,11 @@ public class LockSettingsService extends ILockSettings.Stub { private final class LocalService extends LockSettingsInternal { + @Override + public void onThirdPartyAppsStarted() { + LockSettingsService.this.onThirdPartyAppsStarted(); + } + @Override public void unlockUserKeyIfUnsecured(@UserIdInt int userId) { LockSettingsService.this.unlockUserKeyIfUnsecured(userId); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 88c0ec6d9c954..5cfd9a61b2beb 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -103,6 +103,7 @@ import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.EmergencyAffordanceManager; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.widget.ILockSettings; +import com.android.internal.widget.LockSettingsInternal; import com.android.server.am.ActivityManagerService; import com.android.server.ambientcontext.AmbientContextManagerService; import com.android.server.appbinding.AppBindingService; @@ -3008,6 +3009,14 @@ public final class SystemServer implements Dumpable { t.traceEnd(); }, t); + t.traceBegin("LockSettingsThirdPartyAppsStarted"); + LockSettingsInternal lockSettingsInternal = + LocalServices.getService(LockSettingsInternal.class); + if (lockSettingsInternal != null) { + lockSettingsInternal.onThirdPartyAppsStarted(); + } + t.traceEnd(); + t.traceBegin("StartSystemUI"); try { startSystemUi(context, windowManagerF);