add capability to initialize default locale from USIM EF_LI or EF_PL.
nfjb73 [Thu, 11 Apr 2013 18:34:25 +0000 (13:34 -0500)]
if user has set the defalut locale, the locale from USIM will be ignored.

Bug: 17543708
Change-Id: I1f9fa8b73b84f27ef8414bb1fc1c01b4a021c791

src/java/com/android/internal/telephony/MccTable.java
src/java/com/android/internal/telephony/uicc/IccConstants.java
src/java/com/android/internal/telephony/uicc/SIMRecords.java
src/java/com/android/internal/telephony/uicc/UsimFileHandler.java

index 6444be1..9c91200 100644 (file)
@@ -314,6 +314,7 @@ public final class MccTable
         if (locale != null) {
             Configuration config = new Configuration();
             config.setLocale(locale);
+            config.userSetLocale = false;
             Slog.d(LOG_TAG, "setSystemLocale: updateLocale config=" + config);
             try {
                 ActivityManagerNative.getDefault().updateConfiguration(config);
index f367f29..b0493a6 100644 (file)
@@ -44,8 +44,9 @@ public interface IccConstants {
     static final int EF_CFIS = 0x6FCB;
     static final int EF_IMG = 0x4f20;
 
-    // USIM SIM file ids from TS 31.102
+    // USIM SIM file ids from TS 131.102
     public static final int EF_PBR = 0x4F30;
+    public static final int EF_LI = 0x6F05;
 
     // GSM SIM file ids from CPHS (phase 2, version 4.2) CPHS4_2.WW6
     static final int EF_MAILBOX_CPHS = 0x6F17;
index 1f7b0d8..414c183 100644 (file)
@@ -36,6 +36,8 @@ 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;
@@ -80,6 +82,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]
@@ -162,6 +166,7 @@ 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;
 
     // Lookup table for carriers known to produce SIMs which incorrectly indicate MNC length.
 
@@ -206,6 +211,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);
     }
 
@@ -216,6 +222,7 @@ public class SIMRecords extends IccRecords {
         mCi.unregisterForIccRefresh(this);
         mCi.unSetOnSmsOnSim(this);
         mParentApp.unregisterForReady(this);
+        mParentApp.unregisterForLocked(this);
         resetRecords();
         super.dispose();
     }
@@ -584,6 +591,10 @@ public class SIMRecords extends IccRecords {
                 onReady();
                 break;
 
+            case EVENT_APP_LOCKED:
+                onLocked();
+                break;
+
             /* IO events */
             case EVENT_GET_IMSI_DONE:
                 isRecordLoadResponse = true;
@@ -1201,6 +1212,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:
@@ -1341,6 +1374,56 @@ public class SIMRecords extends IccRecords {
         }
     }
 
+    private String findBestLanguage(byte[] languages) {
+        String bestMatch = null;
+        String[] locales = mContext.getAssets().getLocales();
+
+        if ((languages == null) || (locales == null)) return null;
+
+        // Each 2-bytes consists of one language
+        for (int i = 0; (i + 1) < languages.length; i += 2) {
+            try {
+                String lang = new String(languages, i, 2, "ISO-8859-1");
+                if (DBG) log ("languages from sim = " + lang);
+                for (int j = 0; j < locales.length; j++) {
+                    if (locales[j] != null && locales[j].length() >= 2 &&
+                            locales[j].substring(0, 2).equalsIgnoreCase(lang)) {
+                        return lang;
+                    }
+                }
+                if (bestMatch != null) break;
+            } catch(java.io.UnsupportedEncodingException e) {
+                log ("Failed to parse USIM language records" + e);
+            }
+        }
+        // no match found. return null
+        return null;
+    }
+
+    private void setLocaleFromUsim() {
+        String prefLang = null;
+        // check EFli then EFpl
+        prefLang = findBestLanguage(mEfLi);
+
+        if (prefLang == null) {
+            prefLang = findBestLanguage(mEfPl);
+        }
+
+        if (prefLang != null) {
+            // check country code from SIM
+            String imsi = getIMSI();
+            String country = null;
+            if (imsi != null) {
+                country = MccTable.countryCodeForMcc(
+                                    Integer.parseInt(imsi.substring(0,3)));
+            }
+            if (DBG) log("Setting locale to " + prefLang + "_" + country);
+            MccTable.setSystemLocale(mContext, prefLang, country);
+        } else {
+            if (DBG) log ("No suitable USIM selected locale");
+        }
+    }
+
     @Override
     protected void onRecordLoaded() {
         // One record loaded successfully or failed, In either case
@@ -1360,6 +1443,16 @@ public class SIMRecords extends IccRecords {
     protected void onAllRecordsLoaded() {
         if (DBG) log("record load complete");
 
+        setLocaleFromUsim();
+
+        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();
@@ -1411,6 +1504,24 @@ public class SIMRecords extends IccRecords {
         fetchSimRecords();
     }
 
+    private void onLocked() {
+        mRecordsRequested = true;
+        if (DBG) log("only fetch EF_LI and EF_PL in lock state");
+        loadEfLiAndEfPl();
+    }
+
+    private void loadEfLiAndEfPl() {
+        if (mParentApp.getType() == AppType.APPTYPE_USIM) {
+            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;
 
@@ -1477,6 +1588,8 @@ public class SIMRecords extends IccRecords {
         mFh.loadEFTransparent(EF_GID1, obtainMessage(EVENT_GET_GID1_DONE));
         mRecordsToLoad++;
 
+        loadEfLiAndEfPl();
+
         // XXX should seek instead of examining them all
         if (false) { // XXX
             mFh.loadEFLinearFixedAll(EF_SMS, obtainMessage(EVENT_GET_ALL_SMS_DONE));
index 067bddf..913aa7c 100644 (file)
@@ -58,6 +58,7 @@ public final class UsimFileHandler extends IccFileHandler implements IccConstant
         case EF_INFO_CPHS:
         case EF_CSP_CPHS:
         case EF_GID1:
+        case EF_LI:
             return MF_SIM + DF_ADF;
 
         case EF_PBR: