/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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_PROVIDER_PREPARATION_FAILURE; 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.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.AdditionalMatchers.not; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import android.content.Context; import android.content.IntentSender; import android.content.pm.PackageManager; import android.hardware.boot.IBootControl; import android.os.Handler; import android.os.IPowerManager; import android.os.IRecoverySystemProgressListener; import android.os.IThermalService; import android.os.Looper; import android.os.PowerManager; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.widget.LockSettingsInternal; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.io.FileWriter; /** * atest FrameworksServicesTests:RecoverySystemServiceTest */ @SmallTest @RunWith(AndroidJUnit4.class) public class RecoverySystemServiceTest { private RecoverySystemService mRecoverySystemService; private RecoverySystemServiceTestable.FakeSystemProperties mSystemProperties; private RecoverySystemService.UncryptSocket mUncryptSocket; private Context mContext; private IPowerManager mIPowerManager; private IThermalService mIThermalService; private FileWriter mUncryptUpdateFileWriter; private LockSettingsInternal mLockSettingsInternal; private IBootControl mIBootControl; private RecoverySystemServiceTestable.IMetricsReporter mMetricsReporter; private RecoverySystemService.PreferencesManager mSharedPreferences; private static final String FAKE_OTA_PACKAGE_NAME = "fake.ota.package"; private static final String FAKE_OTHER_PACKAGE_NAME = "fake.other.package"; @Before public void setup() throws Exception { mContext = mock(Context.class); mSystemProperties = new RecoverySystemServiceTestable.FakeSystemProperties(); mUncryptSocket = mock(RecoverySystemService.UncryptSocket.class); mUncryptUpdateFileWriter = mock(FileWriter.class); mLockSettingsInternal = mock(LockSettingsInternal.class); doReturn(true).when(mLockSettingsInternal).prepareRebootEscrow(); doReturn(true).when(mLockSettingsInternal).clearRebootEscrow(); doReturn(LockSettingsInternal.ARM_REBOOT_ERROR_NONE).when(mLockSettingsInternal) .armRebootEscrow(); Looper looper = InstrumentationRegistry.getContext().getMainLooper(); mIPowerManager = mock(IPowerManager.class); mIThermalService = mock(IThermalService.class); PowerManager powerManager = new PowerManager(mock(Context.class), mIPowerManager, mIThermalService, new Handler(looper)); mIBootControl = mock(IBootControl.class); when(mIBootControl.getCurrentSlot()).thenReturn(0); when(mIBootControl.getActiveBootSlot()).thenReturn(1); mMetricsReporter = mock(RecoverySystemServiceTestable.IMetricsReporter.class); mSharedPreferences = mock(RecoverySystemService.PreferencesManager.class); mRecoverySystemService = new RecoverySystemServiceTestable(mContext, mSystemProperties, powerManager, mUncryptUpdateFileWriter, mUncryptSocket, mLockSettingsInternal, mIBootControl, mMetricsReporter, mSharedPreferences); } @Test public void clearBcb_success() throws Exception { doNothing().when(mContext).enforceCallingOrSelfPermission( eq(android.Manifest.permission.RECOVERY), any()); when(mUncryptSocket.getPercentageUncrypted()).thenReturn(100); assertThat(mRecoverySystemService.clearBcb(), is(true)); assertThat(mSystemProperties.getCtlStart(), is("clear-bcb")); verify(mUncryptSocket).sendAck(); verify(mUncryptSocket).close(); } @Test public void clearBcb_uncrypt_failure() throws Exception { doNothing().when(mContext).enforceCallingOrSelfPermission( eq(android.Manifest.permission.RECOVERY), any()); when(mUncryptSocket.getPercentageUncrypted()).thenReturn(0); assertThat(mRecoverySystemService.clearBcb(), is(false)); assertThat(mSystemProperties.getCtlStart(), is("clear-bcb")); verify(mUncryptSocket).sendAck(); verify(mUncryptSocket).close(); } @Test(expected = SecurityException.class) public void clearBcb_noPerm() { doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission( eq(android.Manifest.permission.RECOVERY), any()); mRecoverySystemService.clearBcb(); } @Test public void setupBcb_success() throws Exception { doNothing().when(mContext).enforceCallingOrSelfPermission( eq(android.Manifest.permission.RECOVERY), any()); when(mUncryptSocket.getPercentageUncrypted()).thenReturn(100); assertThat(mRecoverySystemService.setupBcb("foo"), is(true)); assertThat(mSystemProperties.getCtlStart(), is("setup-bcb")); verify(mUncryptSocket).sendCommand("foo"); verify(mUncryptSocket).sendAck(); verify(mUncryptSocket).close(); } @Test public void setupBcb_uncrypt_failure() throws Exception { doNothing().when(mContext).enforceCallingOrSelfPermission( eq(android.Manifest.permission.RECOVERY), any()); when(mUncryptSocket.getPercentageUncrypted()).thenReturn(0); assertThat(mRecoverySystemService.setupBcb("foo"), is(false)); assertThat(mSystemProperties.getCtlStart(), is("setup-bcb")); verify(mUncryptSocket).sendCommand("foo"); verify(mUncryptSocket).sendAck(); verify(mUncryptSocket).close(); } @Test(expected = SecurityException.class) public void setupBcb_noPerm() { doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission( eq(android.Manifest.permission.RECOVERY), any()); mRecoverySystemService.setupBcb("foo"); } @Test public void rebootRecoveryWithCommand_success() throws Exception { doNothing().when(mContext).enforceCallingOrSelfPermission( eq(android.Manifest.permission.RECOVERY), any()); when(mUncryptSocket.getPercentageUncrypted()).thenReturn(100); mRecoverySystemService.rebootRecoveryWithCommand("foo"); assertThat(mSystemProperties.getCtlStart(), is("setup-bcb")); verify(mUncryptSocket).sendCommand("foo"); verify(mUncryptSocket).sendAck(); verify(mUncryptSocket).close(); verify(mIPowerManager).reboot(anyBoolean(), eq("recovery"), anyBoolean()); } @Test public void rebootRecoveryWithCommand_failure() throws Exception { doNothing().when(mContext).enforceCallingOrSelfPermission( eq(android.Manifest.permission.RECOVERY), any()); when(mUncryptSocket.getPercentageUncrypted()).thenReturn(0); mRecoverySystemService.rebootRecoveryWithCommand("foo"); assertThat(mSystemProperties.getCtlStart(), is("setup-bcb")); verify(mUncryptSocket).sendCommand("foo"); verify(mUncryptSocket).sendAck(); verify(mUncryptSocket).close(); verifyNoMoreInteractions(mIPowerManager); } @Test(expected = SecurityException.class) public void rebootRecoveryWithCommand_noPerm() { doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission( eq(android.Manifest.permission.RECOVERY), any()); mRecoverySystemService.rebootRecoveryWithCommand("foo"); } @Test public void uncrypt_success() throws Exception { doNothing().when(mContext).enforceCallingOrSelfPermission( eq(android.Manifest.permission.RECOVERY), any()); when(mUncryptSocket.getPercentageUncrypted()).thenReturn(0, 5, 25, 50, 90, 99, 100); IRecoverySystemProgressListener listener = mock(IRecoverySystemProgressListener.class); assertThat(mRecoverySystemService.uncrypt("foo.zip", listener), is(true)); assertThat(mSystemProperties.getCtlStart(), is("uncrypt")); verify(mUncryptSocket, times(7)).getPercentageUncrypted(); verify(mUncryptSocket).sendAck(); verify(mUncryptSocket).close(); } @Test(expected = SecurityException.class) public void requestLskf_protected() { when(mContext.checkCallingOrSelfPermission(anyString())).thenReturn( PackageManager.PERMISSION_DENIED); mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null); } @Test public void requestLskf_reportMetrics() throws Exception { IntentSender intentSender = mock(IntentSender.class); assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), is(true)); verify(mMetricsReporter).reportRebootEscrowPreparationMetrics( eq(1000), eq(0) /* need preparation */, eq(1) /* client count */); verify(mSharedPreferences).putLong(eq(FAKE_OTA_PACKAGE_NAME + RecoverySystemService.REQUEST_LSKF_TIMESTAMP_PREF_SUFFIX), eq(100_000L)); } @Test public void requestLskf_success() throws Exception { IntentSender intentSender = mock(IntentSender.class); assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), is(true)); when(mSharedPreferences.getLong(eq(FAKE_OTA_PACKAGE_NAME + RecoverySystemService.REQUEST_LSKF_TIMESTAMP_PREF_SUFFIX), anyLong())) .thenReturn(200_000L).thenReturn(5000L); mRecoverySystemService.onPreparedForReboot(true); verify(mMetricsReporter).reportRebootEscrowLskfCapturedMetrics( eq(1000), eq(1) /* client count */, eq(-1) /* invalid duration */); mRecoverySystemService.onPreparedForReboot(true); verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any()); verify(mMetricsReporter).reportRebootEscrowLskfCapturedMetrics( eq(1000), eq(1) /* client count */, eq(95) /* duration */); } @Test public void requestLskf_subsequentRequestNotClearPrepared() throws Exception { IntentSender intentSender = mock(IntentSender.class); assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), is(true)); mRecoverySystemService.onPreparedForReboot(true); verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any()); assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "foobar", true); verify(mIPowerManager).reboot(anyBoolean(), eq("foobar"), anyBoolean()); } @Test public void requestLskf_requestedButNotPrepared() throws Exception { IntentSender intentSender = mock(IntentSender.class); assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), is(true)); verify(intentSender, never()).sendIntent(any(), anyInt(), any(), any(), any()); verify(mMetricsReporter, never()).reportRebootEscrowLskfCapturedMetrics( anyInt(), anyInt(), anyInt()); } @Test public void requestLskf_lockSettingsError() throws Exception { IntentSender intentSender = mock(IntentSender.class); doReturn(false).when(mLockSettingsInternal).prepareRebootEscrow(); assertFalse(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender)); } @Test public void isLskfCaptured_requestedButNotPrepared() throws Exception { IntentSender intentSender = mock(IntentSender.class); assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), is(true)); assertThat(mRecoverySystemService.isLskfCaptured(FAKE_OTA_PACKAGE_NAME), is(false)); } @Test public void isLskfCaptured_Prepared() throws Exception { IntentSender intentSender = mock(IntentSender.class); assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), is(true)); mRecoverySystemService.onPreparedForReboot(true); verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any()); assertThat(mRecoverySystemService.isLskfCaptured(FAKE_OTA_PACKAGE_NAME), is(true)); } @Test(expected = SecurityException.class) public void clearLskf_protected() { when(mContext.checkCallingOrSelfPermission(anyString())).thenReturn( PackageManager.PERMISSION_DENIED); mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME); } @Test public void clearLskf_requestedThenCleared() throws Exception { IntentSender intentSender = mock(IntentSender.class); assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), is(true)); mRecoverySystemService.onPreparedForReboot(true); verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any()); assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true)); verify(mLockSettingsInternal).clearRebootEscrow(); } @Test public void clearLskf_callerNotRequested_Success() throws Exception { IntentSender intentSender = mock(IntentSender.class); assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), is(true)); assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true)); verify(mLockSettingsInternal, never()).clearRebootEscrow(); } @Test public void clearLskf_multiClient_BothClientsClear() throws Exception { IntentSender intentSender = mock(IntentSender.class); assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender), is(true)); assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, intentSender), is(true)); assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true)); verify(mLockSettingsInternal, never()).clearRebootEscrow(); assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true)); verify(mLockSettingsInternal).clearRebootEscrow(); } @Test public void startup_setRebootEscrowListener() throws Exception { mRecoverySystemService.onSystemServicesReady(); verify(mLockSettingsInternal).setRebootEscrowListener(any()); } @Test(expected = SecurityException.class) public void rebootWithLskf_protected() { when(mContext.checkCallingOrSelfPermission(anyString())).thenReturn( PackageManager.PERMISSION_DENIED); mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true); } @Test public void rebootWithLskf_Success() throws Exception { assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); mRecoverySystemService.onPreparedForReboot(true); when(mSharedPreferences.getInt(eq(FAKE_OTA_PACKAGE_NAME + RecoverySystemService.REQUEST_LSKF_COUNT_PREF_SUFFIX), anyInt())).thenReturn(2); when(mSharedPreferences.getInt(eq(RecoverySystemService.LSKF_CAPTURED_COUNT_PREF), anyInt())).thenReturn(3); when(mSharedPreferences.getLong(eq(RecoverySystemService.LSKF_CAPTURED_TIMESTAMP_PREF), anyLong())).thenReturn(40_000L); 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 */, anyBoolean(), eq(60) /* duration */, eq(3) /* lskf capture count */); } @Test public void rebootWithLskf_slotMismatch_Failure() throws Exception { assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); mRecoverySystemService.onPreparedForReboot(true); 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 { 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 { assertEquals(RESUME_ON_REBOOT_REBOOT_ERROR_INVALID_PACKAGE_NAME, mRecoverySystemService.rebootWithLskf(null, null, true)); verifyNoMoreInteractions(mIPowerManager); } @Test public void rebootWithLskf_multiClient_ClientASuccess() throws Exception { assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true)); mRecoverySystemService.onPreparedForReboot(true); // Client B's clear won't affect client A's preparation. assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true)); mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true); verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); } @Test public void rebootWithLskf_multiClient_success_reportMetrics() throws Exception { assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true)); mRecoverySystemService.onPreparedForReboot(true); when(mSharedPreferences.getInt(eq(FAKE_OTA_PACKAGE_NAME + RecoverySystemService.REQUEST_LSKF_COUNT_PREF_SUFFIX), anyInt())).thenReturn(2); when(mSharedPreferences.getInt(eq(RecoverySystemService.LSKF_CAPTURED_COUNT_PREF), anyInt())).thenReturn(1); when(mSharedPreferences.getLong(eq(RecoverySystemService.LSKF_CAPTURED_TIMESTAMP_PREF), anyLong())).thenReturn(60_000L); 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 */, anyBoolean(), eq(40), eq(1) /* lskf capture count */); } @Test public void rebootWithLskf_multiClient_ClientBSuccess() throws Exception { assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); mRecoverySystemService.onPreparedForReboot(true); assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true)); when(mSharedPreferences.getInt(eq(FAKE_OTHER_PACKAGE_NAME + RecoverySystemService.REQUEST_LSKF_COUNT_PREF_SUFFIX), anyInt())).thenReturn(2); when(mSharedPreferences.getInt(eq(RecoverySystemService.LSKF_CAPTURED_COUNT_PREF), anyInt())).thenReturn(1); when(mSharedPreferences.getLong(eq(RecoverySystemService.LSKF_CAPTURED_TIMESTAMP_PREF), anyLong())).thenReturn(60_000L); assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true)); 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)); mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true); verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); verify(mMetricsReporter).reportRebootEscrowRebootMetrics((eq(0)), eq(2000), eq(1) /* client count */, eq(2) /* request count */, eq(true) /* slot switch */, anyBoolean(), eq(40), eq(1) /* lskf capture count */); } @Test public void rebootWithLskf_multiClient_BothClientsClear_Failure() throws Exception { assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true)); mRecoverySystemService.onPreparedForReboot(true); assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true)); // Client A clears assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true)); 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(); assertEquals(RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED, mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true)); verifyNoMoreInteractions(mIPowerManager); } // TODO(xunchang) add more multi client tests @Test public void rebootWithLskf_armEscrowDataFatalError_Failure() throws Exception { doReturn(LockSettingsInternal.ARM_REBOOT_ERROR_PROVIDER_MISMATCH) .when(mLockSettingsInternal).armRebootEscrow(); assertTrue(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null)); mRecoverySystemService.onPreparedForReboot(true); assertTrue(mRecoverySystemService.isLskfCaptured(FAKE_OTA_PACKAGE_NAME)); when(mSharedPreferences.getInt(eq(FAKE_OTA_PACKAGE_NAME + RecoverySystemService.REQUEST_LSKF_COUNT_PREF_SUFFIX), anyInt())).thenReturn(1); when(mSharedPreferences.getInt(eq(RecoverySystemService.LSKF_CAPTURED_COUNT_PREF), anyInt())).thenReturn(1); assertEquals(RESUME_ON_REBOOT_REBOOT_ERROR_PROVIDER_PREPARATION_FAILURE, mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true)); // Verify that the RoR preparation state has been cleared. assertFalse(mRecoverySystemService.isLskfCaptured(FAKE_OTA_PACKAGE_NAME)); verify(mMetricsReporter).reportRebootEscrowRebootMetrics(eq(5004 /* provider mismatch */), eq(1000), eq(1) /* client count */, eq(1) /* request count */, eq(true) /* slot switch */, anyBoolean(), anyInt(), eq(1) /* lskf capture count */); } }