summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVeena Arvind <aveena@google.com>2023-11-02 22:35:58 +0000
committerVeena Arvind <aveena@google.com>2023-11-07 19:55:55 +0000
commite25ce8835ca7124d07d2cbe071ff54b5cdb63d29 (patch)
tree303c791707b98cc7787e50e88bda205483d61378
parent7f1820cb857a69547aa49c77c5c26176d6e5c8cc (diff)
downloadConfigInfrastructure-e25ce8835ca7124d07d2cbe071ff54b5cdb63d29.tar.gz
Support unattended reboot with sim pin replay
Bug: 305269414 Test: atest ConfigInfrastructureServiceUnitTests[com.google.android.configinfrastructure.apex] Change-Id: If60893c973b751a5a927a5076a2f82b512779793
-rw-r--r--service/Android.bp2
-rw-r--r--service/flags.aconfig7
-rw-r--r--service/jarjar-rules.txt3
-rw-r--r--service/java/com/android/server/deviceconfig/SimPinReplayManager.java144
-rw-r--r--service/java/com/android/server/deviceconfig/UnattendedRebootManager.java28
-rw-r--r--service/javatests/Android.bp1
-rw-r--r--service/javatests/src/com/android/server/deviceconfig/SimPinReplayManagerTest.java177
-rw-r--r--service/javatests/src/com/android/server/deviceconfig/UnattendedRebootManagerTest.java41
8 files changed, 394 insertions, 9 deletions
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 <a
+ * href="https://source.android.com/docs/core/ota/resume-on-reboot#sim-pin-replay">Sim Pin
+ * Replay</a> 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<Integer> 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<Integer> 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<Integer> 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.
+ *
+ * <p>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.
+ *
+ * <p>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<Integer> 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();
@@ -147,10 +162,31 @@ public class UnattendedRebootManagerTest {
}
@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();