Merge "integrate carrier id to carrier config"
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 8194c60..15c5780 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -137,9 +137,6 @@
 
     private static final int BIND_TIMEOUT_MILLIS = 30000;
 
-    // Length limit of gid1 for naming config file.
-    private static final int GID1_LENGTH_LIMIT = 20;
-
     // Tags used for saving and restoring XML documents.
     private static final String TAG_DOCUMENT = "carrier_config";
     private static final String TAG_VERSION = "package_version";
@@ -260,7 +257,7 @@
                         mContext.unbindService(conn);
                         break;
                     }
-                    final CarrierIdentifier carrierId = getCarrierIdForPhoneId(phoneId);
+                    final CarrierIdentifier carrierId = getCarrierIdentifierForPhoneId(phoneId);
                     // ResultReceiver callback will execute in this Handler's thread.
                     final ResultReceiver resultReceiver =
                             new ResultReceiver(this) {
@@ -376,7 +373,7 @@
                         mContext.unbindService(conn);
                         break;
                     }
-                    final CarrierIdentifier carrierId = getCarrierIdForPhoneId(phoneId);
+                    final CarrierIdentifier carrierId = getCarrierIdentifierForPhoneId(phoneId);
                     // ResultReceiver callback will execute in this Handler's thread.
                     final ResultReceiver resultReceiver =
                             new ResultReceiver(this) {
@@ -537,6 +534,9 @@
             SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId);
         }
         intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, phoneId);
+        intent.putExtra(TelephonyManager.EXTRA_PRECISE_CARRIER_ID,
+                getPreciseCarrierIdForPhoneId(phoneId));
+        intent.putExtra(TelephonyManager.EXTRA_CARRIER_ID, getCarrierIdForPhoneId(phoneId));
         ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL);
         mHasSentConfigChange[phoneId] = true;
     }
@@ -555,7 +555,7 @@
         }
     }
 
-    private CarrierIdentifier getCarrierIdForPhoneId(int phoneId) {
+    private CarrierIdentifier getCarrierIdentifierForPhoneId(int phoneId) {
         String mcc = "";
         String mnc = "";
         String imsi = "";
@@ -563,6 +563,8 @@
         String gid2 = "";
         String spn = TelephonyManager.from(mContext).getSimOperatorNameForPhone(phoneId);
         String simOperator = TelephonyManager.from(mContext).getSimOperatorNumericForPhone(phoneId);
+        int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+        int preciseCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
         // A valid simOperator should be 5 or 6 digits, depending on the length of the MNC.
         if (simOperator != null && simOperator.length() >= 3) {
             mcc = simOperator.substring(0, 3);
@@ -573,9 +575,10 @@
             imsi = phone.getSubscriberId();
             gid1 = phone.getGroupIdLevel1();
             gid2 = phone.getGroupIdLevel2();
+            carrierId = phone.getCarrierId();
+            preciseCarrierId = phone.getPreciseCarrierId();
         }
-
-        return new CarrierIdentifier(mcc, mnc, spn, imsi, gid1, gid2);
+        return new CarrierIdentifier(mcc, mnc, spn, imsi, gid1, gid2, carrierId, preciseCarrierId);
     }
 
     /** Returns the package name of a priveleged carrier app, or null if there is none. */
@@ -601,27 +604,46 @@
         return phone.getIccSerialNumber();
     }
 
-    private String getGid1ForPhoneId(int phoneId) {
+    /**
+     * Get the sim precise carrier id {@link TelephonyManager#getSimPreciseCarrierId()}
+     */
+    private int getPreciseCarrierIdForPhoneId(int phoneId) {
         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
-            return null;
+            return TelephonyManager.UNKNOWN_CARRIER_ID;
         }
         Phone phone = PhoneFactory.getPhone(phoneId);
         if (phone == null) {
-            return null;
+            return TelephonyManager.UNKNOWN_CARRIER_ID;
         }
-        String gid1 = phone.getGroupIdLevel1();
-        if (gid1 == null) {
-            return null;
+        return phone.getPreciseCarrierId();
+    }
+
+    /**
+     * Get the sim carrier id {@link TelephonyManager#getSimCarrierId() }
+     */
+    private int getCarrierIdForPhoneId(int phoneId) {
+        if (!SubscriptionManager.isValidPhoneId(phoneId)) {
+            return TelephonyManager.UNKNOWN_CARRIER_ID;
         }
-        return gid1.substring(0, Math.min(gid1.length(), GID1_LENGTH_LIMIT));
+        Phone phone = PhoneFactory.getPhone(phoneId);
+        if (phone == null) {
+            return TelephonyManager.UNKNOWN_CARRIER_ID;
+        }
+        return phone.getCarrierId();
     }
 
     /**
      * Writes a bundle to an XML file.
      *
-     * The bundle will be written to a file named after the package name and ICCID, so that it can
-     * be restored later with {@link @restoreConfigFromXml}. The XML output will include the bundle
-     * and the current version of the specified package.
+     * The bundle will be written to a file named after the package name, ICCID and
+     * precise carrier id {@link TelephonyManager#getSimPreciseCarrierId()}. the same carrier
+     * should have a single copy of XML file named after carrier id. However, it's still possible
+     * that platform doesn't recognize the current sim carrier, we will use iccid + carrierid as
+     * the canonical file name. carrierid can also handle the cases SIM OTA resolves to different
+     * carrier while iccid remains the same.
+     *
+     * The file can be restored later with {@link @restoreConfigFromXml}. The XML output will
+     * include the bundle and the current version of the specified package.
      *
      * In case of errors or invalid input, no file will be written.
      *
@@ -637,8 +659,7 @@
         }
 
         final String iccid = getIccIdForPhoneId(phoneId);
-        // extras is the first 20 characters of gid1
-        final String extras = getGid1ForPhoneId(phoneId);
+        final int cid = getPreciseCarrierIdForPhoneId(phoneId);
         if (packageName == null || iccid == null) {
             loge("Cannot save config with null packageName or iccid.");
             return;
@@ -661,8 +682,8 @@
         FileOutputStream outFile = null;
         try {
             outFile = new FileOutputStream(
-                    new File(mContext.getFilesDir(), getFilenameForConfig(packageName,
-                            iccid, extras)));
+                    new File(mContext.getFilesDir(),
+                            getFilenameForConfig(packageName, iccid, cid)));
             FastXmlSerializer out = new FastXmlSerializer();
             out.setOutput(outFile, "utf-8");
             out.startDocument("utf-8", true);
@@ -713,8 +734,7 @@
         }
 
         final String iccid = getIccIdForPhoneId(phoneId);
-        // extras is the first 20 characters of gid1
-        final String extras = getGid1ForPhoneId(phoneId);
+        final int cid = getPreciseCarrierIdForPhoneId(phoneId);
         if (packageName == null || iccid == null) {
             loge("Cannot restore config with null packageName or iccid.");
             return null;
@@ -724,8 +744,8 @@
         FileInputStream inFile = null;
         try {
             inFile = new FileInputStream(
-                    new File(mContext.getFilesDir(), getFilenameForConfig(packageName, iccid,
-                            extras)));
+                    new File(mContext.getFilesDir(),
+                            getFilenameForConfig(packageName, iccid, cid)));
             XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
             parser.setInput(inFile, "utf-8");
 
@@ -789,11 +809,12 @@
 
     /** Builds a canonical file name for a config file. */
     private String getFilenameForConfig(@NonNull String packageName, @NonNull String iccid,
-            String extras) {
-        if (extras != null) {
-            return "carrierconfig-" + packageName + "-" + iccid + "-" + extras + ".xml";
-        }
-        return "carrierconfig-" + packageName + "-" + iccid + ".xml";
+                                        int cid) {
+        // the same carrier should have a single copy of XML file named after carrier id.
+        // However, it's still possible that platform doesn't recognize the current sim carrier,
+        // we will use iccid + carrierid as the canonical file name. carrierid can also handle the
+        // cases SIM OTA resolves to different carrier while iccid remains the same.
+        return "carrierconfig-" + packageName + "-" + iccid + "-" + cid + ".xml";
     }
 
     /** Return the current version code of a package, or null if the name is not found. */
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index b36b87e..dfea90c 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -101,6 +101,7 @@
 import com.android.internal.telephony.CallManager;
 import com.android.internal.telephony.CallStateException;
 import com.android.internal.telephony.CarrierInfoManager;
+import com.android.internal.telephony.CarrierResolver;
 import com.android.internal.telephony.CellNetworkScanResult;
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.DefaultPhoneNotifier;
@@ -2163,6 +2164,20 @@
         }
     }
 
+    @Override
+    public int getCarrierIdFromMccMnc(int slotIndex, String mccmnc) {
+        final Phone phone = PhoneFactory.getPhone(slotIndex);
+        if (phone == null) {
+            return TelephonyManager.UNKNOWN_CARRIER_ID;
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return CarrierResolver.getCarrierIdFromMccMnc(phone.getContext(), mccmnc);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     //
     // Internal helper methods.
     //