From 559ed7f0f0e20a39aea12632f2c8ec2f25f388c5 Mon Sep 17 00:00:00 2001 From: Tianjie Date: Mon, 29 Mar 2021 12:15:57 -0700 Subject: [PATCH] Expose error code for RoR reboot system API The clients of resume on reboot want additional information for reboot failures, so they can handle these failures better. Therefore expose the reboot failure error code via SystemApi. Bug: 183646725 Test: atest FrameworksServicesTests:RecoverySystemServiceTest; Do an RoR with gmscore Change-Id: Ia02655218194a070ce02e9dae6fd62e19259c9f9 --- core/api/system-current.txt | 7 +- core/java/android/os/IRecoverySystem.aidl | 4 +- core/java/android/os/RecoverySystem.java | 83 ++++++++++++++++--- .../recoverysystem/RecoverySystemService.java | 50 +++++------ .../RecoverySystemShellCommand.java | 4 +- .../RecoverySystemServiceTest.java | 45 +++++----- 6 files changed, 126 insertions(+), 67 deletions(-) diff --git a/core/api/system-current.txt b/core/api/system-current.txt index e31f174973234..d8ca05549dbd0 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -7183,10 +7183,15 @@ package android.os { method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener, android.os.Handler) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener) throws java.io.IOException; method @Deprecated @RequiresPermission(android.Manifest.permission.RECOVERY) public static void rebootAndApply(@NonNull android.content.Context, @NonNull String, @NonNull String) throws java.io.IOException; - method @RequiresPermission(anyOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static void rebootAndApply(@NonNull android.content.Context, @NonNull String, boolean) throws java.io.IOException; + method @RequiresPermission(anyOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static int rebootAndApply(@NonNull android.content.Context, @NonNull String, boolean) throws java.io.IOException; method @RequiresPermission(allOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static void rebootWipeAb(android.content.Context, java.io.File, String) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void scheduleUpdateOnBoot(android.content.Context, java.io.File) throws java.io.IOException; method public static boolean verifyPackageCompatibility(java.io.File) throws java.io.IOException; + field public static final int RESUME_ON_REBOOT_REBOOT_ERROR_INVALID_PACKAGE_NAME = 2000; // 0x7d0 + field public static final int RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED = 3000; // 0xbb8 + field public static final int RESUME_ON_REBOOT_REBOOT_ERROR_PROVIDER_PREPARATION_FAILURE = 5000; // 0x1388 + field public static final int RESUME_ON_REBOOT_REBOOT_ERROR_SLOT_MISMATCH = 4000; // 0xfa0 + field public static final int RESUME_ON_REBOOT_REBOOT_ERROR_UNSPECIFIED = 1000; // 0x3e8 } public final class RemoteCallback implements android.os.Parcelable { diff --git a/core/java/android/os/IRecoverySystem.aidl b/core/java/android/os/IRecoverySystem.aidl index 205288303b1eb..9368b68a91c64 100644 --- a/core/java/android/os/IRecoverySystem.aidl +++ b/core/java/android/os/IRecoverySystem.aidl @@ -30,6 +30,6 @@ interface IRecoverySystem { boolean requestLskf(in String packageName, in IntentSender sender); boolean clearLskf(in String packageName); boolean isLskfCaptured(in String packageName); - boolean rebootWithLskfAssumeSlotSwitch(in String packageName, in String reason); - boolean rebootWithLskf(in String packageName, in String reason, in boolean slotSwitch); + int rebootWithLskfAssumeSlotSwitch(in String packageName, in String reason); + int rebootWithLskf(in String packageName, in String reason, in boolean slotSwitch); } diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index 43184ea4b9a97..a42448c261d48 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -20,6 +20,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import static java.nio.charset.StandardCharsets.UTF_8; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -154,6 +155,65 @@ public class RecoverySystem { private final IRecoverySystem mService; + /** + * The error codes for reboots initiated by resume on reboot clients. + * @hide + */ + @IntDef(prefix = { "RESUME_ON_REBOOT_REBOOT_ERROR_" }, value = { + RESUME_ON_REBOOT_REBOOT_ERROR_NONE, + RESUME_ON_REBOOT_REBOOT_ERROR_UNSPECIFIED, + RESUME_ON_REBOOT_REBOOT_ERROR_INVALID_PACKAGE_NAME, + RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED, + RESUME_ON_REBOOT_REBOOT_ERROR_SLOT_MISMATCH, + RESUME_ON_REBOOT_REBOOT_ERROR_PROVIDER_PREPARATION_FAILURE}) + public @interface ResumeOnRebootRebootErrorCode {} + + /** + * The preparation of resume on reboot succeeds. 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; + + /** + * The resume on reboot fails due to an unknown reason. + * @hide + */ + @SystemApi + public static final int RESUME_ON_REBOOT_REBOOT_ERROR_UNSPECIFIED = 1000; + + /** + * The resume on reboot fails because the package name of the client is invalid, e.g. null + * packageName, name contains invalid characters, etc. + * @hide + */ + @SystemApi + public static final int RESUME_ON_REBOOT_REBOOT_ERROR_INVALID_PACKAGE_NAME = 2000; + + /** + * The resume on reboot fails because the Lock Screen Knowledge Factor hasn't been captured. + * This error is also reported if the client attempts to reboot without preparing RoR. + * @hide + */ + @SystemApi + public static final int RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED = 3000; + + /** + * The resume on reboot fails because the client expects a different boot slot for the next boot + * on A/B devices. + * @hide + */ + @SystemApi + public static final int RESUME_ON_REBOOT_REBOOT_ERROR_SLOT_MISMATCH = 4000; + + /** + * The resume on reboot fails because the resume on reboot provider, e.g. HAL / server based, + * fails to arm/store the escrow key. + * @hide + */ + @SystemApi + public static final int RESUME_ON_REBOOT_REBOOT_ERROR_PROVIDER_PREPARATION_FAILURE = 5000; + /** * Interface definition for a callback to be invoked regularly as * verification proceeds. @@ -723,7 +783,8 @@ public class RecoverySystem { } RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE); // OTA is the sole user, who expects a slot switch. - if (!rs.rebootWithLskfAssumeSlotSwitch(context.getPackageName(), reason)) { + if (rs.rebootWithLskfAssumeSlotSwitch(context.getPackageName(), reason) + != RESUME_ON_REBOOT_REBOOT_ERROR_NONE) { throw new IOException("system not prepared to apply update"); } } @@ -752,19 +813,19 @@ public class RecoverySystem { * @param context the Context to use. * @param reason the reboot reason to give to the {@link PowerManager} * @param slotSwitch true if the caller expects the slot to be switched on A/B devices. - * @throws IOException if the reboot couldn't proceed because the device wasn't ready for an - * unattended reboot. + * + * @return 0 on success, and a non-zero error code if the reboot couldn't proceed because the + * device wasn't ready for an unattended reboot. + * @throws IOException on remote exceptions from the RecoverySystemService * @hide */ @SystemApi @RequiresPermission(anyOf = {android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) - public static void rebootAndApply(@NonNull Context context, + public static @ResumeOnRebootRebootErrorCode int rebootAndApply(@NonNull Context context, @NonNull String reason, boolean slotSwitch) throws IOException { RecoverySystem rs = context.getSystemService(RecoverySystem.class); - if (!rs.rebootWithLskf(context.getPackageName(), reason, slotSwitch)) { - throw new IOException("system not prepared to apply update"); - } + return rs.rebootWithLskf(context.getPackageName(), reason, slotSwitch); } /** @@ -1399,8 +1460,8 @@ public class RecoverySystem { * Calls the recovery system service to reboot and apply update. * */ - private boolean rebootWithLskf(String packageName, String reason, boolean slotSwitch) - throws IOException { + private @ResumeOnRebootRebootErrorCode int rebootWithLskf(String packageName, String reason, + boolean slotSwitch) throws IOException { try { return mService.rebootWithLskf(packageName, reason, slotSwitch); } catch (RemoteException e) { @@ -1414,8 +1475,8 @@ public class RecoverySystem { * expects a slot switch for A/B devices. * */ - private boolean rebootWithLskfAssumeSlotSwitch(String packageName, String reason) - throws IOException { + private @ResumeOnRebootRebootErrorCode int rebootWithLskfAssumeSlotSwitch(String packageName, + String reason) throws IOException { try { return mService.rebootWithLskfAssumeSlotSwitch(packageName, reason); } catch (RemoteException e) { diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java index fe21201f5cb7f..6ea030f56d4d3 100644 --- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java +++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java @@ -16,6 +16,13 @@ package com.android.server.recoverysystem; +import static android.os.RecoverySystem.RESUME_ON_REBOOT_REBOOT_ERROR_INVALID_PACKAGE_NAME; +import static android.os.RecoverySystem.RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED; +import static android.os.RecoverySystem.RESUME_ON_REBOOT_REBOOT_ERROR_NONE; +import static android.os.RecoverySystem.RESUME_ON_REBOOT_REBOOT_ERROR_PROVIDER_PREPARATION_FAILURE; +import static android.os.RecoverySystem.RESUME_ON_REBOOT_REBOOT_ERROR_SLOT_MISMATCH; +import static android.os.RecoverySystem.RESUME_ON_REBOOT_REBOOT_ERROR_UNSPECIFIED; +import static android.os.RecoverySystem.ResumeOnRebootRebootErrorCode; import static android.os.UserHandle.USER_SYSTEM; import android.annotation.IntDef; @@ -147,24 +154,6 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo ROR_REQUESTED_SKIP_CLEAR}) private @interface ResumeOnRebootActionsOnClear {} - /** - * The error codes for reboots initiated by resume on reboot clients. - */ - private static final int REBOOT_ERROR_NONE = 0; - private static final int REBOOT_ERROR_UNKNOWN = 1; - private static final int REBOOT_ERROR_INVALID_PACKAGE_NAME = 2; - private static final int REBOOT_ERROR_LSKF_NOT_CAPTURED = 3; - private static final int REBOOT_ERROR_SLOT_MISMATCH = 4; - private static final int REBOOT_ERROR_ARM_REBOOT_ESCROW_FAILURE = 5; - - @IntDef({ REBOOT_ERROR_NONE, - REBOOT_ERROR_UNKNOWN, - REBOOT_ERROR_INVALID_PACKAGE_NAME, - REBOOT_ERROR_LSKF_NOT_CAPTURED, - REBOOT_ERROR_SLOT_MISMATCH, - REBOOT_ERROR_ARM_REBOOT_ESCROW_FAILURE}) - private @interface ResumeOnRebootRebootErrorCode {} - /** * Manages shared preference, i.e. the storage used for metrics reporting. */ @@ -724,14 +713,14 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo boolean slotSwitch) { if (packageName == null) { Slog.w(TAG, "Missing packageName when rebooting with lskf."); - return REBOOT_ERROR_INVALID_PACKAGE_NAME; + return RESUME_ON_REBOOT_REBOOT_ERROR_INVALID_PACKAGE_NAME; } if (!isLskfCaptured(packageName)) { - return REBOOT_ERROR_LSKF_NOT_CAPTURED; + return RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED; } if (!verifySlotForNextBoot(slotSwitch)) { - return REBOOT_ERROR_SLOT_MISMATCH; + return RESUME_ON_REBOOT_REBOOT_ERROR_SLOT_MISMATCH; } final long origId = Binder.clearCallingIdentity(); @@ -744,10 +733,10 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo if (!result) { Slog.w(TAG, "Failure to escrow key for reboot"); - return REBOOT_ERROR_ARM_REBOOT_ESCROW_FAILURE; + return RESUME_ON_REBOOT_REBOOT_ERROR_PROVIDER_PREPARATION_FAILURE; } - return REBOOT_ERROR_NONE; + return RESUME_ON_REBOOT_REBOOT_ERROR_NONE; } private boolean useServerBasedRoR() { @@ -788,12 +777,13 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo requestCount, slotSwitch, serverBased, durationSeconds, lskfCapturedCount); } - private boolean rebootWithLskfImpl(String packageName, String reason, boolean slotSwitch) { + private @ResumeOnRebootRebootErrorCode int rebootWithLskfImpl(String packageName, String reason, + boolean slotSwitch) { @ResumeOnRebootRebootErrorCode int errorCode = armRebootEscrow(packageName, slotSwitch); reportMetricsOnRebootWithLskf(packageName, slotSwitch, errorCode); - if (errorCode != REBOOT_ERROR_NONE) { - return false; + if (errorCode != RESUME_ON_REBOOT_REBOOT_ERROR_NONE) { + return errorCode; } // Clear the metrics prefs after a successful RoR reboot. @@ -801,17 +791,19 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo PowerManager pm = mInjector.getPowerManager(); pm.reboot(reason); - return true; + return RESUME_ON_REBOOT_REBOOT_ERROR_UNSPECIFIED; } @Override // Binder call for the legacy rebootWithLskf - public boolean rebootWithLskfAssumeSlotSwitch(String packageName, String reason) { + public @ResumeOnRebootRebootErrorCode int rebootWithLskfAssumeSlotSwitch(String packageName, + String reason) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null); return rebootWithLskfImpl(packageName, reason, true); } @Override // Binder call - public boolean rebootWithLskf(String packageName, String reason, boolean slotSwitch) { + public @ResumeOnRebootRebootErrorCode int rebootWithLskf(String packageName, String reason, + boolean slotSwitch) { enforcePermissionForResumeOnReboot(); return rebootWithLskfImpl(packageName, reason, slotSwitch); } diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemShellCommand.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemShellCommand.java index ae71c1a1e4449..3d78828888da3 100644 --- a/services/core/java/com/android/server/recoverysystem/RecoverySystemShellCommand.java +++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemShellCommand.java @@ -17,6 +17,7 @@ package com.android.server.recoverysystem; import android.os.IRecoverySystem; +import android.os.RecoverySystem; import android.os.RemoteException; import android.os.ShellCommand; @@ -76,7 +77,8 @@ public class RecoverySystemShellCommand extends ShellCommand { private int rebootAndApply() throws RemoteException { String packageName = getNextArgRequired(); String rebootReason = getNextArgRequired(); - boolean success = mService.rebootWithLskf(packageName, rebootReason, false); + boolean success = (mService.rebootWithLskf(packageName, rebootReason, false) + == RecoverySystem.RESUME_ON_REBOOT_REBOOT_ERROR_NONE); PrintWriter pw = getOutPrintWriter(); // Keep the old message for cts test. pw.printf("%s Reboot and apply status: %s\n", packageName, diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java index 7903a90979fb2..2b358ea5e1058 100644 --- a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java @@ -16,7 +16,12 @@ package com.android.server.recoverysystem; +import static android.os.RecoverySystem.RESUME_ON_REBOOT_REBOOT_ERROR_INVALID_PACKAGE_NAME; +import static android.os.RecoverySystem.RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED; +import static android.os.RecoverySystem.RESUME_ON_REBOOT_REBOOT_ERROR_SLOT_MISMATCH; + import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.mockito.AdditionalMatchers.not; import static org.mockito.ArgumentMatchers.any; @@ -274,8 +279,7 @@ public class RecoverySystemServiceTest { verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any()); assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); - assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "foobar", true), - is(true)); + mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "foobar", true); verify(mIPowerManager).reboot(anyBoolean(), eq("foobar"), anyBoolean()); } @@ -373,8 +377,7 @@ public class RecoverySystemServiceTest { anyInt())).thenReturn(3); when(mSharedPreferences.getLong(eq(RecoverySystemService.LSKF_CAPTURED_TIMESTAMP_PREF), anyLong())).thenReturn(40_000L); - assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true), - is(true)); + mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true); verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); verify(mMetricsReporter).reportRebootEscrowRebootMetrics(eq(0), eq(1000), eq(1) /* client count */, eq(2) /* request count */, eq(true) /* slot switch */, @@ -386,19 +389,20 @@ public class RecoverySystemServiceTest { public void rebootWithLskf_slotMismatch_Failure() throws Exception { assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); mRecoverySystemService.onPreparedForReboot(true); - assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", false), - is(false)); + assertEquals(RESUME_ON_REBOOT_REBOOT_ERROR_SLOT_MISMATCH, + mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", false)); } @Test public void rebootWithLskf_withoutPrepare_Failure() throws Exception { - assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true), - is(false)); + assertEquals(RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED, + mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true)); } @Test public void rebootWithLskf_withNullCallerId_Failure() throws Exception { - assertThat(mRecoverySystemService.rebootWithLskf(null, null, true), is(false)); + assertEquals(RESUME_ON_REBOOT_REBOOT_ERROR_INVALID_PACKAGE_NAME, + mRecoverySystemService.rebootWithLskf(null, null, true)); verifyNoMoreInteractions(mIPowerManager); } @@ -410,8 +414,7 @@ public class RecoverySystemServiceTest { // Client B's clear won't affect client A's preparation. assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true)); - assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true), - is(true)); + mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true); verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); } @@ -428,8 +431,7 @@ public class RecoverySystemServiceTest { when(mSharedPreferences.getLong(eq(RecoverySystemService.LSKF_CAPTURED_TIMESTAMP_PREF), anyLong())).thenReturn(60_000L); - assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true), - is(true)); + mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true); verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); verify(mMetricsReporter).reportRebootEscrowRebootMetrics(eq(0), eq(1000), eq(2) /* client count */, eq(2) /* request count */, eq(true) /* slot switch */, @@ -450,17 +452,15 @@ public class RecoverySystemServiceTest { anyLong())).thenReturn(60_000L); assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true)); - assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true), - is(false)); + assertEquals(RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED, + mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true)); verifyNoMoreInteractions(mIPowerManager); verify(mMetricsReporter).reportRebootEscrowRebootMetrics(not(eq(0)), eq(1000), eq(1) /* client count */, anyInt() /* request count */, eq(true) /* slot switch */, anyBoolean(), eq(40), eq(1)/* lskf capture count */); assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true)); - assertThat( - mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true), - is(true)); + mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true); verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); verify(mMetricsReporter).reportRebootEscrowRebootMetrics((eq(0)), eq(2000), @@ -476,16 +476,15 @@ public class RecoverySystemServiceTest { // Client A clears assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true)); - assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true), - is(false)); + assertEquals(RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED, + mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true)); verifyNoMoreInteractions(mIPowerManager); // Client B clears assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true)); verify(mLockSettingsInternal).clearRebootEscrow(); - assertThat( - mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true), - is(false)); + assertEquals(RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED, + mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true)); verifyNoMoreInteractions(mIPowerManager); }