Change to read carrier specific config only after reading IMSI.
[android/platform/frameworks/opt/telephony.git] / src / java / com / android / internal / telephony / uicc / SIMRecords.java
index 26bd7ae..3acbd4d 100644 (file)
 
 package com.android.internal.telephony.uicc;
 
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
 import android.content.Context;
 import android.os.AsyncResult;
 import android.os.Message;
 import android.os.SystemProperties;
+import android.telephony.TelephonyManager;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.SmsMessage;
 import android.text.TextUtils;
 import android.telephony.Rlog;
+import android.content.res.Resources;
 
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.MccTable;
 import com.android.internal.telephony.SmsConstants;
+import com.android.internal.telephony.SubscriptionController;
 import com.android.internal.telephony.gsm.SimTlv;
+import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
+import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -76,6 +78,8 @@ public class SIMRecords extends IccRecords {
     byte[] mEfCff = null;
     byte[] mEfCfis = null;
 
+    byte[] mEfLi = null;
+    byte[] mEfPl = null;
 
     int mSpnDisplayCondition;
     // Numeric network codes listed in TS 51.011 EF[SPDI]
@@ -158,6 +162,8 @@ public class SIMRecords extends IccRecords {
     private static final int EVENT_GET_CFIS_DONE = 32;
     private static final int EVENT_GET_CSP_CPHS_DONE = 33;
     private static final int EVENT_GET_GID1_DONE = 34;
+    private static final int EVENT_APP_LOCKED = 35;
+    private static final int EVENT_GET_GID2_DONE = 36;
 
     // Lookup table for carriers known to produce SIMs which incorrectly indicate MNC length.
 
@@ -202,6 +208,7 @@ public class SIMRecords extends IccRecords {
         // Start off by setting empty state
         resetRecords();
         mParentApp.registerForReady(this, EVENT_APP_READY, null);
+        mParentApp.registerForLocked(this, EVENT_APP_LOCKED, null);
         if (DBG) log("SIMRecords X ctor this=" + this);
     }
 
@@ -212,6 +219,7 @@ public class SIMRecords extends IccRecords {
         mCi.unregisterForIccRefresh(this);
         mCi.unSetOnSmsOnSim(this);
         mParentApp.unregisterForReady(this);
+        mParentApp.unregisterForLocked(this);
         resetRecords();
         super.dispose();
     }
@@ -225,8 +233,8 @@ public class SIMRecords extends IccRecords {
         mImsi = null;
         mMsisdn = null;
         mVoiceMailNum = null;
-        mCountVoiceMessages = 0;
         mMncLength = UNINITIALIZED;
+        log("setting0 mMncLength" + mMncLength);
         mIccId = null;
         // -1 means no EF_SPN found; treat accordingly.
         mSpnDisplayCondition = -1;
@@ -235,13 +243,15 @@ public class SIMRecords extends IccRecords {
         mSpdiNetworks = null;
         mPnnHomeName = null;
         mGid1 = null;
+        mGid2 = null;
 
         mAdnCache.reset();
 
         log("SIMRecords: onRadioOffOrNotAvailable set 'gsm.sim.operator.numeric' to operator=null");
-        SystemProperties.set(PROPERTY_ICC_OPERATOR_NUMERIC, null);
-        SystemProperties.set(PROPERTY_ICC_OPERATOR_ALPHA, null);
-        SystemProperties.set(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, null);
+        log("update icc_operator_numeric=" + null);
+        mTelephonyManager.setSimOperatorNumericForPhone(mParentApp.getPhoneId(), "");
+        mTelephonyManager.setSimOperatorNameForPhone(mParentApp.getPhoneId(), "");
+        mTelephonyManager.setSimCountryIsoForPhone(mParentApp.getPhoneId(), "");
 
         // recordsRequested is set to false indicating that the SIM
         // read requests made so far are not valid. This is set to
@@ -271,10 +281,32 @@ public class SIMRecords extends IccRecords {
     }
 
     @Override
+    public String getGid2() {
+        return mGid2;
+    }
+
+    @Override
     public UsimServiceTable getUsimServiceTable() {
         return mUsimServiceTable;
     }
 
+    private int getExtFromEf(int ef) {
+        int ext;
+        switch (ef) {
+            case EF_MSISDN:
+                /* For USIM apps use EXT5. (TS 31.102 Section 4.2.37) */
+                if (mParentApp.getType() == AppType.APPTYPE_USIM) {
+                    ext = EF_EXT5;
+                } else {
+                    ext = EF_EXT1;
+                }
+                break;
+            default:
+                ext = EF_EXT1;
+        }
+        return ext;
+    }
+
     /**
      * Set subscriber number to SIM record
      *
@@ -294,15 +326,16 @@ public class SIMRecords extends IccRecords {
     public void setMsisdnNumber(String alphaTag, String number,
             Message onComplete) {
 
-        mMsisdn = number;
-        mMsisdnTag = alphaTag;
+        // If the SIM card is locked by PIN, we will set EF_MSISDN fail.
+        // In that case, msisdn and msisdnTag should not be update.
+        mNewMsisdn = number;
+        mNewMsisdnTag = alphaTag;
 
-        if(DBG) log("Set MSISDN: " + mMsisdnTag + " " + /*mMsisdn*/ "xxxxxxx");
+        if(DBG) log("Set MSISDN: " + mNewMsisdnTag + " " + /*mNewMsisdn*/ "xxxxxxx");
 
+        AdnRecord adn = new AdnRecord(mNewMsisdnTag, mNewMsisdn);
 
-        AdnRecord adn = new AdnRecord(mMsisdnTag, mMsisdn);
-
-        new AdnRecordLoader(mFh).updateEF(adn, EF_MSISDN, EF_EXT1, 1, null,
+        new AdnRecordLoader(mFh).updateEF(adn, EF_MSISDN, getExtFromEf(EF_MSISDN), 1, null,
                 obtainMessage(EVENT_SET_MSISDN_DONE, onComplete));
     }
 
@@ -395,26 +428,13 @@ public class SIMRecords extends IccRecords {
             return;
         }
 
-        // range check
-        if (countWaiting < 0) {
-            countWaiting = -1;
-        } else if (countWaiting > 0xff) {
-            // TS 23.040 9.2.3.24.2
-            // "The value 255 shall be taken to mean 255 or greater"
-            countWaiting = 0xff;
-        }
-
-        mCountVoiceMessages = countWaiting;
-
-        mRecordsEventsRegistrants.notifyResult(EVENT_MWI);
-
         try {
             if (mEfMWIS != null) {
                 // TS 51.011 10.3.45
 
                 // lsb of byte 0 is 'voicemail' status
                 mEfMWIS[0] = (byte)((mEfMWIS[0] & 0xfe)
-                                    | (mCountVoiceMessages == 0 ? 0 : 1));
+                                    | (countWaiting == 0 ? 0 : 1));
 
                 // byte 1 is the number of voice messages waiting
                 if (countWaiting < 0) {
@@ -427,14 +447,13 @@ public class SIMRecords extends IccRecords {
 
                 mFh.updateEFLinearFixed(
                     EF_MWIS, 1, mEfMWIS, null,
-                    obtainMessage (EVENT_UPDATE_DONE, EF_MWIS));
+                    obtainMessage (EVENT_UPDATE_DONE, EF_MWIS, 0));
             }
 
             if (mEfCPHS_MWI != null) {
                     // Refer CPHS4_2.WW6 B4.2.3
                 mEfCPHS_MWI[0] = (byte)((mEfCPHS_MWI[0] & 0xf0)
-                            | (mCountVoiceMessages == 0 ? 0x5 : 0xa));
-
+                            | (countWaiting == 0 ? 0x5 : 0xa));
                 mFh.updateEFTransparent(
                     EF_VOICE_MAIL_INDICATOR_CPHS, mEfCPHS_MWI,
                     obtainMessage (EVENT_UPDATE_DONE, EF_VOICE_MAIL_INDICATOR_CPHS));
@@ -450,6 +469,37 @@ public class SIMRecords extends IccRecords {
         return ((data != null) && (data[0] >= 1) && (data[0] <= 4));
     }
 
+    public int getVoiceMessageCount() {
+        boolean voiceMailWaiting = false;
+        int countVoiceMessages = 0;
+        if (mEfMWIS != null) {
+            // Use this data if the EF[MWIS] exists and
+            // has been loaded
+            // Refer TS 51.011 Section 10.3.45 for the content description
+            voiceMailWaiting = ((mEfMWIS[0] & 0x01) != 0);
+            countVoiceMessages = mEfMWIS[1] & 0xff;
+
+            if (voiceMailWaiting && countVoiceMessages == 0) {
+                // Unknown count = -1
+                countVoiceMessages = -1;
+            }
+            if(DBG) log(" VoiceMessageCount from SIM MWIS = " + countVoiceMessages);
+        } else if (mEfCPHS_MWI != null) {
+            // use voice mail count from CPHS
+            int indicator = (int) (mEfCPHS_MWI[0] & 0xf);
+
+            // Refer CPHS4_2.WW6 B4.2.3
+            if (indicator == 0xA) {
+                // Unknown count = -1
+                countVoiceMessages = -1;
+            } else if (indicator == 0x5) {
+                countVoiceMessages = 0;
+            }
+            if(DBG) log(" VoiceMessageCount from SIM CPHS = " + countVoiceMessages);
+        }
+        return countVoiceMessages;
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -578,6 +628,10 @@ public class SIMRecords extends IccRecords {
                 onReady();
                 break;
 
+            case EVENT_APP_LOCKED:
+                onLocked();
+                break;
+
             /* IO events */
             case EVENT_GET_IMSI_DONE:
                 isRecordLoadResponse = true;
@@ -598,7 +652,8 @@ public class SIMRecords extends IccRecords {
                     mImsi = null;
                 }
 
-                log("IMSI: " + /* imsi.substring(0, 6) +*/ "xxxxxxx");
+                log("IMSI: mMncLength=" + mMncLength);
+                log("IMSI: " + mImsi.substring(0, 6) + "xxxxxxx");
 
                 if (((mMncLength == UNKNOWN) || (mMncLength == 2)) &&
                         ((mImsi != null) && (mImsi.length() >= 6))) {
@@ -606,6 +661,7 @@ public class SIMRecords extends IccRecords {
                     for (String mccmnc : MCCMNC_CODES_HAVING_3DIGITS_MNC) {
                         if (mccmnc.equals(mccmncCode)) {
                             mMncLength = 3;
+                            log("IMSI: setting1 mMncLength=" + mMncLength);
                             break;
                         }
                     }
@@ -617,15 +673,18 @@ public class SIMRecords extends IccRecords {
                     try {
                         int mcc = Integer.parseInt(mImsi.substring(0,3));
                         mMncLength = MccTable.smallestDigitsMccForMnc(mcc);
+                        log("setting2 mMncLength=" + mMncLength);
                     } catch (NumberFormatException e) {
                         mMncLength = UNKNOWN;
-                        loge("Corrupt IMSI!");
+                        loge("Corrupt IMSI! setting3 mMncLength=" + mMncLength);
                     }
                 }
 
                 if (mMncLength != UNKNOWN && mMncLength != UNINITIALIZED) {
+                    log("update mccmnc=" + mImsi.substring(0, 3 + mMncLength));
                     // finally have both the imsi and the mncLength and can parse the imsi properly
-                    MccTable.updateMccMncConfiguration(mContext, mImsi.substring(0, 3 + mMncLength));
+                    MccTable.updateMccMncConfiguration(mContext,
+                            mImsi.substring(0, 3 + mMncLength), false);
                 }
                 mImsiReadyRegistrants.notifyRegistrants();
             break;
@@ -744,6 +803,12 @@ public class SIMRecords extends IccRecords {
                 isRecordLoadResponse = false;
                 ar = (AsyncResult)msg.obj;
 
+                if (ar.exception == null) {
+                    mMsisdn = mNewMsisdn;
+                    mMsisdnTag = mNewMsisdnTag;
+                    log("Success to update EF[MSISDN]");
+                }
+
                 if (ar.userObj != null) {
                     AsyncResult.forMessage(((Message) ar.userObj)).exception
                             = ar.exception;
@@ -757,30 +822,21 @@ public class SIMRecords extends IccRecords {
                 ar = (AsyncResult)msg.obj;
                 data = (byte[])ar.result;
 
+                if(DBG) log("EF_MWIS : " + IccUtils.bytesToHexString(data));
+
                 if (ar.exception != null) {
+                    if(DBG) log("EVENT_GET_MWIS_DONE exception = "
+                            + ar.exception);
                     break;
                 }
 
-                log("EF_MWIS: " + IccUtils.bytesToHexString(data));
-
-                mEfMWIS = data;
-
                 if ((data[0] & 0xff) == 0xff) {
-                    log("Uninitialized record MWIS");
+                    if(DBG) log("SIMRecords: Uninitialized record MWIS");
                     break;
                 }
 
-                // Refer TS 51.011 Section 10.3.45 for the content description
-                boolean voiceMailWaiting = ((data[0] & 0x01) != 0);
-                mCountVoiceMessages = data[1] & 0xff;
-
-                if (voiceMailWaiting && mCountVoiceMessages == 0) {
-                    // Unknown count = -1
-                    mCountVoiceMessages = -1;
-                }
-
-                mRecordsEventsRegistrants.notifyResult(EVENT_MWI);
-            break;
+                mEfMWIS = data;
+                break;
 
             case EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE:
                 isRecordLoadResponse = true;
@@ -788,29 +844,16 @@ public class SIMRecords extends IccRecords {
                 ar = (AsyncResult)msg.obj;
                 data = (byte[])ar.result;
 
+                if(DBG) log("EF_CPHS_MWI: " + IccUtils.bytesToHexString(data));
+
                 if (ar.exception != null) {
+                    if(DBG) log("EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE exception = "
+                            + ar.exception);
                     break;
                 }
 
                 mEfCPHS_MWI = data;
-
-                // Use this data if the EF[MWIS] exists and
-                // has been loaded
-
-                if (mEfMWIS == null) {
-                    int indicator = data[0] & 0xf;
-
-                    // Refer CPHS4_2.WW6 B4.2.3
-                    if (indicator == 0xA) {
-                        // Unknown count = -1
-                        mCountVoiceMessages = -1;
-                    } else if (indicator == 0x5) {
-                        mCountVoiceMessages = 0;
-                    }
-
-                    mRecordsEventsRegistrants.notifyResult(EVENT_MWI);
-                }
-            break;
+                break;
 
             case EVENT_GET_ICCID_DONE:
                 isRecordLoadResponse = true;
@@ -853,17 +896,21 @@ public class SIMRecords extends IccRecords {
                     }
 
                     mMncLength = data[3] & 0xf;
+                    log("setting4 mMncLength=" + mMncLength);
 
                     if (mMncLength == 0xf) {
                         mMncLength = UNKNOWN;
+                        log("setting5 mMncLength=" + mMncLength);
                     }
                 } finally {
                     if (((mMncLength == UNINITIALIZED) || (mMncLength == UNKNOWN) ||
                             (mMncLength == 2)) && ((mImsi != null) && (mImsi.length() >= 6))) {
                         String mccmncCode = mImsi.substring(0, 6);
+                        log("mccmncCode=" + mccmncCode);
                         for (String mccmnc : MCCMNC_CODES_HAVING_3DIGITS_MNC) {
                             if (mccmnc.equals(mccmncCode)) {
                                 mMncLength = 3;
+                                log("setting6 mMncLength=" + mMncLength);
                                 break;
                             }
                         }
@@ -875,22 +922,23 @@ public class SIMRecords extends IccRecords {
                                 int mcc = Integer.parseInt(mImsi.substring(0,3));
 
                                 mMncLength = MccTable.smallestDigitsMccForMnc(mcc);
+                                log("setting7 mMncLength=" + mMncLength);
                             } catch (NumberFormatException e) {
                                 mMncLength = UNKNOWN;
-                                loge("Corrupt IMSI!");
+                                loge("Corrupt IMSI! setting8 mMncLength=" + mMncLength);
                             }
                         } else {
                             // Indicate we got this info, but it didn't contain the length.
                             mMncLength = UNKNOWN;
-
-                            log("MNC length not present in EF_AD");
+                            log("MNC length not present in EF_AD setting9 mMncLength=" + mMncLength);
                         }
                     }
                     if (mImsi != null && mMncLength != UNKNOWN) {
                         // finally have both imsi and the length of the mnc and can parse
                         // the imsi properly
+                        log("update mccmnc=" + mImsi.substring(0, 3 + mMncLength));
                         MccTable.updateMccMncConfiguration(mContext,
-                                mImsi.substring(0, 3 + mMncLength));
+                                mImsi.substring(0, 3 + mMncLength), false);
                     }
                 }
             break;
@@ -1040,6 +1088,7 @@ public class SIMRecords extends IccRecords {
                 isRecordLoadResponse = false;
                 ar = (AsyncResult)msg.obj;
 
+                if (DBG) log("EVENT_SET_MBDN_DONE ex:" + ar.exception);
                 if (ar.exception == null) {
                     mVoiceMailNum = mNewVoiceMailNum;
                     mVoiceMailTag = mNewVoiceMailTag;
@@ -1072,8 +1121,18 @@ public class SIMRecords extends IccRecords {
                                     onCphsCompleted));
                 } else {
                     if (ar.userObj != null) {
-                        AsyncResult.forMessage(((Message) ar.userObj)).exception
+                        Resources resource = Resources.getSystem();
+                        if (ar.exception != null && resource.getBoolean(com.android.internal.
+                                    R.bool.editable_voicemailnumber)) {
+                            // GSMPhone will store vm number on device
+                            // when IccVmNotSupportedException occurred
+                            AsyncResult.forMessage(((Message) ar.userObj)).exception
+                                = new IccVmNotSupportedException(
+                                        "Update SIM voice mailbox error");
+                        } else {
+                            AsyncResult.forMessage(((Message) ar.userObj)).exception
                                 = ar.exception;
+                        }
                         ((Message) ar.userObj).sendToTarget();
                     }
                 }
@@ -1160,6 +1219,22 @@ public class SIMRecords extends IccRecords {
 
                 break;
 
+            case EVENT_GET_GID2_DONE:
+                isRecordLoadResponse = true;
+
+                ar = (AsyncResult)msg.obj;
+                data =(byte[])ar.result;
+
+                if (ar.exception != null) {
+                    loge("Exception in get GID2 " + ar.exception);
+                    mGid2 = null;
+                    break;
+                }
+                mGid2 = IccUtils.bytesToHexString(data);
+                log("GID2: " + mGid2);
+
+                break;
+
             default:
                 super.handleMessage(msg);   // IccRecords handles generic record load responses
 
@@ -1174,6 +1249,28 @@ public class SIMRecords extends IccRecords {
         }
     }
 
+    private class EfPlLoaded implements IccRecordLoaded {
+        public String getEfName() {
+            return "EF_PL";
+        }
+
+        public void onRecordLoaded(AsyncResult ar) {
+            mEfPl = (byte[]) ar.result;
+            if (DBG) log("EF_PL=" + IccUtils.bytesToHexString(mEfPl));
+        }
+    }
+
+    private class EfUsimLiLoaded implements IccRecordLoaded {
+        public String getEfName() {
+            return "EF_LI";
+        }
+
+        public void onRecordLoaded(AsyncResult ar) {
+            mEfLi = (byte[]) ar.result;
+            if (DBG) log("EF_LI=" + IccUtils.bytesToHexString(mEfLi));
+        }
+    }
+
     private void handleFileUpdate(int efid) {
         switch(efid) {
             case EF_MBDN:
@@ -1196,6 +1293,24 @@ public class SIMRecords extends IccRecords {
                 if (DBG) log("SIM Refresh called for EF_FDN");
                 mParentApp.queryFdn();
                 break;
+            case EF_MSISDN:
+                mRecordsToLoad++;
+                log("SIM Refresh called for EF_MSISDN");
+                new AdnRecordLoader(mFh).loadFromEF(EF_MSISDN, getExtFromEf(EF_MSISDN), 1,
+                        obtainMessage(EVENT_GET_MSISDN_DONE));
+                break;
+            case EF_CFIS:
+                mRecordsToLoad++;
+                log("SIM Refresh called for EF_CFIS");
+                mFh.loadEFLinearFixed(EF_CFIS,
+                        1, obtainMessage(EVENT_GET_CFIS_DONE));
+                break;
+            case EF_CFF_CPHS:
+                mRecordsToLoad++;
+                log("SIM Refresh called for EF_CFF_CPHS");
+                mFh.loadEFTransparent(EF_CFF_CPHS,
+                        obtainMessage(EVENT_GET_CFF_DONE));
+                break;
             default:
                 // For now, fetch all records if this is not a
                 // voicemail number.
@@ -1229,15 +1344,8 @@ public class SIMRecords extends IccRecords {
                 onIccRefreshInit();
                 break;
             case IccRefreshResponse.REFRESH_RESULT_RESET:
+                // Refresh reset is handled by the UiccCard object.
                 if (DBG) log("handleSimRefresh with SIM_REFRESH_RESET");
-                mCi.setRadioPower(false, null);
-                /* Note: no need to call setRadioPower(true).  Assuming the desired
-                * radio power state is still ON (as tracked by ServiceStateTracker),
-                * ServiceStateTracker will call setRadioPower when it receives the
-                * RADIO_STATE_CHANGED notification for the power off.  And if the
-                * desired power state has changed in the interim, we don't want to
-                * override it with an unconditional power on.
-                */
                 break;
             default:
                 // unknown refresh operation
@@ -1330,21 +1438,41 @@ public class SIMRecords extends IccRecords {
     protected void onAllRecordsLoaded() {
         if (DBG) log("record load complete");
 
+        Resources resource = Resources.getSystem();
+        if (resource.getBoolean(com.android.internal.R.bool.config_use_sim_language_file)) {
+            setSimLanguage(mEfLi, mEfPl);
+        } else {
+            if (DBG) log ("Not using EF LI/EF PL");
+        }
+
+        if (mParentApp.getState() == AppState.APPSTATE_PIN ||
+               mParentApp.getState() == AppState.APPSTATE_PUK) {
+            // reset recordsRequested, since sim is not loaded really
+            mRecordsRequested = false;
+            // lock state, only update language
+            return ;
+        }
+
         // Some fields require more than one SIM record to set
 
         String operator = getOperatorNumeric();
         if (!TextUtils.isEmpty(operator)) {
             log("onAllRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" +
                     operator + "'");
-            SystemProperties.set(PROPERTY_ICC_OPERATOR_NUMERIC, operator);
+            log("update icc_operator_numeric=" + operator);
+            mTelephonyManager.setSimOperatorNumericForPhone(
+                    mParentApp.getPhoneId(), operator);
+            final SubscriptionController subController = SubscriptionController.getInstance();
+            subController.setMccMnc(operator, subController.getDefaultSmsSubId());
         } else {
             log("onAllRecordsLoaded empty 'gsm.sim.operator.numeric' skipping");
         }
 
         if (!TextUtils.isEmpty(mImsi)) {
-            log("onAllRecordsLoaded set mcc imsi=" + mImsi);
-            SystemProperties.set(PROPERTY_ICC_OPERATOR_ISO_COUNTRY,
-                    MccTable.countryCodeForMcc(Integer.parseInt(mImsi.substring(0,3))));
+            log("onAllRecordsLoaded set mcc imsi" + (VDBG ? ("=" + mImsi) : ""));
+            mTelephonyManager.setSimCountryIsoForPhone(
+                    mParentApp.getPhoneId(), MccTable.countryCodeForMcc(
+                    Integer.parseInt(mImsi.substring(0,3))));
         } else {
             log("onAllRecordsLoaded empty imsi skipping setting mcc");
         }
@@ -1360,7 +1488,9 @@ public class SIMRecords extends IccRecords {
 
     private void setSpnFromConfig(String carrier) {
         if (mSpnOverride.containsCarrier(carrier)) {
-            mSpn = mSpnOverride.getSpn(carrier);
+            setServiceProviderName(mSpnOverride.getSpn(carrier));
+            mTelephonyManager.setSimOperatorNameForPhone(
+                    mParentApp.getPhoneId(), getServiceProviderName());
         }
     }
 
@@ -1378,6 +1508,24 @@ public class SIMRecords extends IccRecords {
         fetchSimRecords();
     }
 
+    private void onLocked() {
+        if (DBG) log("only fetch EF_LI and EF_PL in lock state");
+        loadEfLiAndEfPl();
+    }
+
+    private void loadEfLiAndEfPl() {
+        if (mParentApp.getType() == AppType.APPTYPE_USIM) {
+            mRecordsRequested = true;
+            mFh.loadEFTransparent(EF_LI,
+                    obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfUsimLiLoaded()));
+            mRecordsToLoad++;
+
+            mFh.loadEFTransparent(EF_PL,
+                    obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfPlLoaded()));
+            mRecordsToLoad++;
+        }
+    }
+
     protected void fetchSimRecords() {
         mRecordsRequested = true;
 
@@ -1391,7 +1539,7 @@ public class SIMRecords extends IccRecords {
 
         // FIXME should examine EF[MSISDN]'s capability configuration
         // to determine which is the voice/data/fax line
-        new AdnRecordLoader(mFh).loadFromEF(EF_MSISDN, EF_EXT1, 1,
+        new AdnRecordLoader(mFh).loadFromEF(EF_MSISDN, getExtFromEf(EF_MSISDN), 1,
                     obtainMessage(EVENT_GET_MSISDN_DONE));
         mRecordsToLoad++;
 
@@ -1444,6 +1592,11 @@ public class SIMRecords extends IccRecords {
         mFh.loadEFTransparent(EF_GID1, obtainMessage(EVENT_GET_GID1_DONE));
         mRecordsToLoad++;
 
+        mFh.loadEFTransparent(EF_GID2, obtainMessage(EVENT_GET_GID2_DONE));
+        mRecordsToLoad++;
+
+        loadEfLiAndEfPl();
+
         // XXX should seek instead of examining them all
         if (false) { // XXX
             mFh.loadEFLinearFixedAll(EF_SMS, obtainMessage(EVENT_GET_ALL_SMS_DONE));
@@ -1476,7 +1629,12 @@ public class SIMRecords extends IccRecords {
     @Override
     public int getDisplayRule(String plmn) {
         int rule;
-        if (TextUtils.isEmpty(mSpn) || mSpnDisplayCondition == -1) {
+
+        if (mParentApp != null && mParentApp.getUiccCard() != null &&
+            mParentApp.getUiccCard().getOperatorBrandOverride() != null) {
+        // If the operator has been overridden, treat it as the SPN file on the SIM did not exist.
+            rule = SPN_RULE_SHOW_PLMN;
+        } else if (TextUtils.isEmpty(getServiceProviderName()) || mSpnDisplayCondition == -1) {
             // No EF_SPN content was found on the SIM, or not yet loaded.  Just show ONS.
             rule = SPN_RULE_SHOW_PLMN;
         } else if (isOnMatchingPlmn(plmn)) {
@@ -1564,7 +1722,7 @@ public class SIMRecords extends IccRecords {
 
         switch(mSpnState){
             case INIT:
-                mSpn = null;
+                setServiceProviderName(null);
 
                 mFh.loadEFTransparent(EF_SPN,
                         obtainMessage(EVENT_GET_SPN_DONE));
@@ -1576,11 +1734,13 @@ public class SIMRecords extends IccRecords {
                 if (ar != null && ar.exception == null) {
                     data = (byte[]) ar.result;
                     mSpnDisplayCondition = 0xff & data[0];
-                    mSpn = IccUtils.adnStringFieldToString(data, 1, data.length - 1);
+                    setServiceProviderName(IccUtils.adnStringFieldToString(
+                            data, 1, data.length - 1));
 
-                    if (DBG) log("Load EF_SPN: " + mSpn
+                    if (DBG) log("Load EF_SPN: " + getServiceProviderName()
                             + " spnDisplayCondition: " + mSpnDisplayCondition);
-                    SystemProperties.set(PROPERTY_ICC_OPERATOR_ALPHA, mSpn);
+                    mTelephonyManager.setSimOperatorNameForPhone(
+                            mParentApp.getPhoneId(), getServiceProviderName());
 
                     mSpnState = GetSpnFsmState.IDLE;
                 } else {
@@ -1598,10 +1758,11 @@ public class SIMRecords extends IccRecords {
             case READ_SPN_CPHS:
                 if (ar != null && ar.exception == null) {
                     data = (byte[]) ar.result;
-                    mSpn = IccUtils.adnStringFieldToString(data, 0, data.length);
+                    setServiceProviderName(IccUtils.adnStringFieldToString(data, 0, data.length));
 
-                    if (DBG) log("Load EF_SPN_CPHS: " + mSpn);
-                    SystemProperties.set(PROPERTY_ICC_OPERATOR_ALPHA, mSpn);
+                    if (DBG) log("Load EF_SPN_CPHS: " + getServiceProviderName());
+                    mTelephonyManager.setSimOperatorNameForPhone(
+                            mParentApp.getPhoneId(), getServiceProviderName());
 
                     mSpnState = GetSpnFsmState.IDLE;
                 } else {
@@ -1615,10 +1776,11 @@ public class SIMRecords extends IccRecords {
             case READ_SPN_SHORT_CPHS:
                 if (ar != null && ar.exception == null) {
                     data = (byte[]) ar.result;
-                    mSpn = IccUtils.adnStringFieldToString(data, 0, data.length);
+                    setServiceProviderName(IccUtils.adnStringFieldToString(data, 0, data.length));
 
-                    if (DBG) log("Load EF_SPN_SHORT_CPHS: " + mSpn);
-                    SystemProperties.set(PROPERTY_ICC_OPERATOR_ALPHA, mSpn);
+                    if (DBG) log("Load EF_SPN_SHORT_CPHS: " + getServiceProviderName());
+                    mTelephonyManager.setSimOperatorNameForPhone(
+                            mParentApp.getPhoneId(), getServiceProviderName());
                 }else {
                     if (DBG) log("No SPN loaded in either CHPS or 3GPP");
                 }
@@ -1767,6 +1929,7 @@ public class SIMRecords extends IccRecords {
         pw.println(" mPnnHomeName=" + mPnnHomeName);
         pw.println(" mUsimServiceTable=" + mUsimServiceTable);
         pw.println(" mGid1=" + mGid1);
+        pw.println(" mGid2=" + mGid2);
         pw.flush();
     }
 }