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; } } }