Loading core/java/android/os/RecoverySystem.java +3 −2 Original line number Diff line number Diff line Loading @@ -169,8 +169,9 @@ public class RecoverySystem { public @interface ResumeOnRebootRebootErrorCode {} /** * The preparation of resume on reboot succeeds. Don't expose it because a successful reboot * should just reboot the device. * The preparation of resume on reboot succeeds. * * <p> Don't expose it because a successful reboot should just reboot the device. * @hide */ public static final int RESUME_ON_REBOOT_REBOOT_ERROR_NONE = 0; Loading core/java/com/android/internal/widget/LockSettingsInternal.java +28 −2 Original line number Diff line number Diff line Loading @@ -16,15 +16,41 @@ package com.android.internal.widget; import android.annotation.IntDef; import android.annotation.Nullable; import android.app.admin.PasswordMetrics; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * LockSettingsService local system service interface. * * @hide Only for use within the system server. */ public abstract class LockSettingsInternal { /** ErrorCode for armRebootEscrow failures. **/ @IntDef(prefix = {"ARM_REBOOT_ERROR_"}, value = { ARM_REBOOT_ERROR_NONE, ARM_REBOOT_ERROR_UNSPECIFIED, ARM_REBOOT_ERROR_ESCROW_NOT_READY, ARM_REBOOT_ERROR_NO_PROVIDER, ARM_REBOOT_ERROR_PROVIDER_MISMATCH, ARM_REBOOT_ERROR_NO_ESCROW_KEY, ARM_REBOOT_ERROR_KEYSTORE_FAILURE, ARM_REBOOT_ERROR_STORE_ESCROW_KEY, }) @Retention(RetentionPolicy.SOURCE) public @interface ArmRebootEscrowErrorCode {} public static final int ARM_REBOOT_ERROR_NONE = 0; public static final int ARM_REBOOT_ERROR_UNSPECIFIED = 1; public static final int ARM_REBOOT_ERROR_ESCROW_NOT_READY = 2; public static final int ARM_REBOOT_ERROR_NO_PROVIDER = 3; public static final int ARM_REBOOT_ERROR_PROVIDER_MISMATCH = 4; public static final int ARM_REBOOT_ERROR_NO_ESCROW_KEY = 5; public static final int ARM_REBOOT_ERROR_KEYSTORE_FAILURE = 6; public static final int ARM_REBOOT_ERROR_STORE_ESCROW_KEY = 7; // TODO(b/183140900) split store escrow key errors into detailed ones. /** * Create an escrow token for the current user, which can later be used to unlock FBE Loading Loading @@ -104,9 +130,9 @@ public abstract class LockSettingsInternal { * Should be called immediately before rebooting for an update. This depends on {@link * #prepareRebootEscrow()} having been called and the escrow completing. * * @return true if the arming worked * @return ARM_ERROR_NONE if the arming worked */ public abstract boolean armRebootEscrow(); public abstract @ArmRebootEscrowErrorCode int armRebootEscrow(); /** Loading services/core/java/com/android/server/locksettings/LockSettingsService.java +1 −1 Original line number Diff line number Diff line Loading @@ -3488,7 +3488,7 @@ public class LockSettingsService extends ILockSettings.Stub { } @Override public boolean armRebootEscrow() { public @ArmRebootEscrowErrorCode int armRebootEscrow() { return mRebootEscrowManager.armRebootEscrowIfNeeded(); } Loading services/core/java/com/android/server/locksettings/RebootEscrowManager.java +50 −29 Original line number Diff line number Diff line Loading @@ -18,6 +18,15 @@ package com.android.server.locksettings; import static android.os.UserHandle.USER_SYSTEM; import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_ESCROW_NOT_READY; import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_KEYSTORE_FAILURE; import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NONE; import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NO_ESCROW_KEY; import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NO_PROVIDER; import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_PROVIDER_MISMATCH; import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_STORE_ESCROW_KEY; import static com.android.internal.widget.LockSettingsInternal.ArmRebootEscrowErrorCode; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.UserIdInt; Loading Loading @@ -577,16 +586,14 @@ class RebootEscrowManager { mRebootEscrowWanted = false; setRebootEscrowReady(false); RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider(); if (rebootEscrowProvider == null) { Slog.w(TAG, "Had reboot escrow data for users, but RebootEscrowProvider is unavailable"); return; Slog.w(TAG, "RebootEscrowProvider is unavailable for clear request"); } else { rebootEscrowProvider.clearRebootEscrowKey(); } clearMetricsStorage(); rebootEscrowProvider.clearRebootEscrowKey(); List<UserInfo> users = mUserManager.getUsers(); for (UserInfo user : users) { Loading @@ -596,20 +603,30 @@ class RebootEscrowManager { mEventLog.addEntry(RebootEscrowEvent.CLEARED_LSKF_REQUEST); } boolean armRebootEscrowIfNeeded() { @ArmRebootEscrowErrorCode int armRebootEscrowIfNeeded() { if (!mRebootEscrowReady) { return false; return ARM_REBOOT_ERROR_ESCROW_NOT_READY; } RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider(); if (rebootEscrowProvider == null) { Slog.w(TAG, "Had reboot escrow data for users, but RebootEscrowProvider is unavailable"); return false; clearRebootEscrowIfNeeded(); return ARM_REBOOT_ERROR_NO_PROVIDER; } int expectedProviderType = mInjector.serverBasedResumeOnReboot() ? RebootEscrowProviderInterface.TYPE_SERVER_BASED : RebootEscrowProviderInterface.TYPE_HAL; int actualProviderType = rebootEscrowProvider.getType(); // TODO(b/183140900) Fail the reboot if provider type mismatches. if (expectedProviderType != actualProviderType) { Slog.w(TAG, "Expect reboot escrow provider " + expectedProviderType + ", but the RoR is prepared with " + actualProviderType + ". Please prepare the RoR again."); clearRebootEscrowIfNeeded(); return ARM_REBOOT_ERROR_PROVIDER_MISMATCH; } RebootEscrowKey escrowKey; synchronized (mKeyGenerationLock) { Loading @@ -618,17 +635,26 @@ class RebootEscrowManager { if (escrowKey == null) { Slog.e(TAG, "Escrow key is null, but escrow was marked as ready"); return false; clearRebootEscrowIfNeeded(); return ARM_REBOOT_ERROR_NO_ESCROW_KEY; } // We will use the same key from keystore to encrypt the escrow key and escrow data blob. SecretKey kk = mKeyStoreManager.getKeyStoreEncryptionKey(); if (kk == null) { Slog.e(TAG, "Failed to get encryption key from keystore."); return false; clearRebootEscrowIfNeeded(); return ARM_REBOOT_ERROR_KEYSTORE_FAILURE; } // TODO(b/183140900) design detailed errors for store escrow key errors. // We don't clear rebootEscrow here, because some errors may be recoverable, e.g. network // unavailable for server based provider. boolean armedRebootEscrow = rebootEscrowProvider.storeRebootEscrowKey(escrowKey, kk); if (armedRebootEscrow) { if (!armedRebootEscrow) { return ARM_REBOOT_ERROR_STORE_ESCROW_KEY; } mStorage.setInt(REBOOT_ESCROW_ARMED_KEY, mInjector.getBootCount(), USER_SYSTEM); mStorage.setLong(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, mInjector.getCurrentTimeMillis(), USER_SYSTEM); Loading @@ -639,9 +665,8 @@ class RebootEscrowManager { mInjector.getVbmetaDigest(true), USER_SYSTEM); mStorage.setInt(REBOOT_ESCROW_KEY_PROVIDER, actualProviderType, USER_SYSTEM); mEventLog.addEntry(RebootEscrowEvent.SET_ARMED_STATUS); } return armedRebootEscrow; return ARM_REBOOT_ERROR_NONE; } private void setRebootEscrowReady(boolean ready) { Loading @@ -663,10 +688,6 @@ class RebootEscrowManager { } boolean clearRebootEscrow() { if (mInjector.getRebootEscrowProvider() == null) { return false; } clearRebootEscrowIfNeeded(); return true; } Loading services/core/java/com/android/server/recoverysystem/RecoverySystemService.java +75 −17 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import static android.os.RecoverySystem.RESUME_ON_REBOOT_REBOOT_ERROR_UNSPECIFIE import static android.os.RecoverySystem.ResumeOnRebootRebootErrorCode; import static android.os.UserHandle.USER_SYSTEM; import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NONE; import android.annotation.IntDef; import android.content.Context; import android.content.IntentSender; Loading @@ -47,6 +49,7 @@ import android.os.SystemProperties; import android.provider.DeviceConfig; import android.util.ArrayMap; import android.util.ArraySet; import android.util.FastImmutableArraySet; import android.util.Slog; import com.android.internal.annotations.GuardedBy; Loading Loading @@ -154,6 +157,39 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo ROR_REQUESTED_SKIP_CLEAR }) private @interface ResumeOnRebootActionsOnClear {} /** * Fatal arm escrow errors from lock settings that means the RoR is in a bad state. So clients * need to prepare RoR again. */ static final FastImmutableArraySet<Integer> FATAL_ARM_ESCROW_ERRORS = new FastImmutableArraySet<>(new Integer[]{ LockSettingsInternal.ARM_REBOOT_ERROR_ESCROW_NOT_READY, LockSettingsInternal.ARM_REBOOT_ERROR_NO_PROVIDER, LockSettingsInternal.ARM_REBOOT_ERROR_PROVIDER_MISMATCH, LockSettingsInternal.ARM_REBOOT_ERROR_NO_ESCROW_KEY, LockSettingsInternal.ARM_REBOOT_ERROR_KEYSTORE_FAILURE, }); /** * The error details for ArmRebootEscrow. It contains error codes from RecoverySystemService * and LockSettingsService. */ static class RebootPreparationError { final @ResumeOnRebootRebootErrorCode int mRebootErrorCode; final int mProviderErrorCode; // The supplemental error code from lock settings RebootPreparationError(int rebootErrorCode, int providerErrorCode) { mRebootErrorCode = rebootErrorCode; mProviderErrorCode = providerErrorCode; } int getErrorCodeForMetrics() { // The ResumeOnRebootRebootErrorCode are aligned with 1000; so it's safe to add them // for metrics purpose. return mRebootErrorCode + mProviderErrorCode; } } /** * Manages shared preference, i.e. the storage used for metrics reporting. */ Loading Loading @@ -709,34 +745,40 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo return true; } private @ResumeOnRebootRebootErrorCode int armRebootEscrow(String packageName, private RebootPreparationError armRebootEscrow(String packageName, boolean slotSwitch) { if (packageName == null) { Slog.w(TAG, "Missing packageName when rebooting with lskf."); return RESUME_ON_REBOOT_REBOOT_ERROR_INVALID_PACKAGE_NAME; return new RebootPreparationError( RESUME_ON_REBOOT_REBOOT_ERROR_INVALID_PACKAGE_NAME, ARM_REBOOT_ERROR_NONE); } if (!isLskfCaptured(packageName)) { return RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED; return new RebootPreparationError(RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED, ARM_REBOOT_ERROR_NONE); } if (!verifySlotForNextBoot(slotSwitch)) { return RESUME_ON_REBOOT_REBOOT_ERROR_SLOT_MISMATCH; return new RebootPreparationError(RESUME_ON_REBOOT_REBOOT_ERROR_SLOT_MISMATCH, ARM_REBOOT_ERROR_NONE); } final long origId = Binder.clearCallingIdentity(); boolean result; int providerErrorCode; try { result = mInjector.getLockSettingsService().armRebootEscrow(); providerErrorCode = mInjector.getLockSettingsService().armRebootEscrow(); } finally { Binder.restoreCallingIdentity(origId); } if (!result) { Slog.w(TAG, "Failure to escrow key for reboot"); return RESUME_ON_REBOOT_REBOOT_ERROR_PROVIDER_PREPARATION_FAILURE; if (providerErrorCode != ARM_REBOOT_ERROR_NONE) { Slog.w(TAG, "Failure to escrow key for reboot, providerErrorCode: " + providerErrorCode); return new RebootPreparationError( RESUME_ON_REBOOT_REBOOT_ERROR_PROVIDER_PREPARATION_FAILURE, providerErrorCode); } return RESUME_ON_REBOOT_REBOOT_ERROR_NONE; return new RebootPreparationError(RESUME_ON_REBOOT_REBOOT_ERROR_NONE, ARM_REBOOT_ERROR_NONE); } private boolean useServerBasedRoR() { Loading @@ -750,7 +792,7 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo } private void reportMetricsOnRebootWithLskf(String packageName, boolean slotSwitch, @ResumeOnRebootRebootErrorCode int errorCode) { RebootPreparationError escrowError) { int uid = mInjector.getUidFromPackageName(packageName); boolean serverBased = useServerBasedRoR(); int preparedClientCount; Loading @@ -773,15 +815,31 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo + " request count %d, lskf captured count %d, duration since lskf captured" + " %d seconds.", packageName, preparedClientCount, requestCount, lskfCapturedCount, durationSeconds)); mInjector.reportRebootEscrowRebootMetrics(errorCode, uid, preparedClientCount, requestCount, slotSwitch, serverBased, durationSeconds, lskfCapturedCount); mInjector.reportRebootEscrowRebootMetrics(escrowError.getErrorCodeForMetrics(), uid, preparedClientCount, requestCount, slotSwitch, serverBased, durationSeconds, lskfCapturedCount); } private void clearRoRPreparationStateOnRebootFailure(RebootPreparationError escrowError) { if (!FATAL_ARM_ESCROW_ERRORS.contains(escrowError.mProviderErrorCode)) { return; } Slog.w(TAG, "Clearing resume on reboot states for all clients on arm escrow error: " + escrowError.mProviderErrorCode); synchronized (this) { mCallerPendingRequest.clear(); mCallerPreparedForReboot.clear(); } } private @ResumeOnRebootRebootErrorCode int rebootWithLskfImpl(String packageName, String reason, boolean slotSwitch) { @ResumeOnRebootRebootErrorCode int errorCode = armRebootEscrow(packageName, slotSwitch); reportMetricsOnRebootWithLskf(packageName, slotSwitch, errorCode); RebootPreparationError escrowError = armRebootEscrow(packageName, slotSwitch); reportMetricsOnRebootWithLskf(packageName, slotSwitch, escrowError); clearRoRPreparationStateOnRebootFailure(escrowError); @ResumeOnRebootRebootErrorCode int errorCode = escrowError.mRebootErrorCode; if (errorCode != RESUME_ON_REBOOT_REBOOT_ERROR_NONE) { return errorCode; } Loading Loading
core/java/android/os/RecoverySystem.java +3 −2 Original line number Diff line number Diff line Loading @@ -169,8 +169,9 @@ public class RecoverySystem { public @interface ResumeOnRebootRebootErrorCode {} /** * The preparation of resume on reboot succeeds. Don't expose it because a successful reboot * should just reboot the device. * The preparation of resume on reboot succeeds. * * <p> Don't expose it because a successful reboot should just reboot the device. * @hide */ public static final int RESUME_ON_REBOOT_REBOOT_ERROR_NONE = 0; Loading
core/java/com/android/internal/widget/LockSettingsInternal.java +28 −2 Original line number Diff line number Diff line Loading @@ -16,15 +16,41 @@ package com.android.internal.widget; import android.annotation.IntDef; import android.annotation.Nullable; import android.app.admin.PasswordMetrics; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * LockSettingsService local system service interface. * * @hide Only for use within the system server. */ public abstract class LockSettingsInternal { /** ErrorCode for armRebootEscrow failures. **/ @IntDef(prefix = {"ARM_REBOOT_ERROR_"}, value = { ARM_REBOOT_ERROR_NONE, ARM_REBOOT_ERROR_UNSPECIFIED, ARM_REBOOT_ERROR_ESCROW_NOT_READY, ARM_REBOOT_ERROR_NO_PROVIDER, ARM_REBOOT_ERROR_PROVIDER_MISMATCH, ARM_REBOOT_ERROR_NO_ESCROW_KEY, ARM_REBOOT_ERROR_KEYSTORE_FAILURE, ARM_REBOOT_ERROR_STORE_ESCROW_KEY, }) @Retention(RetentionPolicy.SOURCE) public @interface ArmRebootEscrowErrorCode {} public static final int ARM_REBOOT_ERROR_NONE = 0; public static final int ARM_REBOOT_ERROR_UNSPECIFIED = 1; public static final int ARM_REBOOT_ERROR_ESCROW_NOT_READY = 2; public static final int ARM_REBOOT_ERROR_NO_PROVIDER = 3; public static final int ARM_REBOOT_ERROR_PROVIDER_MISMATCH = 4; public static final int ARM_REBOOT_ERROR_NO_ESCROW_KEY = 5; public static final int ARM_REBOOT_ERROR_KEYSTORE_FAILURE = 6; public static final int ARM_REBOOT_ERROR_STORE_ESCROW_KEY = 7; // TODO(b/183140900) split store escrow key errors into detailed ones. /** * Create an escrow token for the current user, which can later be used to unlock FBE Loading Loading @@ -104,9 +130,9 @@ public abstract class LockSettingsInternal { * Should be called immediately before rebooting for an update. This depends on {@link * #prepareRebootEscrow()} having been called and the escrow completing. * * @return true if the arming worked * @return ARM_ERROR_NONE if the arming worked */ public abstract boolean armRebootEscrow(); public abstract @ArmRebootEscrowErrorCode int armRebootEscrow(); /** Loading
services/core/java/com/android/server/locksettings/LockSettingsService.java +1 −1 Original line number Diff line number Diff line Loading @@ -3488,7 +3488,7 @@ public class LockSettingsService extends ILockSettings.Stub { } @Override public boolean armRebootEscrow() { public @ArmRebootEscrowErrorCode int armRebootEscrow() { return mRebootEscrowManager.armRebootEscrowIfNeeded(); } Loading
services/core/java/com/android/server/locksettings/RebootEscrowManager.java +50 −29 Original line number Diff line number Diff line Loading @@ -18,6 +18,15 @@ package com.android.server.locksettings; import static android.os.UserHandle.USER_SYSTEM; import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_ESCROW_NOT_READY; import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_KEYSTORE_FAILURE; import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NONE; import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NO_ESCROW_KEY; import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NO_PROVIDER; import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_PROVIDER_MISMATCH; import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_STORE_ESCROW_KEY; import static com.android.internal.widget.LockSettingsInternal.ArmRebootEscrowErrorCode; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.UserIdInt; Loading Loading @@ -577,16 +586,14 @@ class RebootEscrowManager { mRebootEscrowWanted = false; setRebootEscrowReady(false); RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider(); if (rebootEscrowProvider == null) { Slog.w(TAG, "Had reboot escrow data for users, but RebootEscrowProvider is unavailable"); return; Slog.w(TAG, "RebootEscrowProvider is unavailable for clear request"); } else { rebootEscrowProvider.clearRebootEscrowKey(); } clearMetricsStorage(); rebootEscrowProvider.clearRebootEscrowKey(); List<UserInfo> users = mUserManager.getUsers(); for (UserInfo user : users) { Loading @@ -596,20 +603,30 @@ class RebootEscrowManager { mEventLog.addEntry(RebootEscrowEvent.CLEARED_LSKF_REQUEST); } boolean armRebootEscrowIfNeeded() { @ArmRebootEscrowErrorCode int armRebootEscrowIfNeeded() { if (!mRebootEscrowReady) { return false; return ARM_REBOOT_ERROR_ESCROW_NOT_READY; } RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider(); if (rebootEscrowProvider == null) { Slog.w(TAG, "Had reboot escrow data for users, but RebootEscrowProvider is unavailable"); return false; clearRebootEscrowIfNeeded(); return ARM_REBOOT_ERROR_NO_PROVIDER; } int expectedProviderType = mInjector.serverBasedResumeOnReboot() ? RebootEscrowProviderInterface.TYPE_SERVER_BASED : RebootEscrowProviderInterface.TYPE_HAL; int actualProviderType = rebootEscrowProvider.getType(); // TODO(b/183140900) Fail the reboot if provider type mismatches. if (expectedProviderType != actualProviderType) { Slog.w(TAG, "Expect reboot escrow provider " + expectedProviderType + ", but the RoR is prepared with " + actualProviderType + ". Please prepare the RoR again."); clearRebootEscrowIfNeeded(); return ARM_REBOOT_ERROR_PROVIDER_MISMATCH; } RebootEscrowKey escrowKey; synchronized (mKeyGenerationLock) { Loading @@ -618,17 +635,26 @@ class RebootEscrowManager { if (escrowKey == null) { Slog.e(TAG, "Escrow key is null, but escrow was marked as ready"); return false; clearRebootEscrowIfNeeded(); return ARM_REBOOT_ERROR_NO_ESCROW_KEY; } // We will use the same key from keystore to encrypt the escrow key and escrow data blob. SecretKey kk = mKeyStoreManager.getKeyStoreEncryptionKey(); if (kk == null) { Slog.e(TAG, "Failed to get encryption key from keystore."); return false; clearRebootEscrowIfNeeded(); return ARM_REBOOT_ERROR_KEYSTORE_FAILURE; } // TODO(b/183140900) design detailed errors for store escrow key errors. // We don't clear rebootEscrow here, because some errors may be recoverable, e.g. network // unavailable for server based provider. boolean armedRebootEscrow = rebootEscrowProvider.storeRebootEscrowKey(escrowKey, kk); if (armedRebootEscrow) { if (!armedRebootEscrow) { return ARM_REBOOT_ERROR_STORE_ESCROW_KEY; } mStorage.setInt(REBOOT_ESCROW_ARMED_KEY, mInjector.getBootCount(), USER_SYSTEM); mStorage.setLong(REBOOT_ESCROW_KEY_ARMED_TIMESTAMP, mInjector.getCurrentTimeMillis(), USER_SYSTEM); Loading @@ -639,9 +665,8 @@ class RebootEscrowManager { mInjector.getVbmetaDigest(true), USER_SYSTEM); mStorage.setInt(REBOOT_ESCROW_KEY_PROVIDER, actualProviderType, USER_SYSTEM); mEventLog.addEntry(RebootEscrowEvent.SET_ARMED_STATUS); } return armedRebootEscrow; return ARM_REBOOT_ERROR_NONE; } private void setRebootEscrowReady(boolean ready) { Loading @@ -663,10 +688,6 @@ class RebootEscrowManager { } boolean clearRebootEscrow() { if (mInjector.getRebootEscrowProvider() == null) { return false; } clearRebootEscrowIfNeeded(); return true; } Loading
services/core/java/com/android/server/recoverysystem/RecoverySystemService.java +75 −17 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import static android.os.RecoverySystem.RESUME_ON_REBOOT_REBOOT_ERROR_UNSPECIFIE import static android.os.RecoverySystem.ResumeOnRebootRebootErrorCode; import static android.os.UserHandle.USER_SYSTEM; import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NONE; import android.annotation.IntDef; import android.content.Context; import android.content.IntentSender; Loading @@ -47,6 +49,7 @@ import android.os.SystemProperties; import android.provider.DeviceConfig; import android.util.ArrayMap; import android.util.ArraySet; import android.util.FastImmutableArraySet; import android.util.Slog; import com.android.internal.annotations.GuardedBy; Loading Loading @@ -154,6 +157,39 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo ROR_REQUESTED_SKIP_CLEAR }) private @interface ResumeOnRebootActionsOnClear {} /** * Fatal arm escrow errors from lock settings that means the RoR is in a bad state. So clients * need to prepare RoR again. */ static final FastImmutableArraySet<Integer> FATAL_ARM_ESCROW_ERRORS = new FastImmutableArraySet<>(new Integer[]{ LockSettingsInternal.ARM_REBOOT_ERROR_ESCROW_NOT_READY, LockSettingsInternal.ARM_REBOOT_ERROR_NO_PROVIDER, LockSettingsInternal.ARM_REBOOT_ERROR_PROVIDER_MISMATCH, LockSettingsInternal.ARM_REBOOT_ERROR_NO_ESCROW_KEY, LockSettingsInternal.ARM_REBOOT_ERROR_KEYSTORE_FAILURE, }); /** * The error details for ArmRebootEscrow. It contains error codes from RecoverySystemService * and LockSettingsService. */ static class RebootPreparationError { final @ResumeOnRebootRebootErrorCode int mRebootErrorCode; final int mProviderErrorCode; // The supplemental error code from lock settings RebootPreparationError(int rebootErrorCode, int providerErrorCode) { mRebootErrorCode = rebootErrorCode; mProviderErrorCode = providerErrorCode; } int getErrorCodeForMetrics() { // The ResumeOnRebootRebootErrorCode are aligned with 1000; so it's safe to add them // for metrics purpose. return mRebootErrorCode + mProviderErrorCode; } } /** * Manages shared preference, i.e. the storage used for metrics reporting. */ Loading Loading @@ -709,34 +745,40 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo return true; } private @ResumeOnRebootRebootErrorCode int armRebootEscrow(String packageName, private RebootPreparationError armRebootEscrow(String packageName, boolean slotSwitch) { if (packageName == null) { Slog.w(TAG, "Missing packageName when rebooting with lskf."); return RESUME_ON_REBOOT_REBOOT_ERROR_INVALID_PACKAGE_NAME; return new RebootPreparationError( RESUME_ON_REBOOT_REBOOT_ERROR_INVALID_PACKAGE_NAME, ARM_REBOOT_ERROR_NONE); } if (!isLskfCaptured(packageName)) { return RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED; return new RebootPreparationError(RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED, ARM_REBOOT_ERROR_NONE); } if (!verifySlotForNextBoot(slotSwitch)) { return RESUME_ON_REBOOT_REBOOT_ERROR_SLOT_MISMATCH; return new RebootPreparationError(RESUME_ON_REBOOT_REBOOT_ERROR_SLOT_MISMATCH, ARM_REBOOT_ERROR_NONE); } final long origId = Binder.clearCallingIdentity(); boolean result; int providerErrorCode; try { result = mInjector.getLockSettingsService().armRebootEscrow(); providerErrorCode = mInjector.getLockSettingsService().armRebootEscrow(); } finally { Binder.restoreCallingIdentity(origId); } if (!result) { Slog.w(TAG, "Failure to escrow key for reboot"); return RESUME_ON_REBOOT_REBOOT_ERROR_PROVIDER_PREPARATION_FAILURE; if (providerErrorCode != ARM_REBOOT_ERROR_NONE) { Slog.w(TAG, "Failure to escrow key for reboot, providerErrorCode: " + providerErrorCode); return new RebootPreparationError( RESUME_ON_REBOOT_REBOOT_ERROR_PROVIDER_PREPARATION_FAILURE, providerErrorCode); } return RESUME_ON_REBOOT_REBOOT_ERROR_NONE; return new RebootPreparationError(RESUME_ON_REBOOT_REBOOT_ERROR_NONE, ARM_REBOOT_ERROR_NONE); } private boolean useServerBasedRoR() { Loading @@ -750,7 +792,7 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo } private void reportMetricsOnRebootWithLskf(String packageName, boolean slotSwitch, @ResumeOnRebootRebootErrorCode int errorCode) { RebootPreparationError escrowError) { int uid = mInjector.getUidFromPackageName(packageName); boolean serverBased = useServerBasedRoR(); int preparedClientCount; Loading @@ -773,15 +815,31 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo + " request count %d, lskf captured count %d, duration since lskf captured" + " %d seconds.", packageName, preparedClientCount, requestCount, lskfCapturedCount, durationSeconds)); mInjector.reportRebootEscrowRebootMetrics(errorCode, uid, preparedClientCount, requestCount, slotSwitch, serverBased, durationSeconds, lskfCapturedCount); mInjector.reportRebootEscrowRebootMetrics(escrowError.getErrorCodeForMetrics(), uid, preparedClientCount, requestCount, slotSwitch, serverBased, durationSeconds, lskfCapturedCount); } private void clearRoRPreparationStateOnRebootFailure(RebootPreparationError escrowError) { if (!FATAL_ARM_ESCROW_ERRORS.contains(escrowError.mProviderErrorCode)) { return; } Slog.w(TAG, "Clearing resume on reboot states for all clients on arm escrow error: " + escrowError.mProviderErrorCode); synchronized (this) { mCallerPendingRequest.clear(); mCallerPreparedForReboot.clear(); } } private @ResumeOnRebootRebootErrorCode int rebootWithLskfImpl(String packageName, String reason, boolean slotSwitch) { @ResumeOnRebootRebootErrorCode int errorCode = armRebootEscrow(packageName, slotSwitch); reportMetricsOnRebootWithLskf(packageName, slotSwitch, errorCode); RebootPreparationError escrowError = armRebootEscrow(packageName, slotSwitch); reportMetricsOnRebootWithLskf(packageName, slotSwitch, escrowError); clearRoRPreparationStateOnRebootFailure(escrowError); @ResumeOnRebootRebootErrorCode int errorCode = escrowError.mRebootErrorCode; if (errorCode != RESUME_ON_REBOOT_REBOOT_ERROR_NONE) { return errorCode; } Loading