1 package com.android.server.deviceconfig; 2 3 import android.content.Context; 4 import android.content.res.Resources; 5 import android.os.PersistableBundle; 6 import android.telephony.CarrierConfigManager; 7 import android.telephony.SubscriptionManager; 8 import android.telephony.TelephonyManager; 9 import android.util.Log; 10 11 import com.google.common.collect.ImmutableList; 12 13 /** 14 * If device contains a SIM PIN, must prepare <a 15 * href="https://source.android.com/docs/core/ota/resume-on-reboot#sim-pin-replay">Sim Pin 16 * Replay</a> to unlock the device post reboot. 17 * 18 * @hide 19 */ 20 public class SimPinReplayManager { 21 22 private static final String TAG = "UnattendedRebootManager"; 23 24 // The identifier of the system resource value that determines whether auto-sim-unlock feature is 25 // enabled/disabled for the device. 26 private static final String SYSTEM_ENABLE_SIM_PIN_STORAGE_KEY = 27 "config_allow_pin_storage_for_unattended_reboot"; 28 // This is a copy of the hidden field 29 // CarrierConfigManager#KEY_STORE_SIM_PIN_FOR_UNATTENDED_REBOOT_BOOL. Phonesky uses this key to 30 // read the boolean value in carrier configs specifying whether to enable/disable auto-sim-unlock. 31 private static final String CARRIER_ENABLE_SIM_PIN_STORAGE_KEY = 32 "store_sim_pin_for_unattended_reboot_bool"; 33 34 private Context mContext; 35 SimPinReplayManager(Context context)36 SimPinReplayManager(Context context) { 37 mContext = context; 38 } 39 40 /** Returns true, if no SIM PIN present or prepared SIM PIN Replay. */ prepareSimPinReplay()41 public boolean prepareSimPinReplay() { 42 // Is SIM Pin present? 43 ImmutableList<Integer> pinLockedSubscriptionIds = getPinLockedSubscriptionIds(mContext); 44 if (pinLockedSubscriptionIds.isEmpty()) { 45 return true; 46 } 47 48 if (!isSimPinStorageEnabled(mContext, pinLockedSubscriptionIds)) { 49 Log.w(TAG, "SIM PIN storage is disabled"); 50 return false; 51 } 52 53 TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class); 54 if (telephonyManager == null) { 55 Log.e(TAG, "Failed to prepare SIM PIN Replay, TelephonyManager is null"); 56 return false; 57 } 58 59 int prepareUnattendedRebootResult = telephonyManager.prepareForUnattendedReboot(); 60 if (prepareUnattendedRebootResult == TelephonyManager.PREPARE_UNATTENDED_REBOOT_SUCCESS) { 61 Log.i(TAG, "SIM PIN replay prepared"); 62 return true; 63 } 64 Log.w(TAG, "Failed to prepare SIM PIN Replay, " + prepareUnattendedRebootResult); 65 return false; 66 } 67 68 /** Returns a list of telephony subscription IDs (SIM IDs) locked by PIN. */ getPinLockedSubscriptionIds(Context context)69 private static ImmutableList<Integer> getPinLockedSubscriptionIds(Context context) { 70 SubscriptionManager subscriptionManager = context.getSystemService(SubscriptionManager.class); 71 int[] subscriptionIds = subscriptionManager.getActiveSubscriptionIdList(); 72 if (subscriptionIds.length == 0) { 73 return ImmutableList.of(); 74 } 75 76 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 77 ImmutableList.Builder<Integer> pinLockedSubscriptionIdsBuilder = ImmutableList.builder(); 78 for (int subscriptionId : subscriptionIds) { 79 if (telephonyManager.createForSubscriptionId(subscriptionId).isIccLockEnabled()) { 80 pinLockedSubscriptionIdsBuilder.add(subscriptionId); 81 } 82 } 83 return pinLockedSubscriptionIdsBuilder.build(); 84 } 85 86 /** 87 * Returns true, if SIM PIN storage is enabled. 88 * 89 * <p>The SIM PIN storage might be disabled by OEM or by carrier, subscription (SIM) Id is 90 * required when checking if the corresponding SIM PIN storage is disabled by the carrier. 91 * 92 * <p>Both the OEM and carrier enable SIM PIN storage by default. If fails to read the OEM/carrier 93 * configs, it assume SIM PIN storage is enabled. 94 */ isSimPinStorageEnabled( Context context, ImmutableList<Integer> pinLockedSubscriptionIds)95 private static boolean isSimPinStorageEnabled( 96 Context context, ImmutableList<Integer> pinLockedSubscriptionIds) { 97 if (!isSystemEnableSimPin()) { 98 return false; 99 } 100 101 // If the carrier enables SIM PIN. 102 CarrierConfigManager carrierConfigManager = 103 context.getSystemService(CarrierConfigManager.class); 104 if (carrierConfigManager == null) { 105 Log.w(TAG, "CarrierConfigManager is null"); 106 return true; 107 } 108 for (int pinLockedSubscriptionId : pinLockedSubscriptionIds) { 109 PersistableBundle subscriptionConfig = 110 carrierConfigManager.getConfigForSubId( 111 pinLockedSubscriptionId, CARRIER_ENABLE_SIM_PIN_STORAGE_KEY); 112 // Only disable if carrier explicitly disables sim pin storage. 113 if (!subscriptionConfig.isEmpty() 114 && !subscriptionConfig.getBoolean( 115 CARRIER_ENABLE_SIM_PIN_STORAGE_KEY, /* defaultValue= */ true)) { 116 Log.w( 117 TAG, 118 "The carrier disables SIM PIN storage on subscription ID " + pinLockedSubscriptionId); 119 return false; 120 } 121 } 122 Log.v(TAG, "SIM PIN Storage is enabled"); 123 return true; 124 } 125 isSystemEnableSimPin()126 private static boolean isSystemEnableSimPin() { 127 try { 128 boolean value = 129 Resources.getSystem() 130 .getBoolean( 131 Resources.getSystem() 132 .getIdentifier( 133 SYSTEM_ENABLE_SIM_PIN_STORAGE_KEY, 134 /* defType= */ "bool", 135 /* defPackage= */ "android")); 136 Log.i(TAG, SYSTEM_ENABLE_SIM_PIN_STORAGE_KEY + " = " + value); 137 return value; 138 } catch (Resources.NotFoundException e) { 139 Log.e(TAG, "Could not read system resource value ," + SYSTEM_ENABLE_SIM_PIN_STORAGE_KEY); 140 // When not explicitly disabled, assume SIM PIN storage functions properly. 141 return true; 142 } 143 } 144 } 145