From e25ce8835ca7124d07d2cbe071ff54b5cdb63d29 Mon Sep 17 00:00:00 2001 From: Veena Arvind Date: Thu, 2 Nov 2023 22:35:58 +0000 Subject: Support unattended reboot with sim pin replay Bug: 305269414 Test: atest ConfigInfrastructureServiceUnitTests[com.google.android.configinfrastructure.apex] Change-Id: If60893c973b751a5a927a5076a2f82b512779793 --- service/Android.bp | 2 +- service/flags.aconfig | 7 + service/jarjar-rules.txt | 3 + .../server/deviceconfig/SimPinReplayManager.java | 144 +++++++++++++++++ .../deviceconfig/UnattendedRebootManager.java | 28 +++- service/javatests/Android.bp | 1 + .../deviceconfig/SimPinReplayManagerTest.java | 177 +++++++++++++++++++++ .../deviceconfig/UnattendedRebootManagerTest.java | 41 ++++- 8 files changed, 394 insertions(+), 9 deletions(-) create mode 100644 service/java/com/android/server/deviceconfig/SimPinReplayManager.java create mode 100644 service/javatests/src/com/android/server/deviceconfig/SimPinReplayManagerTest.java diff --git a/service/Android.bp b/service/Android.bp index 664505d..7fbec4a 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -26,7 +26,6 @@ java_sdk_library { permitted_packages: [ "android.provider", "com.android.server.deviceconfig", - //"com.google.protobuf", ], apex_available: [ "com.android.configinfrastructure", @@ -35,6 +34,7 @@ java_sdk_library { "modules-utils-build", "modules-utils-shell-command-handler", "device_config_reboot_flags_java_lib", + "guava", "libaconfig_java_proto_lite" ], libs: [ diff --git a/service/flags.aconfig b/service/flags.aconfig index a9ca293..e1396a0 100644 --- a/service/flags.aconfig +++ b/service/flags.aconfig @@ -12,3 +12,10 @@ flag { description: "This flag controls enabling the unattended reboot feature for applying flags." bug: "297502146" } + +flag { + name: "enable_sim_pin_replay" + namespace: "core_experiments_team_internal" + description: "This flag controls enabling sim pin replay for unattended reboot." + bug: "305269414" +} diff --git a/service/jarjar-rules.txt b/service/jarjar-rules.txt index ebaebab..c284d6e 100644 --- a/service/jarjar-rules.txt +++ b/service/jarjar-rules.txt @@ -1,3 +1,6 @@ rule com.android.modules.utils.** com.android.server.deviceconfig.internal.modules.utils.@1 rule com.google.protobuf.** com.android.server.deviceconfig.internal.protobuf.@1 +rule com.google.common.** com.android.server.deviceconfig.internal.common.@1 +rule javax.annotation.** com.android.server.deviceconfig.javax.annotation.@1 +rule com.google.thirdparty.publicsuffix.** com.android.server.deviceconfig.publicsuffix.@1 rule android.aconfig.** com.android.server.deviceconfig.internal.aconfig.@1 diff --git a/service/java/com/android/server/deviceconfig/SimPinReplayManager.java b/service/java/com/android/server/deviceconfig/SimPinReplayManager.java new file mode 100644 index 0000000..93c3f5f --- /dev/null +++ b/service/java/com/android/server/deviceconfig/SimPinReplayManager.java @@ -0,0 +1,144 @@ +package com.android.server.deviceconfig; + +import android.content.Context; +import android.content.res.Resources; +import android.os.PersistableBundle; +import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import android.util.Log; + +import com.google.common.collect.ImmutableList; + +/** + * If device contains a SIM PIN, must prepare Sim Pin + * Replay to unlock the device post reboot. + * + * @hide + */ +public class SimPinReplayManager { + + private static final String TAG = "UnattendedRebootManager"; + + // The identifier of the system resource value that determines whether auto-sim-unlock feature is + // enabled/disabled for the device. + private static final String SYSTEM_ENABLE_SIM_PIN_STORAGE_KEY = + "config_allow_pin_storage_for_unattended_reboot"; + // This is a copy of the hidden field + // CarrierConfigManager#KEY_STORE_SIM_PIN_FOR_UNATTENDED_REBOOT_BOOL. Phonesky uses this key to + // read the boolean value in carrier configs specifying whether to enable/disable auto-sim-unlock. + private static final String CARRIER_ENABLE_SIM_PIN_STORAGE_KEY = + "store_sim_pin_for_unattended_reboot_bool"; + + private Context mContext; + + SimPinReplayManager(Context context) { + mContext = context; + } + + /** Returns true, if no SIM PIN present or prepared SIM PIN Replay. */ + public boolean prepareSimPinReplay() { + // Is SIM Pin present? + ImmutableList pinLockedSubscriptionIds = getPinLockedSubscriptionIds(mContext); + if (pinLockedSubscriptionIds.isEmpty()) { + return true; + } + + if (!isSimPinStorageEnabled(mContext, pinLockedSubscriptionIds)) { + Log.w(TAG, "SIM PIN storage is disabled"); + return false; + } + + TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class); + if (telephonyManager == null) { + Log.e(TAG, "Failed to prepare SIM PIN Replay, TelephonyManager is null"); + return false; + } + + int prepareUnattendedRebootResult = telephonyManager.prepareForUnattendedReboot(); + if (prepareUnattendedRebootResult == TelephonyManager.PREPARE_UNATTENDED_REBOOT_SUCCESS) { + Log.i(TAG, "SIM PIN replay prepared"); + return true; + } + Log.w(TAG, "Failed to prepare SIM PIN Replay, " + prepareUnattendedRebootResult); + return false; + } + + /** Returns a list of telephony subscription IDs (SIM IDs) locked by PIN. */ + private static ImmutableList getPinLockedSubscriptionIds(Context context) { + SubscriptionManager subscriptionManager = context.getSystemService(SubscriptionManager.class); + int[] subscriptionIds = subscriptionManager.getActiveSubscriptionIdList(); + if (subscriptionIds.length == 0) { + return ImmutableList.of(); + } + + TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); + ImmutableList.Builder pinLockedSubscriptionIdsBuilder = ImmutableList.builder(); + for (int subscriptionId : subscriptionIds) { + if (telephonyManager.createForSubscriptionId(subscriptionId).isIccLockEnabled()) { + pinLockedSubscriptionIdsBuilder.add(subscriptionId); + } + } + return pinLockedSubscriptionIdsBuilder.build(); + } + + /** + * Returns true, if SIM PIN storage is enabled. + * + *

The SIM PIN storage might be disabled by OEM or by carrier, subscription (SIM) Id is + * required when checking if the corresponding SIM PIN storage is disabled by the carrier. + * + *

Both the OEM and carrier enable SIM PIN storage by default. If fails to read the OEM/carrier + * configs, it assume SIM PIN storage is enabled. + */ + private static boolean isSimPinStorageEnabled( + Context context, ImmutableList pinLockedSubscriptionIds) { + if (!isSystemEnableSimPin()) { + return false; + } + + // If the carrier enables SIM PIN. + CarrierConfigManager carrierConfigManager = + context.getSystemService(CarrierConfigManager.class); + if (carrierConfigManager == null) { + Log.w(TAG, "CarrierConfigManager is null"); + return true; + } + for (int pinLockedSubscriptionId : pinLockedSubscriptionIds) { + PersistableBundle subscriptionConfig = + carrierConfigManager.getConfigForSubId( + pinLockedSubscriptionId, CARRIER_ENABLE_SIM_PIN_STORAGE_KEY); + // Only disable if carrier explicitly disables sim pin storage. + if (!subscriptionConfig.isEmpty() + && !subscriptionConfig.getBoolean( + CARRIER_ENABLE_SIM_PIN_STORAGE_KEY, /* defaultValue= */ true)) { + Log.w( + TAG, + "The carrier disables SIM PIN storage on subscription ID " + pinLockedSubscriptionId); + return false; + } + } + Log.v(TAG, "SIM PIN Storage is enabled"); + return true; + } + + private static boolean isSystemEnableSimPin() { + try { + boolean value = + Resources.getSystem() + .getBoolean( + Resources.getSystem() + .getIdentifier( + SYSTEM_ENABLE_SIM_PIN_STORAGE_KEY, + /* defType= */ "bool", + /* defPackage= */ "android")); + Log.i(TAG, SYSTEM_ENABLE_SIM_PIN_STORAGE_KEY + " = " + value); + return value; + } catch (Resources.NotFoundException e) { + Log.e(TAG, "Could not read system resource value ," + SYSTEM_ENABLE_SIM_PIN_STORAGE_KEY); + // When not explicitly disabled, assume SIM PIN storage functions properly. + return true; + } + } +} diff --git a/service/java/com/android/server/deviceconfig/UnattendedRebootManager.java b/service/java/com/android/server/deviceconfig/UnattendedRebootManager.java index 8429d0a..2823b66 100644 --- a/service/java/com/android/server/deviceconfig/UnattendedRebootManager.java +++ b/service/java/com/android/server/deviceconfig/UnattendedRebootManager.java @@ -1,5 +1,7 @@ package com.android.server.deviceconfig; +import static com.android.server.deviceconfig.Flags.enableSimPinReplay; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AlarmManager; @@ -19,6 +21,7 @@ import android.os.RecoverySystem; import android.os.SystemClock; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; + import java.io.IOException; import java.time.Instant; import java.time.LocalDateTime; @@ -57,6 +60,8 @@ final class UnattendedRebootManager { private final UnattendedRebootManagerInjector mInjector; + private final SimPinReplayManager mSimPinReplayManager; + private static class InjectorImpl implements UnattendedRebootManagerInjector { InjectorImpl() { /*no op*/ @@ -133,9 +138,13 @@ final class UnattendedRebootManager { } @VisibleForTesting - UnattendedRebootManager(Context context, UnattendedRebootManagerInjector injector) { + UnattendedRebootManager( + Context context, + UnattendedRebootManagerInjector injector, + SimPinReplayManager simPinReplayManager) { mContext = context; mInjector = injector; + mSimPinReplayManager = simPinReplayManager; mContext.registerReceiver( new BroadcastReceiver() { @@ -160,7 +169,7 @@ final class UnattendedRebootManager { } UnattendedRebootManager(Context context) { - this(context, new InjectorImpl()); + this(context, new InjectorImpl(), new SimPinReplayManager(context)); } public void prepareUnattendedReboot() { @@ -213,7 +222,7 @@ final class UnattendedRebootManager { < mInjector.getRebootFrequency()) { Log.v( TAG, - "Device has already been rebooted in that last" + "Device has already been rebooted in that last " + mInjector.getRebootFrequency() + " days."); scheduleReboot(); @@ -235,7 +244,7 @@ final class UnattendedRebootManager { // Is network connected? // TODO(b/305259443): Use after-boot network connectivity projection if (!isNetworkConnected(mContext)) { - Log.i(TAG, "Network is not connected, schedule reboot for another time."); + Log.i(TAG, "Network is not connected, reschedule reboot."); mInjector.triggerRebootOnNetworkAvailable(mContext); return; } @@ -247,19 +256,24 @@ final class UnattendedRebootManager { .getHour(); if (currentHour < mInjector.getRebootStartTime() || currentHour >= mInjector.getRebootEndTime()) { - Log.v(TAG, "Reboot requested outside of reboot window, reschedule."); + Log.v(TAG, "Reboot requested outside of reboot window, reschedule reboot."); prepareUnattendedReboot(); scheduleReboot(); return; } + // Is preparing for SIM PIN replay successful? + if (enableSimPinReplay() && !mSimPinReplayManager.prepareSimPinReplay()) { + Log.w(TAG, "Sim Pin Replay failed, reschedule reboot"); + scheduleReboot(); + } // Proceed with RoR. - Log.v(TAG, "Rebooting device..."); + Log.v(TAG, "Rebooting device to apply device config flags."); try { int success = mInjector.rebootAndApply(mContext, REBOOT_REASON, /* slotSwitch= */ false); if (success != 0) { // If reboot is not successful, reschedule. - Log.w(TAG, "Unattended reboot failed, reschedule."); + Log.w(TAG, "Unattended reboot failed, reschedule reboot."); scheduleReboot(); } } catch (IOException e) { diff --git a/service/javatests/Android.bp b/service/javatests/Android.bp index d9617d8..0177890 100644 --- a/service/javatests/Android.bp +++ b/service/javatests/Android.bp @@ -44,6 +44,7 @@ android_test { "frameworks-base-testutils", "mockito-target-minus-junit4", "truth", + "flag-junit", ], libs: [ "android.test.base", diff --git a/service/javatests/src/com/android/server/deviceconfig/SimPinReplayManagerTest.java b/service/javatests/src/com/android/server/deviceconfig/SimPinReplayManagerTest.java new file mode 100644 index 0000000..f56a6dd --- /dev/null +++ b/service/javatests/src/com/android/server/deviceconfig/SimPinReplayManagerTest.java @@ -0,0 +1,177 @@ +package com.android.server.deviceconfig; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.ContextWrapper; +import android.os.PersistableBundle; +import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import android.util.Log; + +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Test; + +@SmallTest +public class SimPinReplayManagerTest { + + private static final String TAG = "SimPinReplayManagerTest"; + + // A copy of the hidden field CarrierConfigManager#KEY_STORE_SIM_PIN_FOR_UNATTENDED_REBOOT_BOOL. + public static final String CARRIER_ENABLE_SIM_PIN_STORAGE_KEY = + "store_sim_pin_for_unattended_reboot_bool"; + + SimPinReplayManager mSimPinReplayManager; + SubscriptionManager mSubscriptionManager; + TelephonyManager mTelephonyManager; + CarrierConfigManager mCarrierConfigManager; + + private Context mContext; + + @Before + public void setUp() { + + mSubscriptionManager = mock(SubscriptionManager.class); + mTelephonyManager = mock(TelephonyManager.class); + mCarrierConfigManager = mock(CarrierConfigManager.class); + + mContext = + new ContextWrapper(getInstrumentation().getTargetContext()) { + @Override + public Object getSystemService(String name) { + if (name.equals(Context.TELEPHONY_SUBSCRIPTION_SERVICE)) { + return mSubscriptionManager; + } else if (name.equals(Context.TELEPHONY_SERVICE)) { + return mTelephonyManager; + } else if (name.equals(Context.CARRIER_CONFIG_SERVICE)) { + return mCarrierConfigManager; + } + return super.getSystemService(name); + } + }; + + mSimPinReplayManager = new SimPinReplayManager(mContext); + } + + @Test + public void prepareSimPinReplay_success() { + Log.i(TAG, "prepareSimPinReplay_success"); + when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[] {1}); // has sim + TelephonyManager subIdManager = mock(TelephonyManager.class); + when(mTelephonyManager.createForSubscriptionId(1)).thenReturn(subIdManager); + when(subIdManager.isIccLockEnabled()).thenReturn(true); // has pin + PersistableBundle config = new PersistableBundle(); // empty carrier config + when(mCarrierConfigManager.getConfigForSubId(1, CARRIER_ENABLE_SIM_PIN_STORAGE_KEY)) + .thenReturn(config); + when(mTelephonyManager.prepareForUnattendedReboot()) + .thenReturn(TelephonyManager.PREPARE_UNATTENDED_REBOOT_SUCCESS); + + boolean isPrepared = mSimPinReplayManager.prepareSimPinReplay(); + + assertTrue(isPrepared); + } + + @Test + public void prepareSimPinReplay_noSim() { + Log.i(TAG, "prepareSimPinReplay_noSim"); + when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[] {}); // no sim + + boolean isPrepared = mSimPinReplayManager.prepareSimPinReplay(); + + assertTrue(isPrepared); + } + + @Test + public void prepareSimPinReplay_noSimPin() { + Log.i(TAG, "prepareSimPinReplay_noSimPin"); + when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[] {1}); // has sim + TelephonyManager subIdManager = mock(TelephonyManager.class); + when(mTelephonyManager.createForSubscriptionId(1)).thenReturn(subIdManager); + when(subIdManager.isIccLockEnabled()).thenReturn(false); // no pin + + boolean isPrepared = mSimPinReplayManager.prepareSimPinReplay(); + + assertTrue(isPrepared); + } + + @Test + public void prepareSimPinReplay_carrierDisableSimPin() { + Log.i(TAG, "prepareSimPinReplay_carrierDisableSimPin"); + when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[] {1}); // has sim + TelephonyManager subIdManager = mock(TelephonyManager.class); + when(mTelephonyManager.createForSubscriptionId(1)).thenReturn(subIdManager); + when(subIdManager.isIccLockEnabled()).thenReturn(true); // has pin + PersistableBundle config = new PersistableBundle(); + config.putBoolean(CARRIER_ENABLE_SIM_PIN_STORAGE_KEY, false); // carrier disabled + when(mCarrierConfigManager.getConfigForSubId(1, CARRIER_ENABLE_SIM_PIN_STORAGE_KEY)) + .thenReturn(config); + + boolean isPrepared = mSimPinReplayManager.prepareSimPinReplay(); + + assertFalse(isPrepared); + } + + @Test + public void prepareSimPinReplay_carrierEnabled() { + Log.i(TAG, "prepareSimPinReplay_carrierEnabled"); + when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[] {1}); // has sim + TelephonyManager subIdManager = mock(TelephonyManager.class); + when(mTelephonyManager.createForSubscriptionId(1)).thenReturn(subIdManager); + when(subIdManager.isIccLockEnabled()).thenReturn(true); // has pin + PersistableBundle config = new PersistableBundle(); + config.putBoolean(CARRIER_ENABLE_SIM_PIN_STORAGE_KEY, true); // carrier enabled + when(mCarrierConfigManager.getConfigForSubId(1, CARRIER_ENABLE_SIM_PIN_STORAGE_KEY)) + .thenReturn(config); + when(mTelephonyManager.prepareForUnattendedReboot()) + .thenReturn(TelephonyManager.PREPARE_UNATTENDED_REBOOT_SUCCESS); + + boolean isPrepared = mSimPinReplayManager.prepareSimPinReplay(); + + assertTrue(isPrepared); + } + + @Test + public void prepareSimPinReplay_prepareError() { + Log.i(TAG, "prepareSimPinReplay_prepareError"); + when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[] {1}); // has sim + TelephonyManager subIdManager = mock(TelephonyManager.class); + when(mTelephonyManager.createForSubscriptionId(1)).thenReturn(subIdManager); + when(subIdManager.isIccLockEnabled()).thenReturn(true); // has pin + PersistableBundle config = new PersistableBundle(); + config.putBoolean(CARRIER_ENABLE_SIM_PIN_STORAGE_KEY, true); // carrier enabled + when(mCarrierConfigManager.getConfigForSubId(1, CARRIER_ENABLE_SIM_PIN_STORAGE_KEY)) + .thenReturn(config); + when(mTelephonyManager.prepareForUnattendedReboot()) + .thenReturn(TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR); + + boolean isPrepared = mSimPinReplayManager.prepareSimPinReplay(); + + assertFalse(isPrepared); + } + + @Test + public void prepareSimPinReplay_preparePinRequired() { + Log.i(TAG, "prepareSimPinReplay_preparePinRequired"); + when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[] {1}); // has sim + TelephonyManager subIdManager = mock(TelephonyManager.class); + when(mTelephonyManager.createForSubscriptionId(1)).thenReturn(subIdManager); + when(subIdManager.isIccLockEnabled()).thenReturn(true); // has pin + PersistableBundle config = new PersistableBundle(); + config.putBoolean(CARRIER_ENABLE_SIM_PIN_STORAGE_KEY, true); // carrier enabled + when(mCarrierConfigManager.getConfigForSubId(1, CARRIER_ENABLE_SIM_PIN_STORAGE_KEY)) + .thenReturn(config); + when(mTelephonyManager.prepareForUnattendedReboot()) + .thenReturn(TelephonyManager.PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED); + + boolean isPrepared = mSimPinReplayManager.prepareSimPinReplay(); + + assertFalse(isPrepared); + } +} diff --git a/service/javatests/src/com/android/server/deviceconfig/UnattendedRebootManagerTest.java b/service/javatests/src/com/android/server/deviceconfig/UnattendedRebootManagerTest.java index 7d822b6..a0579f1 100644 --- a/service/javatests/src/com/android/server/deviceconfig/UnattendedRebootManagerTest.java +++ b/service/javatests/src/com/android/server/deviceconfig/UnattendedRebootManagerTest.java @@ -1,6 +1,8 @@ package com.android.server.deviceconfig; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; +import static com.android.server.deviceconfig.Flags.FLAG_ENABLE_SIM_PIN_REPLAY; + import static com.android.server.deviceconfig.UnattendedRebootManager.ACTION_RESUME_ON_REBOOT_LSKF_CAPTURED; import static com.android.server.deviceconfig.UnattendedRebootManager.ACTION_TRIGGER_REBOOT; import static com.google.common.truth.Truth.assertThat; @@ -10,6 +12,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import android.platform.test.flag.junit.SetFlagsRule; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import android.app.KeyguardManager; @@ -29,6 +32,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; @SmallTest @@ -53,9 +57,17 @@ public class UnattendedRebootManagerTest { private ConnectivityManager mConnectivityManager; private FakeInjector mFakeInjector; private UnattendedRebootManager mRebootManager; + private SimPinReplayManager mSimPinReplayManager; + + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Before public void setUp() throws Exception { + mSetFlagsRule.enableFlags(FLAG_ENABLE_SIM_PIN_REPLAY); + + mSimPinReplayManager = mock(SimPinReplayManager.class); mKeyguardManager = mock(KeyguardManager.class); mConnectivityManager = mock(ConnectivityManager.class); @@ -73,7 +85,7 @@ public class UnattendedRebootManagerTest { }; mFakeInjector = new FakeInjector(); - mRebootManager = new UnattendedRebootManager(mContext, mFakeInjector); + mRebootManager = new UnattendedRebootManager(mContext, mFakeInjector, mSimPinReplayManager); // Need to register receiver in tests so that the test doesn't trigger reboot requested by // deviceconfig. @@ -100,6 +112,7 @@ public class UnattendedRebootManagerTest { .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) .build()); + when(mSimPinReplayManager.prepareSimPinReplay()).thenReturn(true); mRebootManager.prepareUnattendedReboot(); mRebootManager.scheduleReboot(); @@ -119,6 +132,7 @@ public class UnattendedRebootManagerTest { .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) .build()); + when(mSimPinReplayManager.prepareSimPinReplay()).thenReturn(true); mRebootManager.prepareUnattendedReboot(); mRebootManager.scheduleReboot(); @@ -138,6 +152,7 @@ public class UnattendedRebootManagerTest { .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) .build()); + when(mSimPinReplayManager.prepareSimPinReplay()).thenReturn(true); mRebootManager.scheduleReboot(); @@ -146,11 +161,32 @@ public class UnattendedRebootManagerTest { assertThat(mFakeInjector.getActualRebootTime()).isEqualTo(RESCHEDULED_REBOOT_TIME); } + @Test + public void scheduleReboot_simPinPreparationFailed() { + Log.i(TAG, "scheduleReboot"); + when(mKeyguardManager.isDeviceSecure()).thenReturn(true); + when(mConnectivityManager.getNetworkCapabilities(any())) + .thenReturn( + new NetworkCapabilities.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) + .build()); + when(mSimPinReplayManager.prepareSimPinReplay()).thenReturn(false).thenReturn(true); + + mRebootManager.prepareUnattendedReboot(); + mRebootManager.scheduleReboot(); + + assertTrue(mFakeInjector.isRebootAndApplied()); + assertFalse(mFakeInjector.isRegularRebooted()); + assertThat(mFakeInjector.getActualRebootTime()).isEqualTo(RESCHEDULED_REBOOT_TIME); + } + @Test public void scheduleReboot_noInternet() { Log.i(TAG, "scheduleReboot_noInternet"); when(mKeyguardManager.isDeviceSecure()).thenReturn(true); when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(new NetworkCapabilities()); + when(mSimPinReplayManager.prepareSimPinReplay()).thenReturn(true); mRebootManager.prepareUnattendedReboot(); mRebootManager.scheduleReboot(); @@ -170,6 +206,7 @@ public class UnattendedRebootManagerTest { new NetworkCapabilities.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .build()); + when(mSimPinReplayManager.prepareSimPinReplay()).thenReturn(true); mRebootManager.prepareUnattendedReboot(); mRebootManager.scheduleReboot(); @@ -190,6 +227,7 @@ public class UnattendedRebootManagerTest { .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) .build()); + when(mSimPinReplayManager.prepareSimPinReplay()).thenReturn(true); mFakeInjector.setElapsedRealtime(82800000); // 23 hours mRebootManager.prepareUnattendedReboot(); @@ -210,6 +248,7 @@ public class UnattendedRebootManagerTest { .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) .build()); + when(mSimPinReplayManager.prepareSimPinReplay()).thenReturn(true); mFakeInjector.setNow(OUTSIDE_WINDOW_REBOOT_TIME); mRebootManager.prepareUnattendedReboot(); -- cgit v1.2.3