Merge "Expose error code for RoR reboot system API" am: d5547af728

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1656644

Change-Id: I8a935bab40cbaa2b9fab9247478efdbd4654eb37
This commit is contained in:
Tianjie Xu
2021-04-09 22:56:52 +00:00
committed by Automerger Merge Worker
6 changed files with 126 additions and 67 deletions

View File

@@ -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, 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 @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 @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(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 @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; 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 { public final class RemoteCallback implements android.os.Parcelable {

View File

@@ -30,6 +30,6 @@ interface IRecoverySystem {
boolean requestLskf(in String packageName, in IntentSender sender); boolean requestLskf(in String packageName, in IntentSender sender);
boolean clearLskf(in String packageName); boolean clearLskf(in String packageName);
boolean isLskfCaptured(in String packageName); boolean isLskfCaptured(in String packageName);
boolean rebootWithLskfAssumeSlotSwitch(in String packageName, in String reason); int rebootWithLskfAssumeSlotSwitch(in String packageName, in String reason);
boolean rebootWithLskf(in String packageName, in String reason, in boolean slotSwitch); int rebootWithLskf(in String packageName, in String reason, in boolean slotSwitch);
} }

View File

@@ -20,6 +20,7 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
import android.annotation.IntDef;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.annotation.RequiresPermission; import android.annotation.RequiresPermission;
@@ -154,6 +155,65 @@ public class RecoverySystem {
private final IRecoverySystem mService; 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 * Interface definition for a callback to be invoked regularly as
* verification proceeds. * verification proceeds.
@@ -723,7 +783,8 @@ public class RecoverySystem {
} }
RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE); RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
// OTA is the sole user, who expects a slot switch. // 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"); throw new IOException("system not prepared to apply update");
} }
} }
@@ -752,19 +813,19 @@ public class RecoverySystem {
* @param context the Context to use. * @param context the Context to use.
* @param reason the reboot reason to give to the {@link PowerManager} * @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. * @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 * @hide
*/ */
@SystemApi @SystemApi
@RequiresPermission(anyOf = {android.Manifest.permission.RECOVERY, @RequiresPermission(anyOf = {android.Manifest.permission.RECOVERY,
android.Manifest.permission.REBOOT}) 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 { @NonNull String reason, boolean slotSwitch) throws IOException {
RecoverySystem rs = context.getSystemService(RecoverySystem.class); RecoverySystem rs = context.getSystemService(RecoverySystem.class);
if (!rs.rebootWithLskf(context.getPackageName(), reason, slotSwitch)) { return rs.rebootWithLskf(context.getPackageName(), reason, slotSwitch);
throw new IOException("system not prepared to apply update");
}
} }
/** /**
@@ -1399,8 +1460,8 @@ public class RecoverySystem {
* Calls the recovery system service to reboot and apply update. * Calls the recovery system service to reboot and apply update.
* *
*/ */
private boolean rebootWithLskf(String packageName, String reason, boolean slotSwitch) private @ResumeOnRebootRebootErrorCode int rebootWithLskf(String packageName, String reason,
throws IOException { boolean slotSwitch) throws IOException {
try { try {
return mService.rebootWithLskf(packageName, reason, slotSwitch); return mService.rebootWithLskf(packageName, reason, slotSwitch);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -1414,8 +1475,8 @@ public class RecoverySystem {
* expects a slot switch for A/B devices. * expects a slot switch for A/B devices.
* *
*/ */
private boolean rebootWithLskfAssumeSlotSwitch(String packageName, String reason) private @ResumeOnRebootRebootErrorCode int rebootWithLskfAssumeSlotSwitch(String packageName,
throws IOException { String reason) throws IOException {
try { try {
return mService.rebootWithLskfAssumeSlotSwitch(packageName, reason); return mService.rebootWithLskfAssumeSlotSwitch(packageName, reason);
} catch (RemoteException e) { } catch (RemoteException e) {

View File

@@ -16,6 +16,13 @@
package com.android.server.recoverysystem; 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 static android.os.UserHandle.USER_SYSTEM;
import android.annotation.IntDef; import android.annotation.IntDef;
@@ -147,24 +154,6 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
ROR_REQUESTED_SKIP_CLEAR}) ROR_REQUESTED_SKIP_CLEAR})
private @interface ResumeOnRebootActionsOnClear {} 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. * 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) { boolean slotSwitch) {
if (packageName == null) { if (packageName == null) {
Slog.w(TAG, "Missing packageName when rebooting with lskf."); 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)) { if (!isLskfCaptured(packageName)) {
return REBOOT_ERROR_LSKF_NOT_CAPTURED; return RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED;
} }
if (!verifySlotForNextBoot(slotSwitch)) { if (!verifySlotForNextBoot(slotSwitch)) {
return REBOOT_ERROR_SLOT_MISMATCH; return RESUME_ON_REBOOT_REBOOT_ERROR_SLOT_MISMATCH;
} }
final long origId = Binder.clearCallingIdentity(); final long origId = Binder.clearCallingIdentity();
@@ -744,10 +733,10 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
if (!result) { if (!result) {
Slog.w(TAG, "Failure to escrow key for reboot"); 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() { private boolean useServerBasedRoR() {
@@ -788,12 +777,13 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
requestCount, slotSwitch, serverBased, durationSeconds, lskfCapturedCount); 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); @ResumeOnRebootRebootErrorCode int errorCode = armRebootEscrow(packageName, slotSwitch);
reportMetricsOnRebootWithLskf(packageName, slotSwitch, errorCode); reportMetricsOnRebootWithLskf(packageName, slotSwitch, errorCode);
if (errorCode != REBOOT_ERROR_NONE) { if (errorCode != RESUME_ON_REBOOT_REBOOT_ERROR_NONE) {
return false; return errorCode;
} }
// Clear the metrics prefs after a successful RoR reboot. // 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(); PowerManager pm = mInjector.getPowerManager();
pm.reboot(reason); pm.reboot(reason);
return true; return RESUME_ON_REBOOT_REBOOT_ERROR_UNSPECIFIED;
} }
@Override // Binder call for the legacy rebootWithLskf @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); mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
return rebootWithLskfImpl(packageName, reason, true); return rebootWithLskfImpl(packageName, reason, true);
} }
@Override // Binder call @Override // Binder call
public boolean rebootWithLskf(String packageName, String reason, boolean slotSwitch) { public @ResumeOnRebootRebootErrorCode int rebootWithLskf(String packageName, String reason,
boolean slotSwitch) {
enforcePermissionForResumeOnReboot(); enforcePermissionForResumeOnReboot();
return rebootWithLskfImpl(packageName, reason, slotSwitch); return rebootWithLskfImpl(packageName, reason, slotSwitch);
} }

View File

@@ -17,6 +17,7 @@
package com.android.server.recoverysystem; package com.android.server.recoverysystem;
import android.os.IRecoverySystem; import android.os.IRecoverySystem;
import android.os.RecoverySystem;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ShellCommand; import android.os.ShellCommand;
@@ -76,7 +77,8 @@ public class RecoverySystemShellCommand extends ShellCommand {
private int rebootAndApply() throws RemoteException { private int rebootAndApply() throws RemoteException {
String packageName = getNextArgRequired(); String packageName = getNextArgRequired();
String rebootReason = 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(); PrintWriter pw = getOutPrintWriter();
// Keep the old message for cts test. // Keep the old message for cts test.
pw.printf("%s Reboot and apply status: %s\n", packageName, pw.printf("%s Reboot and apply status: %s\n", packageName,

View File

@@ -16,7 +16,12 @@
package com.android.server.recoverysystem; 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.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.mockito.AdditionalMatchers.not; import static org.mockito.AdditionalMatchers.not;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
@@ -274,8 +279,7 @@ public class RecoverySystemServiceTest {
verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any()); verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any());
assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true));
assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "foobar", true), mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "foobar", true);
is(true));
verify(mIPowerManager).reboot(anyBoolean(), eq("foobar"), anyBoolean()); verify(mIPowerManager).reboot(anyBoolean(), eq("foobar"), anyBoolean());
} }
@@ -373,8 +377,7 @@ public class RecoverySystemServiceTest {
anyInt())).thenReturn(3); anyInt())).thenReturn(3);
when(mSharedPreferences.getLong(eq(RecoverySystemService.LSKF_CAPTURED_TIMESTAMP_PREF), when(mSharedPreferences.getLong(eq(RecoverySystemService.LSKF_CAPTURED_TIMESTAMP_PREF),
anyLong())).thenReturn(40_000L); anyLong())).thenReturn(40_000L);
assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true), mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true);
is(true));
verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean());
verify(mMetricsReporter).reportRebootEscrowRebootMetrics(eq(0), eq(1000), verify(mMetricsReporter).reportRebootEscrowRebootMetrics(eq(0), eq(1000),
eq(1) /* client count */, eq(2) /* request count */, eq(true) /* slot switch */, 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 { public void rebootWithLskf_slotMismatch_Failure() throws Exception {
assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true));
mRecoverySystemService.onPreparedForReboot(true); mRecoverySystemService.onPreparedForReboot(true);
assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", false), assertEquals(RESUME_ON_REBOOT_REBOOT_ERROR_SLOT_MISMATCH,
is(false)); mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", false));
} }
@Test @Test
public void rebootWithLskf_withoutPrepare_Failure() throws Exception { public void rebootWithLskf_withoutPrepare_Failure() throws Exception {
assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true), assertEquals(RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED,
is(false)); mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true));
} }
@Test @Test
public void rebootWithLskf_withNullCallerId_Failure() throws Exception { 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); verifyNoMoreInteractions(mIPowerManager);
} }
@@ -410,8 +414,7 @@ public class RecoverySystemServiceTest {
// Client B's clear won't affect client A's preparation. // Client B's clear won't affect client A's preparation.
assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true)); assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true));
assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true), mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true);
is(true));
verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean());
} }
@@ -428,8 +431,7 @@ public class RecoverySystemServiceTest {
when(mSharedPreferences.getLong(eq(RecoverySystemService.LSKF_CAPTURED_TIMESTAMP_PREF), when(mSharedPreferences.getLong(eq(RecoverySystemService.LSKF_CAPTURED_TIMESTAMP_PREF),
anyLong())).thenReturn(60_000L); anyLong())).thenReturn(60_000L);
assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true), mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true);
is(true));
verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean());
verify(mMetricsReporter).reportRebootEscrowRebootMetrics(eq(0), eq(1000), verify(mMetricsReporter).reportRebootEscrowRebootMetrics(eq(0), eq(1000),
eq(2) /* client count */, eq(2) /* request count */, eq(true) /* slot switch */, eq(2) /* client count */, eq(2) /* request count */, eq(true) /* slot switch */,
@@ -450,17 +452,15 @@ public class RecoverySystemServiceTest {
anyLong())).thenReturn(60_000L); anyLong())).thenReturn(60_000L);
assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true)); assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true));
assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true), assertEquals(RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED,
is(false)); mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true));
verifyNoMoreInteractions(mIPowerManager); verifyNoMoreInteractions(mIPowerManager);
verify(mMetricsReporter).reportRebootEscrowRebootMetrics(not(eq(0)), eq(1000), verify(mMetricsReporter).reportRebootEscrowRebootMetrics(not(eq(0)), eq(1000),
eq(1) /* client count */, anyInt() /* request count */, eq(true) /* slot switch */, eq(1) /* client count */, anyInt() /* request count */, eq(true) /* slot switch */,
anyBoolean(), eq(40), eq(1)/* lskf capture count */); anyBoolean(), eq(40), eq(1)/* lskf capture count */);
assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true)); assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true));
assertThat( mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true);
mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true),
is(true));
verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean());
verify(mMetricsReporter).reportRebootEscrowRebootMetrics((eq(0)), eq(2000), verify(mMetricsReporter).reportRebootEscrowRebootMetrics((eq(0)), eq(2000),
@@ -476,16 +476,15 @@ public class RecoverySystemServiceTest {
// Client A clears // Client A clears
assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true)); assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true));
assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true), assertEquals(RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED,
is(false)); mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true));
verifyNoMoreInteractions(mIPowerManager); verifyNoMoreInteractions(mIPowerManager);
// Client B clears // Client B clears
assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true)); assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true));
verify(mLockSettingsInternal).clearRebootEscrow(); verify(mLockSettingsInternal).clearRebootEscrow();
assertThat( assertEquals(RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED,
mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true), mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true));
is(false));
verifyNoMoreInteractions(mIPowerManager); verifyNoMoreInteractions(mIPowerManager);
} }