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
old mode 100755 (executable)
new mode 100644 (file)
index 66eaf6a..3acbd4d
 
 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.Handler;
 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.BaseCommands;
 import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.MccTable;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneBase;
-import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.SmsConstants;
+import com.android.internal.telephony.SubscriptionController;
 import com.android.internal.telephony.gsm.SimTlv;
-import com.android.internal.telephony.gsm.SmsMessage;
+import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
+import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
 
-
 /**
  * {@hide}
  */
 public class SIMRecords extends IccRecords {
-    protected static final String LOG_TAG = "GSM";
+    protected static final String LOG_TAG = "SIMRecords";
 
     private static final boolean CRASH_RIL = false;
 
-    protected static final boolean DBG = true;
-
     // ***** Instance Variables
 
     VoiceMailConstants mVmConfig;
@@ -62,13 +57,13 @@ public class SIMRecords extends IccRecords {
 
     // ***** Cached SIM State; cleared on channel close
 
-    private boolean callForwardingEnabled;
+    private boolean mCallForwardingEnabled;
 
 
     /**
      * States only used by getSpnFsm FSM
      */
-    private Get_Spn_Fsm_State spnState;
+    private GetSpnFsmState mSpnState;
 
     /** CPHS service information (See CPHS 4.2 B.3.1.1)
      *  It will be set in onSimReady if reading GET_CPHS_INFO successfully
@@ -78,25 +73,39 @@ public class SIMRecords extends IccRecords {
     private byte[] mCphsInfo = null;
     boolean mCspPlmnEnabled = true;
 
-    byte[] efMWIS = null;
-    byte[] efCPHS_MWI =null;
+    byte[] mEfMWIS = null;
+    byte[] mEfCPHS_MWI =null;
     byte[] mEfCff = null;
     byte[] mEfCfis = null;
 
+    byte[] mEfLi = null;
+    byte[] mEfPl = null;
 
-    int spnDisplayCondition;
+    int mSpnDisplayCondition;
     // Numeric network codes listed in TS 51.011 EF[SPDI]
-    ArrayList<String> spdiNetworks = null;
+    ArrayList<String> mSpdiNetworks = null;
 
-    String pnnHomeName = null;
+    String mPnnHomeName = null;
 
     UsimServiceTable mUsimServiceTable;
 
-    // ***** Constants
+    @Override
+    public String toString() {
+        return "SimRecords: " + super.toString()
+                + " mVmConfig" + mVmConfig
+                + " mSpnOverride=" + "mSpnOverride"
+                + " callForwardingEnabled=" + mCallForwardingEnabled
+                + " spnState=" + mSpnState
+                + " mCphsInfo=" + mCphsInfo
+                + " mCspPlmnEnabled=" + mCspPlmnEnabled
+                + " efMWIS=" + mEfMWIS
+                + " efCPHS_MWI=" + mEfCPHS_MWI
+                + " mEfCff=" + mEfCff
+                + " mEfCfis=" + mEfCfis
+                + " getOperatorNumeric=" + getOperatorNumeric();
+    }
 
-    // Bitmasks for SPN display rules.
-    public static final int SPN_RULE_SHOW_SPN  = 0x01;
-    public static final int SPN_RULE_SHOW_PLMN = 0x02;
+    // ***** Constants
 
     // From TS 51.011 EF[SPDI] section
     static final int TAG_SPDI = 0xA3;
@@ -118,9 +127,14 @@ public class SIMRecords extends IccRecords {
     private static final int CPHS_SST_MBN_MASK = 0x30;
     private static final int CPHS_SST_MBN_ENABLED = 0x30;
 
-    // ***** Event Constants
+    // EF_CFIS related constants
+    // Spec reference TS 51.011 section 10.3.46.
+    private static final int CFIS_BCD_NUMBER_LENGTH_OFFSET = 2;
+    private static final int CFIS_TON_NPI_OFFSET = 3;
+    private static final int CFIS_ADN_CAPABILITY_ID_OFFSET = 14;
+    private static final int CFIS_ADN_EXTENSION_ID_OFFSET = 15;
 
-    private static final int EVENT_APP_READY = 1;
+    // ***** Event Constants
     private static final int EVENT_GET_IMSI_DONE = 3;
     private static final int EVENT_GET_ICCID_DONE = 4;
     private static final int EVENT_GET_MBI_DONE = 5;
@@ -143,14 +157,18 @@ public class SIMRecords extends IccRecords {
     private static final int EVENT_GET_CFF_DONE = 24;
     private static final int EVENT_SET_CPHS_MAILBOX_DONE = 25;
     private static final int EVENT_GET_INFO_CPHS_DONE = 26;
-    private static final int EVENT_SET_MSISDN_DONE = 30;
+    // private static final int EVENT_SET_MSISDN_DONE = 30; Defined in IccRecords as 30
     private static final int EVENT_SIM_REFRESH = 31;
     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.
 
     private static final String[] MCCMNC_CODES_HAVING_3DIGITS_MNC = {
+        "302370", "302720", "310260",
         "405025", "405026", "405027", "405028", "405029", "405030", "405031", "405032",
         "405033", "405034", "405035", "405036", "405037", "405038", "405039", "405040",
         "405041", "405042", "405043", "405044", "405045", "405046", "405047", "405750",
@@ -166,7 +184,7 @@ public class SIMRecords extends IccRecords {
         "405886", "405908", "405909", "405910", "405911", "405912", "405913", "405914",
         "405915", "405916", "405917", "405918", "405919", "405920", "405921", "405922",
         "405923", "405924", "405925", "405926", "405927", "405928", "405929", "405930",
-        "405931", "405932"
+        "405931", "405932", "502142", "502143", "502145", "502146", "502147", "502148"
     };
 
     // ***** Constructor
@@ -174,15 +192,15 @@ public class SIMRecords extends IccRecords {
     public SIMRecords(UiccCardApplication app, Context c, CommandsInterface ci) {
         super(app, c, ci);
 
-        adnCache = new AdnRecordCache(mFh);
+        mAdnCache = new AdnRecordCache(mFh);
 
         mVmConfig = new VoiceMailConstants();
         mSpnOverride = new SpnOverride();
 
-        recordsRequested = false;  // No load request is made till SIM ready
+        mRecordsRequested = false;  // No load request is made till SIM ready
 
         // recordsToLoad is set to 0 because no requests are made yet
-        recordsToLoad = 0;
+        mRecordsToLoad = 0;
 
         mCi.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null);
         mCi.registerForIccRefresh(this, EVENT_SIM_REFRESH, null);
@@ -190,48 +208,55 @@ 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);
     }
 
     @Override
     public void dispose() {
-        if (DBG) log("Disposing SIMRecords " + this);
+        if (DBG) log("Disposing SIMRecords this=" + this);
         //Unregister for all events
         mCi.unregisterForIccRefresh(this);
         mCi.unSetOnSmsOnSim(this);
         mParentApp.unregisterForReady(this);
+        mParentApp.unregisterForLocked(this);
         resetRecords();
         super.dispose();
     }
 
+    @Override
     protected void finalize() {
         if(DBG) log("finalized");
     }
 
     protected void resetRecords() {
         mImsi = null;
-        msisdn = null;
-        voiceMailNum = null;
-        countVoiceMessages = 0;
-        mncLength = UNINITIALIZED;
-        iccid = null;
+        mMsisdn = null;
+        mVoiceMailNum = null;
+        mMncLength = UNINITIALIZED;
+        log("setting0 mMncLength" + mMncLength);
+        mIccId = null;
         // -1 means no EF_SPN found; treat accordingly.
-        spnDisplayCondition = -1;
-        efMWIS = null;
-        efCPHS_MWI = null;
-        spdiNetworks = null;
-        pnnHomeName = null;
+        mSpnDisplayCondition = -1;
+        mEfMWIS = null;
+        mEfCPHS_MWI = null;
+        mSpdiNetworks = null;
+        mPnnHomeName = null;
+        mGid1 = null;
+        mGid2 = null;
 
-        adnCache.reset();
+        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
         // true only when fresh set of read requests are made.
-        recordsRequested = false;
+        mRecordsRequested = false;
     }
 
 
@@ -245,8 +270,19 @@ public class SIMRecords extends IccRecords {
         return mImsi;
     }
 
+    @Override
     public String getMsisdnNumber() {
-        return msisdn;
+        return mMsisdn;
+    }
+
+    @Override
+    public String getGid1() {
+        return mGid1;
+    }
+
+    @Override
+    public String getGid2() {
+        return mGid2;
     }
 
     @Override
@@ -254,6 +290,23 @@ public class SIMRecords extends IccRecords {
         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
      *
@@ -269,27 +322,31 @@ public class SIMRecords extends IccRecords {
      *        ((AsyncResult)onComplete.obj).exception == null on success
      *        ((AsyncResult)onComplete.obj).exception != null on fail
      */
+    @Override
     public void setMsisdnNumber(String alphaTag, String number,
             Message onComplete) {
 
-        msisdn = number;
-        msisdnTag = 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: " + msisdnTag + " " + /*msisdn*/ "xxxxxxx");
+        if(DBG) log("Set MSISDN: " + mNewMsisdnTag + " " + /*mNewMsisdn*/ "xxxxxxx");
 
+        AdnRecord adn = new AdnRecord(mNewMsisdnTag, mNewMsisdn);
 
-        AdnRecord adn = new AdnRecord(msisdnTag, msisdn);
-
-        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));
     }
 
+    @Override
     public String getMsisdnAlphaTag() {
-        return msisdnTag;
+        return mMsisdnTag;
     }
 
+    @Override
     public String getVoiceMailNumber() {
-        return voiceMailNum;
+        return mVoiceMailNum;
     }
 
     /**
@@ -316,24 +373,25 @@ public class SIMRecords extends IccRecords {
      *        ((AsyncResult)onComplete.obj).exception == null on success
      *        ((AsyncResult)onComplete.obj).exception != null on fail
      */
+    @Override
     public void setVoiceMailNumber(String alphaTag, String voiceNumber,
             Message onComplete) {
-        if (isVoiceMailFixed) {
+        if (mIsVoiceMailFixed) {
             AsyncResult.forMessage((onComplete)).exception =
                     new IccVmFixedException("Voicemail number is fixed by operator");
             onComplete.sendToTarget();
             return;
         }
 
-        newVoiceMailNum = voiceNumber;
-        newVoiceMailTag = alphaTag;
+        mNewVoiceMailNum = voiceNumber;
+        mNewVoiceMailTag = alphaTag;
 
-        AdnRecord adn = new AdnRecord(newVoiceMailTag, newVoiceMailNum);
+        AdnRecord adn = new AdnRecord(mNewVoiceMailTag, mNewVoiceMailNum);
 
-        if (mailboxIndex != 0 && mailboxIndex != 0xff) {
+        if (mMailboxIndex != 0 && mMailboxIndex != 0xff) {
 
             new AdnRecordLoader(mFh).updateEF(adn, EF_MBDN, EF_EXT6,
-                    mailboxIndex, null,
+                    mMailboxIndex, null,
                     obtainMessage(EVENT_SET_MBDN_DONE, onComplete));
 
         } else if (isCphsMailboxEnabled()) {
@@ -349,9 +407,10 @@ public class SIMRecords extends IccRecords {
         }
     }
 
+    @Override
     public String getVoiceMailAlphaTag()
     {
-        return voiceMailTag;
+        return mVoiceMailTag;
     }
 
     /**
@@ -361,6 +420,7 @@ public class SIMRecords extends IccRecords {
      *                     -1 to indicate that an unknown number of
      *                      messages are waiting
      */
+    @Override
     public void
     setVoiceMessageWaiting(int line, int countWaiting) {
         if (line != 1) {
@@ -368,48 +428,34 @@ 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;
-        }
-
-        countVoiceMessages = countWaiting;
-
-        mRecordsEventsRegistrants.notifyResult(EVENT_MWI);
-
         try {
-            if (efMWIS != null) {
+            if (mEfMWIS != null) {
                 // TS 51.011 10.3.45
 
                 // lsb of byte 0 is 'voicemail' status
-                efMWIS[0] = (byte)((efMWIS[0] & 0xfe)
-                                    | (countVoiceMessages == 0 ? 0 : 1));
+                mEfMWIS[0] = (byte)((mEfMWIS[0] & 0xfe)
+                                    | (countWaiting == 0 ? 0 : 1));
 
                 // byte 1 is the number of voice messages waiting
                 if (countWaiting < 0) {
                     // The spec does not define what this should be
                     // if we don't know the count
-                    efMWIS[1] = 0;
+                    mEfMWIS[1] = 0;
                 } else {
-                    efMWIS[1] = (byte) countWaiting;
+                    mEfMWIS[1] = (byte) countWaiting;
                 }
 
                 mFh.updateEFLinearFixed(
-                    EF_MWIS, 1, efMWIS, null,
-                    obtainMessage (EVENT_UPDATE_DONE, EF_MWIS));
+                    EF_MWIS, 1, mEfMWIS, null,
+                    obtainMessage (EVENT_UPDATE_DONE, EF_MWIS, 0));
             }
 
-            if (efCPHS_MWI != null) {
+            if (mEfCPHS_MWI != null) {
                     // Refer CPHS4_2.WW6 B4.2.3
-                efCPHS_MWI[0] = (byte)((efCPHS_MWI[0] & 0xf0)
-                            | (countVoiceMessages == 0 ? 0x5 : 0xa));
-
+                mEfCPHS_MWI[0] = (byte)((mEfCPHS_MWI[0] & 0xf0)
+                            | (countWaiting == 0 ? 0x5 : 0xa));
                 mFh.updateEFTransparent(
-                    EF_VOICE_MAIL_INDICATOR_CPHS, efCPHS_MWI,
+                    EF_VOICE_MAIL_INDICATOR_CPHS, mEfCPHS_MWI,
                     obtainMessage (EVENT_UPDATE_DONE, EF_VOICE_MAIL_INDICATOR_CPHS));
             }
         } catch (ArrayIndexOutOfBoundsException ex) {
@@ -423,23 +469,54 @@ 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}
      */
     @Override
     public boolean getVoiceCallForwardingFlag() {
-        return callForwardingEnabled;
+        return mCallForwardingEnabled;
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void setVoiceCallForwardingFlag(int line, boolean enable) {
+    public void setVoiceCallForwardingFlag(int line, boolean enable, String dialNumber) {
 
         if (line != 1) return; // only line 1 is supported
 
-        callForwardingEnabled = enable;
+        mCallForwardingEnabled = enable;
 
         mRecordsEventsRegistrants.notifyResult(EVENT_CFI);
 
@@ -455,8 +532,18 @@ public class SIMRecords extends IccRecords {
                 log("setVoiceCallForwardingFlag: enable=" + enable
                         + " mEfCfis=" + IccUtils.bytesToHexString(mEfCfis));
 
-                // TODO: Should really update other fields in EF_CFIS, eg,
-                // dialing number.  We don't read or use it right now.
+                // Update dialNumber if not empty and CFU is enabled.
+                // Spec reference for EF_CFIS contents, TS 51.011 section 10.3.46.
+                if (enable && !TextUtils.isEmpty(dialNumber)) {
+                    log("EF_CFIS: updating cf number, " + dialNumber);
+                    byte[] bcdNumber = PhoneNumberUtils.numberToCalledPartyBCD(dialNumber);
+
+                    System.arraycopy(bcdNumber, 0, mEfCfis, CFIS_TON_NPI_OFFSET, bcdNumber.length);
+
+                    mEfCfis[CFIS_BCD_NUMBER_LENGTH_OFFSET] = (byte) (bcdNumber.length);
+                    mEfCfis[CFIS_ADN_CAPABILITY_ID_OFFSET] = (byte) 0xFF;
+                    mEfCfis[CFIS_ADN_EXTENSION_ID_OFFSET] = (byte) 0xFF;
+                }
 
                 mFh.updateEFLinearFixed(
                         EF_CFIS, 1, mEfCfis, null,
@@ -480,7 +567,7 @@ public class SIMRecords extends IccRecords {
                         obtainMessage (EVENT_UPDATE_DONE, EF_CFF_CPHS));
             }
         } catch (ArrayIndexOutOfBoundsException ex) {
-            logw("Error saving call fowarding flag to SIM. "
+            logw("Error saving call forwarding flag to SIM. "
                             + "Probably malformed SIM record", ex);
 
         }
@@ -491,6 +578,7 @@ public class SIMRecords extends IccRecords {
      * @param fileChanged indicates whether any files changed
      * @param fileList if non-null, a list of EF files that changed
      */
+    @Override
     public void onRefresh(boolean fileChanged, int[] fileList) {
         if (fileChanged) {
             // A future optimization would be to inspect fileList and
@@ -509,17 +597,18 @@ public class SIMRecords extends IccRecords {
             log("getOperatorNumeric: IMSI == null");
             return null;
         }
-        if (mncLength == UNINITIALIZED || mncLength == UNKNOWN) {
+        if (mMncLength == UNINITIALIZED || mMncLength == UNKNOWN) {
             log("getSIMOperatorNumeric: bad mncLength");
             return null;
         }
 
         // Length = length of MCC + length of MNC
         // length of mcc = 3 (TS 23.003 Section 2.2)
-        return mImsi.substring(0, 3 + mncLength);
+        return mImsi.substring(0, 3 + mMncLength);
     }
 
     // ***** Overridden from Handler
+    @Override
     public void handleMessage(Message msg) {
         AsyncResult ar;
         AdnRecord adn;
@@ -539,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;
@@ -559,34 +652,39 @@ 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 (((mncLength == UNKNOWN) || (mncLength == 2)) &&
+                if (((mMncLength == UNKNOWN) || (mMncLength == 2)) &&
                         ((mImsi != null) && (mImsi.length() >= 6))) {
                     String mccmncCode = mImsi.substring(0, 6);
                     for (String mccmnc : MCCMNC_CODES_HAVING_3DIGITS_MNC) {
                         if (mccmnc.equals(mccmncCode)) {
-                            mncLength = 3;
+                            mMncLength = 3;
+                            log("IMSI: setting1 mMncLength=" + mMncLength);
                             break;
                         }
                     }
                 }
 
-                if (mncLength == UNKNOWN) {
+                if (mMncLength == UNKNOWN) {
                     // the SIM has told us all it knows, but it didn't know the mnc length.
                     // guess using the mcc
                     try {
                         int mcc = Integer.parseInt(mImsi.substring(0,3));
-                        mncLength = MccTable.smallestDigitsMccForMnc(mcc);
+                        mMncLength = MccTable.smallestDigitsMccForMnc(mcc);
+                        log("setting2 mMncLength=" + mMncLength);
                     } catch (NumberFormatException e) {
-                        mncLength = UNKNOWN;
-                        loge("Corrupt IMSI!");
+                        mMncLength = UNKNOWN;
+                        loge("Corrupt IMSI! setting3 mMncLength=" + mMncLength);
                     }
                 }
 
-                if (mncLength != UNKNOWN && mncLength != UNINITIALIZED) {
+                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 + mncLength));
+                    MccTable.updateMccMncConfiguration(mContext,
+                            mImsi.substring(0, 3 + mMncLength), false);
                 }
                 mImsiReadyRegistrants.notifyRegistrants();
             break;
@@ -604,22 +702,22 @@ public class SIMRecords extends IccRecords {
                     log("EF_MBI: " + IccUtils.bytesToHexString(data));
 
                     // Voice mail record number stored first
-                    mailboxIndex = (int)data[0] & 0xff;
+                    mMailboxIndex = data[0] & 0xff;
 
                     // check if dailing numbe id valid
-                    if (mailboxIndex != 0 && mailboxIndex != 0xff) {
+                    if (mMailboxIndex != 0 && mMailboxIndex != 0xff) {
                         log("Got valid mailbox number for MBDN");
                         isValidMbdn = true;
                     }
                 }
 
                 // one more record to load
-                recordsToLoad += 1;
+                mRecordsToLoad += 1;
 
                 if (isValidMbdn) {
                     // Note: MBDN was not included in NUM_OF_SIM_RECORDS_LOADED
                     new AdnRecordLoader(mFh).loadFromEF(EF_MBDN, EF_EXT6,
-                            mailboxIndex, obtainMessage(EVENT_GET_MBDN_DONE));
+                            mMailboxIndex, obtainMessage(EVENT_GET_MBDN_DONE));
                 } else {
                     // If this EF not present, try mailbox as in CPHS standard
                     // CPHS (CPHS4_2.WW6) is a european standard.
@@ -636,8 +734,8 @@ public class SIMRecords extends IccRecords {
                 //If they are not reset, incase of invalid data/exception these
                 //variables are retaining their previous values and are
                 //causing invalid voice mailbox info display to user.
-                voiceMailNum = null;
-                voiceMailTag = null;
+                mVoiceMailNum = null;
+                mVoiceMailTag = null;
                 isRecordLoadResponse = true;
 
                 ar = (AsyncResult)msg.obj;
@@ -654,7 +752,7 @@ public class SIMRecords extends IccRecords {
                         //load CPHS on fail...
                         // FIXME right now, only load line1's CPHS voice mail entry
 
-                        recordsToLoad += 1;
+                        mRecordsToLoad += 1;
                         new AdnRecordLoader(mFh).loadFromEF(
                                 EF_MAILBOX_CPHS, EF_EXT1, 1,
                                 obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE));
@@ -671,7 +769,7 @@ public class SIMRecords extends IccRecords {
                     // Bug #645770 fall back to CPHS
                     // FIXME should use SST to decide
                     // FIXME right now, only load line1's CPHS voice mail entry
-                    recordsToLoad += 1;
+                    mRecordsToLoad += 1;
                     new AdnRecordLoader(mFh).loadFromEF(
                             EF_MAILBOX_CPHS, EF_EXT1, 1,
                             obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE));
@@ -679,8 +777,8 @@ public class SIMRecords extends IccRecords {
                     break;
                 }
 
-                voiceMailNum = adn.getNumber();
-                voiceMailTag = adn.getAlphaTag();
+                mVoiceMailNum = adn.getNumber();
+                mVoiceMailTag = adn.getAlphaTag();
             break;
 
             case EVENT_GET_MSISDN_DONE:
@@ -695,16 +793,22 @@ public class SIMRecords extends IccRecords {
 
                 adn = (AdnRecord)ar.result;
 
-                msisdn = adn.getNumber();
-                msisdnTag = adn.getAlphaTag();
+                mMsisdn = adn.getNumber();
+                mMsisdnTag = adn.getAlphaTag();
 
-                log("MSISDN: " + /*msisdn*/ "xxxxxxx");
+                log("MSISDN: " + /*mMsisdn*/ "xxxxxxx");
             break;
 
             case EVENT_SET_MSISDN_DONE:
                 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;
@@ -718,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));
-
-                efMWIS = 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);
-                countVoiceMessages = data[1] & 0xff;
-
-                if (voiceMailWaiting && countVoiceMessages == 0) {
-                    // Unknown count = -1
-                    countVoiceMessages = -1;
-                }
-
-                mRecordsEventsRegistrants.notifyResult(EVENT_MWI);
-            break;
+                mEfMWIS = data;
+                break;
 
             case EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE:
                 isRecordLoadResponse = true;
@@ -749,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;
                 }
 
-                efCPHS_MWI = data;
-
-                // Use this data if the EF[MWIS] exists and
-                // has been loaded
-
-                if (efMWIS == null) {
-                    int indicator = (int)(data[0] & 0xf);
-
-                    // Refer CPHS4_2.WW6 B4.2.3
-                    if (indicator == 0xA) {
-                        // Unknown count = -1
-                        countVoiceMessages = -1;
-                    } else if (indicator == 0x5) {
-                        countVoiceMessages = 0;
-                    }
-
-                    mRecordsEventsRegistrants.notifyResult(EVENT_MWI);
-                }
-            break;
+                mEfCPHS_MWI = data;
+                break;
 
             case EVENT_GET_ICCID_DONE:
                 isRecordLoadResponse = true;
@@ -783,9 +865,9 @@ public class SIMRecords extends IccRecords {
                     break;
                 }
 
-                iccid = IccUtils.bcdToString(data, 0, data.length);
+                mIccId = IccUtils.bcdToString(data, 0, data.length);
 
-                log("iccid: " + iccid);
+                log("iccid: " + mIccId);
 
             break;
 
@@ -813,45 +895,50 @@ public class SIMRecords extends IccRecords {
                         break;
                     }
 
-                    mncLength = (int)data[3] & 0xf;
+                    mMncLength = data[3] & 0xf;
+                    log("setting4 mMncLength=" + mMncLength);
 
-                    if (mncLength == 0xf) {
-                        mncLength = UNKNOWN;
+                    if (mMncLength == 0xf) {
+                        mMncLength = UNKNOWN;
+                        log("setting5 mMncLength=" + mMncLength);
                     }
                 } finally {
-                    if (((mncLength == UNINITIALIZED) || (mncLength == UNKNOWN) ||
-                            (mncLength == 2)) && ((mImsi != null) && (mImsi.length() >= 6))) {
+                    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)) {
-                                mncLength = 3;
+                                mMncLength = 3;
+                                log("setting6 mMncLength=" + mMncLength);
                                 break;
                             }
                         }
                     }
 
-                    if (mncLength == UNKNOWN || mncLength == UNINITIALIZED) {
+                    if (mMncLength == UNKNOWN || mMncLength == UNINITIALIZED) {
                         if (mImsi != null) {
                             try {
                                 int mcc = Integer.parseInt(mImsi.substring(0,3));
 
-                                mncLength = MccTable.smallestDigitsMccForMnc(mcc);
+                                mMncLength = MccTable.smallestDigitsMccForMnc(mcc);
+                                log("setting7 mMncLength=" + mMncLength);
                             } catch (NumberFormatException e) {
-                                mncLength = UNKNOWN;
-                                loge("Corrupt IMSI!");
+                                mMncLength = UNKNOWN;
+                                loge("Corrupt IMSI! setting8 mMncLength=" + mMncLength);
                             }
                         } else {
                             // Indicate we got this info, but it didn't contain the length.
-                            mncLength = UNKNOWN;
-
-                            log("MNC length not present in EF_AD");
+                            mMncLength = UNKNOWN;
+                            log("MNC length not present in EF_AD setting9 mMncLength=" + mMncLength);
                         }
                     }
-                    if (mImsi != null && mncLength != UNKNOWN) {
+                    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 + mncLength));
+                                mImsi.substring(0, 3 + mMncLength), false);
                     }
                 }
             break;
@@ -875,14 +962,14 @@ public class SIMRecords extends IccRecords {
                 log("EF_CFF_CPHS: " + IccUtils.bytesToHexString(data));
                 mEfCff = data;
 
-                if (validEfCfis(mEfCfis)) {
-                    callForwardingEnabled =
+                // if EF_CFIS is valid, prefer it to EF_CFF_CPHS
+                if (!validEfCfis(mEfCfis)) {
+                    mCallForwardingEnabled =
                         ((data[0] & CFF_LINE1_MASK) == CFF_UNCONDITIONAL_ACTIVE);
 
                     mRecordsEventsRegistrants.notifyResult(EVENT_CFI);
                 } else {
-                    log("EVENT_GET_CFF_DONE: invalid mEfCfis="
-                            + IccUtils.bytesToHexString(mEfCfis));
+                    log("EVENT_GET_CFF_DONE: EF_CFIS is valid, ignoring EF_CFF_CPHS");
                 }
                 break;
 
@@ -920,7 +1007,7 @@ public class SIMRecords extends IccRecords {
 
                 for ( ; tlv.isValidObject() ; tlv.nextObject()) {
                     if (tlv.getTag() == TAG_FULL_NETWORK_NAME) {
-                        pnnHomeName
+                        mPnnHomeName
                             = IccUtils.networkNameToString(
                                 tlv.getData(), 0, tlv.getData().length);
                         break;
@@ -935,7 +1022,7 @@ public class SIMRecords extends IccRecords {
                 if (ar.exception != null)
                     break;
 
-                handleSmses((ArrayList) ar.result);
+                handleSmses((ArrayList<byte []>) ar.result);
                 break;
 
             case EVENT_MARK_SMS_READ_DONE:
@@ -1001,13 +1088,14 @@ 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) {
-                    voiceMailNum = newVoiceMailNum;
-                    voiceMailTag = newVoiceMailTag;
+                    mVoiceMailNum = mNewVoiceMailNum;
+                    mVoiceMailTag = mNewVoiceMailTag;
                 }
 
                 if (isCphsMailboxEnabled()) {
-                    adn = new AdnRecord(voiceMailTag, voiceMailNum);
+                    adn = new AdnRecord(mVoiceMailTag, mVoiceMailNum);
                     Message onCphsCompleted = (Message) ar.userObj;
 
                     /* write to cphs mailbox whenever it is available but
@@ -1033,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();
                     }
                 }
@@ -1043,8 +1141,8 @@ public class SIMRecords extends IccRecords {
                 isRecordLoadResponse = false;
                 ar = (AsyncResult)msg.obj;
                 if(ar.exception == null) {
-                    voiceMailNum = newVoiceMailNum;
-                    voiceMailTag = newVoiceMailTag;
+                    mVoiceMailNum = mNewVoiceMailNum;
+                    mVoiceMailTag = mNewVoiceMailTag;
                 } else {
                     if (DBG) log("Set CPHS MailBox with exception: "
                             + ar.exception);
@@ -1080,8 +1178,8 @@ public class SIMRecords extends IccRecords {
                     mEfCfis = data;
 
                     // Refer TS 51.011 Section 10.3.46 for the content description
-                    callForwardingEnabled = ((data[1] & 0x01) != 0);
-                    log("EF_CFIS: callFordwardingEnabled=" + callForwardingEnabled);
+                    mCallForwardingEnabled = ((data[1] & 0x01) != 0);
+                    log("EF_CFIS: callForwardingEnabled=" + mCallForwardingEnabled);
 
                     mRecordsEventsRegistrants.notifyResult(EVENT_CFI);
                 } else {
@@ -1105,6 +1203,38 @@ public class SIMRecords extends IccRecords {
                 handleEfCspData(data);
                 break;
 
+            case EVENT_GET_GID1_DONE:
+                isRecordLoadResponse = true;
+
+                ar = (AsyncResult)msg.obj;
+                data =(byte[])ar.result;
+
+                if (ar.exception != null) {
+                    loge("Exception in get GID1 " + ar.exception);
+                    mGid1 = null;
+                    break;
+                }
+                mGid1 = IccUtils.bytesToHexString(data);
+                log("GID1: " + mGid1);
+
+                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
 
@@ -1119,29 +1249,73 @@ 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:
-                recordsToLoad++;
+                mRecordsToLoad++;
                 new AdnRecordLoader(mFh).loadFromEF(EF_MBDN, EF_EXT6,
-                        mailboxIndex, obtainMessage(EVENT_GET_MBDN_DONE));
+                        mMailboxIndex, obtainMessage(EVENT_GET_MBDN_DONE));
                 break;
             case EF_MAILBOX_CPHS:
-                recordsToLoad++;
+                mRecordsToLoad++;
                 new AdnRecordLoader(mFh).loadFromEF(EF_MAILBOX_CPHS, EF_EXT1,
                         1, obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE));
                 break;
             case EF_CSP_CPHS:
-                recordsToLoad++;
+                mRecordsToLoad++;
                 log("[CSP] SIM Refresh for EF_CSP_CPHS");
                 mFh.loadEFTransparent(EF_CSP_CPHS,
                         obtainMessage(EVENT_GET_CSP_CPHS_DONE));
                 break;
+            case EF_FDN:
+                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.
                 // TODO: Handle other cases, instead of fetching all.
-                adnCache.reset();
+                mAdnCache.reset();
                 fetchSimRecords();
                 break;
         }
@@ -1167,19 +1341,11 @@ public class SIMRecords extends IccRecords {
             case IccRefreshResponse.REFRESH_RESULT_INIT:
                 if (DBG) log("handleSimRefresh with SIM_REFRESH_INIT");
                 // need to reload all files (that we care about)
-                adnCache.reset();
-                fetchSimRecords();
+                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
@@ -1189,11 +1355,10 @@ public class SIMRecords extends IccRecords {
     }
 
     /**
-     * Dispatch 3GPP format message. Overridden for CDMA/LTE phones by
-     * {@link com.android.internal.telephony.cdma.CdmaLteUiccRecords}
-     * to send messages to the secondary 3GPP format SMS dispatcher.
+     * Dispatch 3GPP format message to registrant ({@code GSMPhone} or {@code CDMALTEPhone})
+     * to pass to the 3GPP SMS dispatcher for delivery.
      */
-    protected int dispatchGsmMessage(SmsMessageBase message) {
+    private int dispatchGsmMessage(SmsMessage message) {
         mNewSmsRegistrants.notifyResult(message);
         return 0;
     }
@@ -1211,18 +1376,18 @@ public class SIMRecords extends IccRecords {
             // should still parse correctly.
             byte[] pdu = new byte[n - 1];
             System.arraycopy(ba, 1, pdu, 0, n - 1);
-            SmsMessage message = SmsMessage.createFromPdu(pdu);
+            SmsMessage message = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP);
 
             dispatchGsmMessage(message);
         }
     }
 
 
-    private void handleSmses(ArrayList messages) {
+    private void handleSmses(ArrayList<byte[]> messages) {
         int count = messages.size();
 
         for (int i = 0; i < count; i++) {
-            byte[] ba = (byte[]) messages.get(i);
+            byte[] ba = messages.get(i);
 
             if (ba[0] != 0)
                 Rlog.i("ENF", "status " + i + ": " + ba[0]);
@@ -1237,7 +1402,7 @@ public class SIMRecords extends IccRecords {
                 // should still parse correctly.
                 byte[] pdu = new byte[n - 1];
                 System.arraycopy(ba, 1, pdu, 0, n - 1);
-                SmsMessage message = SmsMessage.createFromPdu(pdu);
+                SmsMessage message = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP);
 
                 dispatchGsmMessage(message);
 
@@ -1246,7 +1411,7 @@ public class SIMRecords extends IccRecords {
 
                 ba[0] = 1;
 
-                if (false) { // XXX writing seems to crash RdoServD
+                if (false) { // FIXME: writing seems to crash RdoServD
                     mFh.updateEFLinearFixed(EF_SMS,
                             i, ba, null, obtainMessage(EVENT_MARK_SMS_READ_DONE, i));
                 }
@@ -1254,41 +1419,68 @@ public class SIMRecords extends IccRecords {
         }
     }
 
+    @Override
     protected void onRecordLoaded() {
         // One record loaded successfully or failed, In either case
         // we need to update the recordsToLoad count
-        recordsToLoad -= 1;
-        if (DBG) log("onRecordLoaded " + recordsToLoad + " requested: " + recordsRequested);
+        mRecordsToLoad -= 1;
+        if (DBG) log("onRecordLoaded " + mRecordsToLoad + " requested: " + mRecordsRequested);
 
-        if (recordsToLoad == 0 && recordsRequested == true) {
+        if (mRecordsToLoad == 0 && mRecordsRequested == true) {
             onAllRecordsLoaded();
-        } else if (recordsToLoad < 0) {
+        } else if (mRecordsToLoad < 0) {
             loge("recordsToLoad <0, programmer error suspected");
-            recordsToLoad = 0;
+            mRecordsToLoad = 0;
         }
     }
 
+    @Override
     protected void onAllRecordsLoaded() {
-        String operator = getOperatorNumeric();
+        if (DBG) log("record load complete");
 
-        // Some fields require more than one SIM record to set
+        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");
+        }
 
-        log("SIMRecords: onAllRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" +
-                operator + "'");
-        SystemProperties.set(PROPERTY_ICC_OPERATOR_NUMERIC, operator);
+        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
 
-        if (mImsi != null) {
-            SystemProperties.set(PROPERTY_ICC_OPERATOR_ISO_COUNTRY,
-                    MccTable.countryCodeForMcc(Integer.parseInt(mImsi.substring(0,3))));
+        String operator = getOperatorNumeric();
+        if (!TextUtils.isEmpty(operator)) {
+            log("onAllRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" +
+                    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");
         }
-        else {
-            loge("onAllRecordsLoaded: imsi is NULL!");
+
+        if (!TextUtils.isEmpty(mImsi)) {
+            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");
         }
 
         setVoiceMailByCountry(operator);
         setSpnFromConfig(operator);
 
-        recordsLoadedRegistrants.notifyRegistrants(
+        mRecordsLoadedRegistrants.notifyRegistrants(
             new AsyncResult(null, null, null));
     }
 
@@ -1296,16 +1488,18 @@ public class SIMRecords extends IccRecords {
 
     private void setSpnFromConfig(String carrier) {
         if (mSpnOverride.containsCarrier(carrier)) {
-            spn = mSpnOverride.getSpn(carrier);
+            setServiceProviderName(mSpnOverride.getSpn(carrier));
+            mTelephonyManager.setSimOperatorNameForPhone(
+                    mParentApp.getPhoneId(), getServiceProviderName());
         }
     }
 
 
     private void setVoiceMailByCountry (String spn) {
         if (mVmConfig.containsCarrier(spn)) {
-            isVoiceMailFixed = true;
-            voiceMailNum = mVmConfig.getVoiceMailNumber(spn);
-            voiceMailTag = mVmConfig.getVoiceMailTag(spn);
+            mIsVoiceMailFixed = true;
+            mVoiceMailNum = mVmConfig.getVoiceMailNumber(spn);
+            mVoiceMailTag = mVmConfig.getVoiceMailTag(spn);
         }
     }
 
@@ -1314,33 +1508,51 @@ 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() {
-        recordsRequested = true;
+        mRecordsRequested = true;
 
-        if (DBG) log("fetchSimRecords " + recordsToLoad);
+        if (DBG) log("fetchSimRecords " + mRecordsToLoad);
 
         mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE));
-        recordsToLoad++;
+        mRecordsToLoad++;
 
         mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE));
-        recordsToLoad++;
+        mRecordsToLoad++;
 
         // 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));
-        recordsToLoad++;
+        mRecordsToLoad++;
 
         // Record number is subscriber profile
         mFh.loadEFLinearFixed(EF_MBI, 1, obtainMessage(EVENT_GET_MBI_DONE));
-        recordsToLoad++;
+        mRecordsToLoad++;
 
         mFh.loadEFTransparent(EF_AD, obtainMessage(EVENT_GET_AD_DONE));
-        recordsToLoad++;
+        mRecordsToLoad++;
 
         // Record number is subscriber profile
         mFh.loadEFLinearFixed(EF_MWIS, 1, obtainMessage(EVENT_GET_MWIS_DONE));
-        recordsToLoad++;
+        mRecordsToLoad++;
 
 
         // Also load CPHS-style voice mail indicator, which stores
@@ -1350,37 +1562,45 @@ public class SIMRecords extends IccRecords {
         mFh.loadEFTransparent(
                 EF_VOICE_MAIL_INDICATOR_CPHS,
                 obtainMessage(EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE));
-        recordsToLoad++;
+        mRecordsToLoad++;
 
         // Same goes for Call Forward Status indicator: fetch both
         // EF[CFIS] and CPHS-EF, with EF[CFIS] preferred.
         mFh.loadEFLinearFixed(EF_CFIS, 1, obtainMessage(EVENT_GET_CFIS_DONE));
-        recordsToLoad++;
+        mRecordsToLoad++;
         mFh.loadEFTransparent(EF_CFF_CPHS, obtainMessage(EVENT_GET_CFF_DONE));
-        recordsToLoad++;
+        mRecordsToLoad++;
 
 
         getSpnFsm(true, null);
 
         mFh.loadEFTransparent(EF_SPDI, obtainMessage(EVENT_GET_SPDI_DONE));
-        recordsToLoad++;
+        mRecordsToLoad++;
 
         mFh.loadEFLinearFixed(EF_PNN, 1, obtainMessage(EVENT_GET_PNN_DONE));
-        recordsToLoad++;
+        mRecordsToLoad++;
 
         mFh.loadEFTransparent(EF_SST, obtainMessage(EVENT_GET_SST_DONE));
-        recordsToLoad++;
+        mRecordsToLoad++;
 
         mFh.loadEFTransparent(EF_INFO_CPHS, obtainMessage(EVENT_GET_INFO_CPHS_DONE));
-        recordsToLoad++;
+        mRecordsToLoad++;
 
         mFh.loadEFTransparent(EF_CSP_CPHS,obtainMessage(EVENT_GET_CSP_CPHS_DONE));
-        recordsToLoad++;
+        mRecordsToLoad++;
+
+        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));
-            recordsToLoad++;
+            mRecordsToLoad++;
         }
 
         if (CRASH_RIL) {
@@ -1395,7 +1615,7 @@ public class SIMRecords extends IccRecords {
             mFh.updateEFLinearFixed(EF_SMS, 1, ba, null,
                             obtainMessage(EVENT_MARK_SMS_READ_DONE, 1));
         }
-        if (DBG) log("fetchSimRecords " + recordsToLoad + " requested: " + recordsRequested);
+        if (DBG) log("fetchSimRecords " + mRecordsToLoad + " requested: " + mRecordsRequested);
     }
 
     /**
@@ -1409,18 +1629,23 @@ public class SIMRecords extends IccRecords {
     @Override
     public int getDisplayRule(String plmn) {
         int rule;
-        if (TextUtils.isEmpty(spn) || spnDisplayCondition == -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)) {
             rule = SPN_RULE_SHOW_SPN;
-            if ((spnDisplayCondition & 0x01) == 0x01) {
+            if ((mSpnDisplayCondition & 0x01) == 0x01) {
                 // ONS required when registered to HPLMN or PLMN in EF_SPDI
                 rule |= SPN_RULE_SHOW_PLMN;
             }
         } else {
             rule = SPN_RULE_SHOW_PLMN;
-            if ((spnDisplayCondition & 0x02) == 0x00) {
+            if ((mSpnDisplayCondition & 0x02) == 0x00) {
                 // SPN required if not registered to HPLMN or PLMN in EF_SPDI
                 rule |= SPN_RULE_SHOW_SPN;
             }
@@ -1438,8 +1663,8 @@ public class SIMRecords extends IccRecords {
             return true;
         }
 
-        if (spdiNetworks != null) {
-            for (String spdiNet : spdiNetworks) {
+        if (mSpdiNetworks != null) {
+            for (String spdiNet : mSpdiNetworks) {
                 if (plmn.equals(spdiNet)) {
                     return true;
                 }
@@ -1451,7 +1676,7 @@ public class SIMRecords extends IccRecords {
     /**
      * States of Get SPN Finite State Machine which only used by getSpnFsm()
      */
-    private enum Get_Spn_Fsm_State {
+    private enum GetSpnFsmState {
         IDLE,               // No initialized
         INIT,               // Start FSM
         READ_SPN_3GPP,      // Load EF_SPN firstly
@@ -1482,84 +1707,88 @@ public class SIMRecords extends IccRecords {
         if (start) {
             // Check previous state to see if there is outstanding
             // SPN read
-            if(spnState == Get_Spn_Fsm_State.READ_SPN_3GPP ||
-               spnState == Get_Spn_Fsm_State.READ_SPN_CPHS ||
-               spnState == Get_Spn_Fsm_State.READ_SPN_SHORT_CPHS ||
-               spnState == Get_Spn_Fsm_State.INIT) {
+            if(mSpnState == GetSpnFsmState.READ_SPN_3GPP ||
+               mSpnState == GetSpnFsmState.READ_SPN_CPHS ||
+               mSpnState == GetSpnFsmState.READ_SPN_SHORT_CPHS ||
+               mSpnState == GetSpnFsmState.INIT) {
                 // Set INIT then return so the INIT code
                 // will run when the outstanding read done.
-                spnState = Get_Spn_Fsm_State.INIT;
+                mSpnState = GetSpnFsmState.INIT;
                 return;
             } else {
-                spnState = Get_Spn_Fsm_State.INIT;
+                mSpnState = GetSpnFsmState.INIT;
             }
         }
 
-        switch(spnState){
+        switch(mSpnState){
             case INIT:
-                spn = null;
+                setServiceProviderName(null);
 
                 mFh.loadEFTransparent(EF_SPN,
                         obtainMessage(EVENT_GET_SPN_DONE));
-                recordsToLoad++;
+                mRecordsToLoad++;
 
-                spnState = Get_Spn_Fsm_State.READ_SPN_3GPP;
+                mSpnState = GetSpnFsmState.READ_SPN_3GPP;
                 break;
             case READ_SPN_3GPP:
                 if (ar != null && ar.exception == null) {
                     data = (byte[]) ar.result;
-                    spnDisplayCondition = 0xff & data[0];
-                    spn = IccUtils.adnStringFieldToString(data, 1, data.length - 1);
+                    mSpnDisplayCondition = 0xff & data[0];
+                    setServiceProviderName(IccUtils.adnStringFieldToString(
+                            data, 1, data.length - 1));
 
-                    if (DBG) log("Load EF_SPN: " + spn
-                            + " spnDisplayCondition: " + spnDisplayCondition);
-                    SystemProperties.set(PROPERTY_ICC_OPERATOR_ALPHA, spn);
+                    if (DBG) log("Load EF_SPN: " + getServiceProviderName()
+                            + " spnDisplayCondition: " + mSpnDisplayCondition);
+                    mTelephonyManager.setSimOperatorNameForPhone(
+                            mParentApp.getPhoneId(), getServiceProviderName());
 
-                    spnState = Get_Spn_Fsm_State.IDLE;
+                    mSpnState = GetSpnFsmState.IDLE;
                 } else {
                     mFh.loadEFTransparent( EF_SPN_CPHS,
                             obtainMessage(EVENT_GET_SPN_DONE));
-                    recordsToLoad++;
+                    mRecordsToLoad++;
 
-                    spnState = Get_Spn_Fsm_State.READ_SPN_CPHS;
+                    mSpnState = GetSpnFsmState.READ_SPN_CPHS;
 
                     // See TS 51.011 10.3.11.  Basically, default to
                     // show PLMN always, and SPN also if roaming.
-                    spnDisplayCondition = -1;
+                    mSpnDisplayCondition = -1;
                 }
                 break;
             case READ_SPN_CPHS:
                 if (ar != null && ar.exception == null) {
                     data = (byte[]) ar.result;
-                    spn = IccUtils.adnStringFieldToString(data, 0, data.length);
+                    setServiceProviderName(IccUtils.adnStringFieldToString(data, 0, data.length));
 
-                    if (DBG) log("Load EF_SPN_CPHS: " + spn);
-                    SystemProperties.set(PROPERTY_ICC_OPERATOR_ALPHA, spn);
+                    if (DBG) log("Load EF_SPN_CPHS: " + getServiceProviderName());
+                    mTelephonyManager.setSimOperatorNameForPhone(
+                            mParentApp.getPhoneId(), getServiceProviderName());
 
-                    spnState = Get_Spn_Fsm_State.IDLE;
+                    mSpnState = GetSpnFsmState.IDLE;
                 } else {
                     mFh.loadEFTransparent(
                             EF_SPN_SHORT_CPHS, obtainMessage(EVENT_GET_SPN_DONE));
-                    recordsToLoad++;
+                    mRecordsToLoad++;
 
-                    spnState = Get_Spn_Fsm_State.READ_SPN_SHORT_CPHS;
+                    mSpnState = GetSpnFsmState.READ_SPN_SHORT_CPHS;
                 }
                 break;
             case READ_SPN_SHORT_CPHS:
                 if (ar != null && ar.exception == null) {
                     data = (byte[]) ar.result;
-                    spn = IccUtils.adnStringFieldToString(data, 0, data.length);
+                    setServiceProviderName(IccUtils.adnStringFieldToString(data, 0, data.length));
 
-                    if (DBG) log("Load EF_SPN_SHORT_CPHS: " + spn);
-                    SystemProperties.set(PROPERTY_ICC_OPERATOR_ALPHA, spn);
+                    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");
                 }
 
-                spnState = Get_Spn_Fsm_State.IDLE;
+                mSpnState = GetSpnFsmState.IDLE;
                 break;
             default:
-                spnState = Get_Spn_Fsm_State.IDLE;
+                mSpnState = GetSpnFsmState.IDLE;
         }
     }
 
@@ -1590,7 +1819,7 @@ public class SIMRecords extends IccRecords {
             return;
         }
 
-        spdiNetworks = new ArrayList<String>(plmnEntries.length / 3);
+        mSpdiNetworks = new ArrayList<String>(plmnEntries.length / 3);
 
         for (int i = 0 ; i + 2 < plmnEntries.length ; i += 3) {
             String plmnCode;
@@ -1599,7 +1828,7 @@ public class SIMRecords extends IccRecords {
             // Valid operator codes are 5 or 6 digits
             if (plmnCode.length() >= 5) {
                 log("EF_SPDI network: " + plmnCode);
-                spdiNetworks.add(plmnCode);
+                mSpdiNetworks.add(plmnCode);
             }
         }
     }
@@ -1612,10 +1841,12 @@ public class SIMRecords extends IccRecords {
         return ((mCphsInfo[1] & CPHS_SST_MBN_MASK) == CPHS_SST_MBN_ENABLED );
     }
 
+    @Override
     protected void log(String s) {
         Rlog.d(LOG_TAG, "[SIMRecords] " + s);
     }
 
+    @Override
     protected void loge(String s) {
         Rlog.e(LOG_TAG, "[SIMRecords] " + s);
     }
@@ -1632,6 +1863,7 @@ public class SIMRecords extends IccRecords {
      * Return true if "Restriction of menu options for manual PLMN selection"
      * bit is set or EF_CSP data is unavailable, return false otherwise.
      */
+    @Override
     public boolean isCspPlmnEnabled() {
         return mCspPlmnEnabled;
     }
@@ -1651,7 +1883,7 @@ public class SIMRecords extends IccRecords {
         // Normally this is programmed as 10th service after the standard
         // services.
         int usedCspGroups = data.length / 2;
-        // This is the "Servive Group Number" of "Value Added Services Group".
+        // This is the "Service Group Number" of "Value Added Services Group".
         byte valueAddedServicesGroup = (byte)0xC0;
 
         mCspPlmnEnabled = true;
@@ -1684,18 +1916,20 @@ public class SIMRecords extends IccRecords {
         super.dump(fd, pw, args);
         pw.println(" mVmConfig=" + mVmConfig);
         pw.println(" mSpnOverride=" + mSpnOverride);
-        pw.println(" callForwardingEnabled=" + callForwardingEnabled);
-        pw.println(" spnState=" + spnState);
+        pw.println(" mCallForwardingEnabled=" + mCallForwardingEnabled);
+        pw.println(" mSpnState=" + mSpnState);
         pw.println(" mCphsInfo=" + mCphsInfo);
         pw.println(" mCspPlmnEnabled=" + mCspPlmnEnabled);
-        pw.println(" efMWIS[]=" + Arrays.toString(efMWIS));
-        pw.println(" efCPHS_MWI[]=" + Arrays.toString(efCPHS_MWI));
+        pw.println(" mEfMWIS[]=" + Arrays.toString(mEfMWIS));
+        pw.println(" mEfCPHS_MWI[]=" + Arrays.toString(mEfCPHS_MWI));
         pw.println(" mEfCff[]=" + Arrays.toString(mEfCff));
         pw.println(" mEfCfis[]=" + Arrays.toString(mEfCfis));
-        pw.println(" spnDisplayCondition=" + spnDisplayCondition);
-        pw.println(" spdiNetworks[]=" + spdiNetworks);
-        pw.println(" pnnHomeName=" + pnnHomeName);
+        pw.println(" mSpnDisplayCondition=" + mSpnDisplayCondition);
+        pw.println(" mSpdiNetworks[]=" + mSpdiNetworks);
+        pw.println(" mPnnHomeName=" + mPnnHomeName);
         pw.println(" mUsimServiceTable=" + mUsimServiceTable);
+        pw.println(" mGid1=" + mGid1);
+        pw.println(" mGid2=" + mGid2);
         pw.flush();
     }
-}
\ No newline at end of file
+}