merge in lmp-mr1-release history after reset to lmp-mr1-dev
diff --git a/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java b/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
index 818f83e..9ac955d 100644
--- a/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
+++ b/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.telephony;
 
+import static android.Manifest.permission.READ_PHONE_STATE;
+
 import android.app.ActivityManagerNative;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -35,8 +37,10 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionInfo;
 import android.telephony.TelephonyManager;
+import com.android.internal.telephony.uicc.IccCardProxy;
 import com.android.internal.telephony.uicc.IccConstants;
 import com.android.internal.telephony.uicc.IccFileHandler;
+import com.android.internal.telephony.uicc.IccRecords;
 import com.android.internal.telephony.uicc.IccUtils;
 import android.text.TextUtils;
 
@@ -48,9 +52,13 @@
 public class SubscriptionInfoUpdater extends Handler {
     private static final String LOG_TAG = "SubscriptionInfoUpdater";
     private static final int PROJECT_SIM_NUM = TelephonyManager.getDefault().getPhoneCount();
-    private static final int EVENT_OFFSET = 8;
-    private static final int EVENT_QUERY_ICCID_DONE = 1;
+
+    private static final int EVENT_SIM_LOCKED_QUERY_ICCID_DONE = 1;
     private static final int EVENT_GET_NETWORK_SELECTION_MODE_DONE = 2;
+    private static final int EVENT_SIM_LOADED = 3;
+    private static final int EVENT_SIM_ABSENT = 4;
+    private static final int EVENT_SIM_LOCKED = 5;
+
     private static final String ICCID_STRING_FOR_NO_SIM = "";
     /**
      *  int[] sInsertSimState maintains all slots' SIM inserted status currently,
@@ -80,16 +88,10 @@
 
     private static Phone[] mPhone;
     private static Context mContext = null;
-    private static IccFileHandler[] mFh = new IccFileHandler[PROJECT_SIM_NUM];
     private static String mIccId[] = new String[PROJECT_SIM_NUM];
     private static int[] mInsertSimState = new int[PROJECT_SIM_NUM];
-    private static TelephonyManager mTelephonyMgr = null;
     private SubscriptionManager mSubscriptionManager = null;
 
-    // To prevent repeatedly update flow every time receiver SIM_STATE_CHANGE
-    private static boolean mNeedUpdate = true;
-
-
     public SubscriptionInfoUpdater(Context context, Phone[] phoneProxy, CommandsInterface[] ci) {
         logd("Constructor invoked");
 
@@ -99,10 +101,8 @@
 
         IntentFilter intentFilter = new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
         mContext.registerReceiver(sReceiver, intentFilter);
-    }
-
-    private int encodeEventId(int event, int slotId) {
-        return event << (slotId * EVENT_OFFSET);
+        intentFilter = new IntentFilter(IccCardProxy.ACTION_INTERNAL_SIM_STATE_CHANGED);
+        mContext.registerReceiver(sReceiver, intentFilter);
     }
 
     private final BroadcastReceiver sReceiver = new  BroadcastReceiver() {
@@ -110,122 +110,40 @@
         public void onReceive(Context context, Intent intent) {
             logd("[Receiver]+");
             String action = intent.getAction();
-            int slotId;
             logd("Action: " + action);
+
+            if (!action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED) &&
+                !action.equals(IccCardProxy.ACTION_INTERNAL_SIM_STATE_CHANGED)) {
+                return;
+            }
+
+            int slotId = intent.getIntExtra(PhoneConstants.SLOT_KEY,
+                    SubscriptionManager.INVALID_SIM_SLOT_INDEX);
+            logd("slotId: " + slotId);
+            if (slotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+                return;
+            }
+
+            String simStatus = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
+            logd("simStatus: " + simStatus);
+
             if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
-                String simStatus = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
-                slotId = intent.getIntExtra(PhoneConstants.SLOT_KEY,
-                        SubscriptionManager.INVALID_SIM_SLOT_INDEX);
-                logd("slotId: " + slotId + " simStatus: " + simStatus);
-                if (slotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
-                    return;
+                if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(simStatus)) {
+                    sendMessage(obtainMessage(EVENT_SIM_ABSENT, slotId, -1));
+                } else {
+                    logd("Ignoring simStatus: " + simStatus);
                 }
-                if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(simStatus)
-                        || IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(simStatus)
-                        || IccCardConstants.INTENT_VALUE_ICC_INTERNAL_LOCKED.equals(simStatus)) {
-                    if (mIccId[slotId] != null && mIccId[slotId].equals(ICCID_STRING_FOR_NO_SIM)) {
-                        logd("SIM" + (slotId + 1) + " hot plug in");
-                        mIccId[slotId] = null;
-                        mNeedUpdate = true;
-                    }
-                    //TODO: Use RetryManager to limit number of retries and do a exponential backoff
-                    if (((PhoneProxy)mPhone[slotId]).getIccFileHandler() != null) {
-                        queryIccId(slotId);
-                    } else {
-                        intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE,
-                                IccCardConstants.INTENT_VALUE_ICC_INTERNAL_LOCKED);
-                        ActivityManagerNative.broadcastStickyIntent(intent,
-                                "android.permission.READ_PHONE_STATE", UserHandle.USER_ALL);
-                    }
+            } else if (action.equals(IccCardProxy.ACTION_INTERNAL_SIM_STATE_CHANGED)) {
+                if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(simStatus)) {
+                    String reason = intent.getStringExtra(
+                        IccCardConstants.INTENT_KEY_LOCKED_REASON);
+                    sendMessage(obtainMessage(EVENT_SIM_LOCKED, slotId, -1, reason));
                 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(simStatus)) {
-                    queryIccId(slotId);
-                    if (mTelephonyMgr == null) {
-                        mTelephonyMgr = TelephonyManager.from(mContext);
-                    }
                     int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
                             SubscriptionManager.INVALID_SUBSCRIPTION_ID);
-
-                    if (SubscriptionManager.isValidSubscriptionId(subId)) {
-                        String msisdn = TelephonyManager.getDefault()
-                                .getLine1NumberForSubscriber(subId);
-                        ContentResolver contentResolver = mContext.getContentResolver();
-
-                        if (msisdn != null) {
-                            ContentValues number = new ContentValues(1);
-                            number.put(SubscriptionManager.NUMBER, msisdn);
-                            contentResolver.update(SubscriptionManager.CONTENT_URI, number,
-                                    SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "="
-                                    + Long.toString(subId), null);
-                        }
-
-                        SubscriptionInfo subInfo =
-                                mSubscriptionManager.getActiveSubscriptionInfo(subId);
-                        String nameToSet;
-                        String CarrierName =
-                                TelephonyManager.getDefault().getSimOperator(subId);
-                        logd("CarrierName = " + CarrierName);
-                        String simCarrierName =
-                                TelephonyManager.getDefault().getSimOperatorName(subId);
-                        ContentValues name = new ContentValues(1);
-
-                        if (subInfo != null
-                                && subInfo.getNameSource() !=
-                                SubscriptionManager.NAME_SOURCE_USER_INPUT) {
-                            if (!TextUtils.isEmpty(simCarrierName)) {
-                                nameToSet = simCarrierName;
-                            } else {
-                                nameToSet = "CARD " + Integer.toString(slotId + 1);
-                            }
-                            name.put(SubscriptionManager.DISPLAY_NAME, nameToSet);
-                            logd("sim name = " + nameToSet);
-                        }
-                        name.put(SubscriptionManager.CARRIER_NAME,
-                                !TextUtils.isEmpty(simCarrierName) ? simCarrierName :
-                                mContext.getString(com.android.internal.R.string.unknownName));
-                        contentResolver.update(SubscriptionManager.CONTENT_URI, name,
-                                SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID
-                                + "=" + Long.toString(subId), null);
-                        logd("carrier name = " + simCarrierName);
-
-                        /* Update preferred network type and network selection mode on IMSI change.
-                         * Storing last IMSI in SharedPreference for now. Can consider making it
-                         * part of subscription info db */
-                        SharedPreferences sp =
-                                PreferenceManager.getDefaultSharedPreferences(context);
-                        String storedImsi = sp.getString(CURR_IMSI + slotId, "");
-                        String newImsi = mPhone[slotId].getSubscriberId();
-
-                        if (!storedImsi.equals(newImsi)) {
-                            int networkType = RILConstants.PREFERRED_NETWORK_MODE;
-
-                            // Set the modem network mode
-                            mPhone[slotId].setPreferredNetworkType(networkType, null);
-                            Settings.Global.putInt(mPhone[slotId].getContext().getContentResolver(),
-                                    Settings.Global.PREFERRED_NETWORK_MODE + mPhone[slotId].getSubId(),
-                                    networkType);
-
-                            // Only support automatic selection mode on IMSI change.
-                            mPhone[slotId].getNetworkSelectionMode(
-                                    obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE));
-
-                            // Update stored IMSI
-                            SharedPreferences.Editor editor = sp.edit();
-                            editor.putString(CURR_IMSI + slotId, newImsi);
-                            editor.apply();
-                        }
-                    } else {
-                        logd("[Receiver] Invalid subId, could not update ContentResolver");
-                    }
-                } else if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(simStatus)) {
-                    if (mIccId[slotId] != null && !mIccId[slotId].equals(ICCID_STRING_FOR_NO_SIM)) {
-                        logd("SIM" + (slotId + 1) + " hot plug out");
-                        mNeedUpdate = true;
-                    }
-                    mFh[slotId] = null;
-                    mIccId[slotId] = ICCID_STRING_FOR_NO_SIM;
-                    if (isAllIccIdQueryDone() && mNeedUpdate) {
-                        updateSubscriptionInfoByIccId();
-                    }
+                    sendMessage(obtainMessage(EVENT_SIM_LOADED, slotId, subId));
+                } else {
+                    logd("Ignoring simStatus: " + simStatus);
                 }
             }
             logd("[Receiver]-");
@@ -268,22 +186,12 @@
 
     @Override
     public void handleMessage(Message msg) {
-        AsyncResult ar = (AsyncResult)msg.obj;
-        int msgNum = msg.what;
-        int slotId;
-        for (slotId = PhoneConstants.SUB1; slotId <= PhoneConstants.SUB3; slotId++) {
-            int pivot = 1 << (slotId * EVENT_OFFSET);
-            if (msgNum >= pivot) {
-                continue;
-            } else {
-                break;
-            }
-        }
-        slotId--;
-        int event = msgNum >> (slotId * EVENT_OFFSET);
-        switch (event) {
-            case EVENT_QUERY_ICCID_DONE:
-                logd("handleMessage : <EVENT_QUERY_ICCID_DONE> SIM" + (slotId + 1));
+        switch (msg.what) {
+            case EVENT_SIM_LOCKED_QUERY_ICCID_DONE: {
+                AsyncResult ar = (AsyncResult)msg.obj;
+                QueryIccIdUserObj uObj = (QueryIccIdUserObj) ar.userObj;
+                int slotId = uObj.slotId;
+                logd("handleMessage : <EVENT_SIM_LOCKED_QUERY_ICCID_DONE> SIM" + (slotId + 1));
                 if (ar.exception == null) {
                     if (ar.result != null) {
                         byte[] data = (byte[])ar.result;
@@ -297,11 +205,17 @@
                     logd("Query IccId fail: " + ar.exception);
                 }
                 logd("sIccId[" + slotId + "] = " + mIccId[slotId]);
-                if (isAllIccIdQueryDone() && mNeedUpdate) {
+                if (isAllIccIdQueryDone()) {
                     updateSubscriptionInfoByIccId();
                 }
+                broadcastSimStateChanged(slotId, IccCardConstants.INTENT_VALUE_ICC_LOCKED,
+                                         uObj.reason);
                 break;
-            case EVENT_GET_NETWORK_SELECTION_MODE_DONE:
+            }
+
+            case EVENT_GET_NETWORK_SELECTION_MODE_DONE: {
+                AsyncResult ar = (AsyncResult)msg.obj;
+                Integer slotId = (Integer)ar.userObj;
                 if (ar.exception == null && ar.result != null) {
                     int[] modes = (int[])ar.result;
                     if (modes[0] == 1) {  // Manual mode.
@@ -311,33 +225,52 @@
                     logd("EVENT_GET_NETWORK_SELECTION_MODE_DONE: error getting network mode.");
                 }
                 break;
+            }
+
+           case EVENT_SIM_LOADED:
+                handleSimLoaded(msg.arg1, msg.arg2);
+                break;
+
+            case EVENT_SIM_ABSENT:
+                handleSimAbsent(msg.arg1);
+                break;
+
+            case EVENT_SIM_LOCKED:
+                handleSimLocked(msg.arg1, (String) msg.obj);
+                break;
+
             default:
                 logd("Unknown msg:" + msg.what);
         }
     }
 
-    private void queryIccId(int slotId) {
-        logd("queryIccId: slotid=" + slotId);
-        if (mFh[slotId] == null) {
-            logd("Getting IccFileHandler");
-            if (mPhone[slotId].getIccCard() != null) {
-                mFh[slotId] = mPhone[slotId].getIccCard().getIccFileHandler();
-            }
-            /** Just in case file handler cannot be obtained from IccCard directly, we can use the
-             * earlier way of getting it from phone */
-            // TODO remove this if block
-             if (mFh[slotId] == null) {
-                logd("queryIccId: Could not get IccFileHandler directly from IccCard");
-                mFh[slotId] = ((PhoneProxy) mPhone[slotId]).getIccFileHandler();
-            }
+    private static class QueryIccIdUserObj {
+        public String reason;
+        public int slotId;
+
+        QueryIccIdUserObj(String reason, int slotId) {
+            this.reason = reason;
+            this.slotId = slotId;
+        }
+    };
+
+    private void handleSimLocked(int slotId, String reason) {
+        if (mIccId[slotId] != null && mIccId[slotId].equals(ICCID_STRING_FOR_NO_SIM)) {
+            logd("SIM" + (slotId + 1) + " hot plug in");
+            mIccId[slotId] = null;
         }
 
-        if (mFh[slotId] != null) {
+
+        IccFileHandler fileHandler = mPhone[slotId].getIccCard() == null ? null :
+                mPhone[slotId].getIccCard().getIccFileHandler();
+
+        if (fileHandler != null) {
             String iccId = mIccId[slotId];
             if (iccId == null) {
                 logd("Querying IccId");
-                mFh[slotId].loadEFTransparent(IccConstants.EF_ICCID,
-                        obtainMessage(encodeEventId(EVENT_QUERY_ICCID_DONE, slotId)));
+                fileHandler.loadEFTransparent(IccConstants.EF_ICCID,
+                        obtainMessage(EVENT_SIM_LOCKED_QUERY_ICCID_DONE,
+                                new QueryIccIdUserObj(reason, slotId)));
             } else {
                 logd("NOT Querying IccId its already set sIccid[" + slotId + "]=" + iccId);
             }
@@ -346,13 +279,118 @@
         }
     }
 
+    private void handleSimLoaded(int slotId, int subId) {
+        logd("handleSimStateLoadedInternal: slotId: " + slotId + " subId: " + subId);
+
+        // The SIM should be loaded at this state, but it is possible in cases such as SIM being
+        // removed or a refresh RESET that the IccRecords could be null. The right behavior is to
+        // not broadcast the SIM loaded.
+        IccRecords records = mPhone[slotId].getIccCard().getIccRecords();
+        if (records == null) {  // Possibly a race condition.
+            logd("onRecieve: IccRecords null");
+            return;
+        }
+        if (records.getIccId() == null) {
+            logd("onRecieve: IccID null");
+            return;
+        }
+        mIccId[slotId] = records.getIccId();
+
+        if (isAllIccIdQueryDone()) {
+            updateSubscriptionInfoByIccId();
+        }
+
+        if (SubscriptionManager.isValidSubscriptionId(subId)) {
+            String msisdn = TelephonyManager.getDefault()
+                    .getLine1NumberForSubscriber(subId);
+            ContentResolver contentResolver = mContext.getContentResolver();
+
+            if (msisdn != null) {
+                ContentValues number = new ContentValues(1);
+                number.put(SubscriptionManager.NUMBER, msisdn);
+                contentResolver.update(SubscriptionManager.CONTENT_URI, number,
+                        SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "="
+                        + Long.toString(subId), null);
+            }
+
+            SubscriptionInfo subInfo =
+                    mSubscriptionManager.getActiveSubscriptionInfo(subId);
+            String nameToSet;
+            String CarrierName =
+                    TelephonyManager.getDefault().getSimOperator(subId);
+            logd("CarrierName = " + CarrierName);
+            String simCarrierName =
+                    TelephonyManager.getDefault().getSimOperatorName(subId);
+            ContentValues name = new ContentValues(1);
+
+            if (subInfo != null
+                    && subInfo.getNameSource() !=
+                    SubscriptionManager.NAME_SOURCE_USER_INPUT) {
+                if (!TextUtils.isEmpty(simCarrierName)) {
+                    nameToSet = simCarrierName;
+                } else {
+                    nameToSet = "CARD " + Integer.toString(slotId + 1);
+                }
+                name.put(SubscriptionManager.DISPLAY_NAME, nameToSet);
+                logd("sim name = " + nameToSet);
+            }
+            name.put(SubscriptionManager.CARRIER_NAME,
+                    !TextUtils.isEmpty(simCarrierName) ? simCarrierName :
+                    mContext.getString(com.android.internal.R.string.unknownName));
+            contentResolver.update(SubscriptionManager.CONTENT_URI, name,
+                    SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID
+                    + "=" + Long.toString(subId), null);
+            logd("carrier name = " + simCarrierName);
+
+            /* Update preferred network type and network selection mode on IMSI change.
+             * Storing last IMSI in SharedPreference for now. Can consider making it
+             * part of subscription info db */
+            SharedPreferences sp =
+                    PreferenceManager.getDefaultSharedPreferences(mContext);
+            String storedImsi = sp.getString(CURR_IMSI + slotId, "");
+            String newImsi = mPhone[slotId].getSubscriberId();
+
+            if (!storedImsi.equals(newImsi)) {
+                int networkType = RILConstants.PREFERRED_NETWORK_MODE;
+
+                // Set the modem network mode
+                mPhone[slotId].setPreferredNetworkType(networkType, null);
+                Settings.Global.putInt(mPhone[slotId].getContext().getContentResolver(),
+                        Settings.Global.PREFERRED_NETWORK_MODE + mPhone[slotId].getSubId(),
+                        networkType);
+
+                // Only support automatic selection mode on IMSI change.
+                mPhone[slotId].getNetworkSelectionMode(
+                        obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE, new Integer(slotId)));
+
+                // Update stored IMSI
+                SharedPreferences.Editor editor = sp.edit();
+                editor.putString(CURR_IMSI + slotId, newImsi);
+                editor.apply();
+            }
+        } else {
+            logd("Invalid subId, could not update ContentResolver");
+        }
+
+        broadcastSimStateChanged(slotId, IccCardConstants.INTENT_VALUE_ICC_LOADED, null);
+    }
+
+    private void handleSimAbsent(int slotId) {
+        if (mIccId[slotId] != null && !mIccId[slotId].equals(ICCID_STRING_FOR_NO_SIM)) {
+            logd("SIM" + (slotId + 1) + " hot plug out");
+        }
+        mIccId[slotId] = ICCID_STRING_FOR_NO_SIM;
+        if (isAllIccIdQueryDone()) {
+            updateSubscriptionInfoByIccId();
+        }
+    }
+
     /**
      * TODO: Simplify more, as no one is interested in what happened
      * only what the current list contains.
      */
     synchronized private void updateSubscriptionInfoByIccId() {
         logd("updateSubscriptionInfoByIccId:+ Start");
-        mNeedUpdate = false;
 
         mSubscriptionManager.clearSubscriptionInfo();
 
@@ -501,6 +539,20 @@
         return newSim;
     }
 
+    private void broadcastSimStateChanged(int slotId, String state, String reason) {
+        Intent i = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        i.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+        i.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");
+        i.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, state);
+        i.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason);
+        SubscriptionManager.putPhoneIdAndSubIdExtra(i, slotId);
+        logd("Broadcasting intent ACTION_SIM_STATE_CHANGED " +
+             IccCardConstants.INTENT_VALUE_ICC_LOADED + " reason " + null +
+             " for mCardIndex : " + slotId);
+        ActivityManagerNative.broadcastStickyIntent(i, READ_PHONE_STATE,
+                UserHandle.USER_ALL);
+    }
+
     public void dispose() {
         logd("[dispose]");
         mContext.unregisterReceiver(sReceiver);
diff --git a/src/java/com/android/internal/telephony/uicc/IccCardProxy.java b/src/java/com/android/internal/telephony/uicc/IccCardProxy.java
index 5cafe21..8c13e73 100644
--- a/src/java/com/android/internal/telephony/uicc/IccCardProxy.java
+++ b/src/java/com/android/internal/telephony/uicc/IccCardProxy.java
@@ -119,6 +119,8 @@
     private boolean mInitialized = false;
     private State mExternalState = State.UNKNOWN;
 
+    public static final String ACTION_INTERNAL_SIM_STATE_CHANGED = "android.intent.action.internal_sim_state_changed";
+
     public IccCardProxy(Context context, CommandsInterface ci, int cardIndex) {
         if (DBG) log("ctor: ci=" + ci + " cardIndex=" + cardIndex);
         mContext = context;
@@ -364,7 +366,7 @@
     }
 
     private void onRecordsLoaded() {
-        broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_LOADED, null);
+        broadcastInternalIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_LOADED, null);
     }
 
     private void updateIccAvailability() {
@@ -513,6 +515,24 @@
         }
     }
 
+    private void broadcastInternalIccStateChangedIntent(String value, String reason) {
+        synchronized (mLock) {
+            if (mCardIndex == null) {
+                loge("broadcastInternalIccStateChangedIntent: Card Index is not set; Return!!");
+                return;
+            }
+
+            Intent intent = new Intent(ACTION_INTERNAL_SIM_STATE_CHANGED);
+            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+            intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");
+            intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value);
+            intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason);
+            SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mCardIndex);
+            log("Sending intent ACTION_INTERNAL_SIM_STATE_CHANGED" + " for mCardIndex : " + mCardIndex);
+            ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);
+        }
+    }
+
     private void setExternalState(State newState, boolean override) {
         synchronized (mLock) {
             if (mCardIndex == null || !SubscriptionManager.isValidSlotId(mCardIndex)) {
@@ -527,8 +547,15 @@
             mExternalState = newState;
             loge("setExternalState: set mCardIndex=" + mCardIndex + " mExternalState=" + mExternalState);
             setSystemProperty(PROPERTY_SIM_STATE, mCardIndex, getState().toString());
-            broadcastIccStateChangedIntent(getIccStateIntentString(mExternalState),
-                    getIccStateReason(mExternalState));
+
+            // For locked states, we should be sending internal broadcast.
+            if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(getIccStateIntentString(mExternalState))) {
+                broadcastInternalIccStateChangedIntent(getIccStateIntentString(mExternalState),
+                        getIccStateReason(mExternalState));
+            } else {
+                broadcastIccStateChangedIntent(getIccStateIntentString(mExternalState),
+                        getIccStateReason(mExternalState));
+            }
             // TODO: Need to notify registrants for other states as well.
             if ( State.ABSENT == mExternalState) {
                 mAbsentRegistrants.notifyRegistrants();