Merge "Add getCardIdForDefaultEuicc method"
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index cb860d8..ff01405 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -128,9 +128,17 @@
     // considered sensetive information.
     private ArrayList<String> mCardStrings;
 
+    // This is the card ID of the default eUICC. It is set to the first ever seen eUICC
+    private int mDefaultEuiccCardId;
+
+    private static final int INVALID_CARD_ID = TelephonyManager.INVALID_CARD_ID;
+
     // SharedPreference key for saving the known card strings (ICCIDs and EIDs) ordered by card ID
     private static final String CARD_STRINGS = "card_strings";
 
+    // SharedPreferences key for saving the default euicc card ID
+    private static final String DEFAULT_CARD = "default_card";
+
     private static final Object mLock = new Object();
     private static UiccController mInstance;
     private static ArrayList<IccSlotStatus> sLastSlotStatus;
@@ -199,6 +207,7 @@
 
         mLauncher = new UiccStateChangedLauncher(c, this);
         mCardStrings = loadCardStrings();
+        mDefaultEuiccCardId = loadDefaultEuiccCardId();
     }
 
     private int getSlotIdFromPhoneId(int phoneId) {
@@ -570,10 +579,22 @@
 
     /**
      * Converts the card string (the ICCID/EID, formerly named card ID) to the public int cardId.
-     * Returns -1 if the card string does not map to a cardId.
+     * Returns INVALID_CARD_ID if the card string does not map to a cardId.
      */
     public int convertToPublicCardId(String cardString) {
-        return mCardStrings.indexOf(cardString);
+        int id = mCardStrings.indexOf(cardString);
+        if (id == -1) {
+            return INVALID_CARD_ID;
+        } else {
+            return id;
+        }
+    }
+
+    /**
+     * Get the card ID of the default eUICC.
+     */
+    public int getCardIdForDefaultEuicc() {
+        return mDefaultEuiccCardId;
     }
 
     private ArrayList<String> loadCardStrings() {
@@ -593,6 +614,19 @@
         editor.commit();
     }
 
+    private int loadDefaultEuiccCardId() {
+        return PreferenceManager.getDefaultSharedPreferences(mContext)
+                .getInt(DEFAULT_CARD, INVALID_CARD_ID);
+    }
+
+    private void setDefaultEuiccCardId(int cardId) {
+        mDefaultEuiccCardId = cardId;
+        SharedPreferences.Editor editor =
+                PreferenceManager.getDefaultSharedPreferences(mContext).edit();
+        editor.putInt(DEFAULT_CARD, mDefaultEuiccCardId);
+        editor.commit();
+    }
+
     private synchronized void onGetSlotStatusDone(AsyncResult ar) {
         if (!mIsSlotStatusSupported) {
             if (VDBG) log("onGetSlotStatusDone: ignoring since mIsSlotStatusSupported is false");
@@ -655,6 +689,12 @@
             if (mUiccSlots[i].isEuicc()) {
                 String eid = iss.eid;
                 addCardId(eid);
+
+                // If default eUICC card ID is unset, set it to the card ID of the eUICC with the
+                // lowest slot index.
+                if (mDefaultEuiccCardId == INVALID_CARD_ID) {
+                    setDefaultEuiccCardId(convertToPublicCardId(eid));
+                }
             }
         }
 
@@ -801,6 +841,8 @@
         pw.flush();
         pw.println(" mIsCdmaSupported=" + isCdmaSupported(mContext));
         pw.println(" mUiccSlots: size=" + mUiccSlots.length);
+        pw.println(" mCardStrings=" + mCardStrings);
+        pw.println(" mDefaultEuiccCardId=" + mDefaultEuiccCardId);
         for (int i = 0; i < mUiccSlots.length; i++) {
             if (mUiccSlots[i] == null) {
                 pw.println("  mUiccSlots[" + i + "]=null");
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
index 4012e76..3b8b799 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
@@ -259,4 +259,28 @@
         // assert that the card ID was created
         assertEquals(0, mUiccControllerUT.convertToPublicCardId(iss.eid));
     }
+
+    @Test
+    public void testCardIdForDefaultEuicc() {
+        // Give UiccController a real context so it can use shared preferences
+        mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
+
+        // Mock out UiccSlots
+        mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+        doReturn(true).when(mMockSlot).isEuicc();
+
+        // simulate slot status loaded
+        IccSlotStatus iss = new IccSlotStatus();
+        iss.setSlotState(1 /* active */);
+        iss.eid = "ABADACB";
+        ArrayList<IccSlotStatus> status = new ArrayList<IccSlotStatus>();
+        status.add(iss);
+        AsyncResult ar = new AsyncResult(null, status, null);
+        Message msg = Message.obtain(mUiccControllerUT, EVENT_GET_SLOT_STATUS_DONE, ar);
+        mUiccControllerUT.handleMessage(msg);
+
+        // assert that the default cardId is the slot with the lowest slot index, even if inactive
+        assertEquals(mUiccControllerUT.convertToPublicCardId(iss.eid),
+                mUiccControllerUT.getCardIdForDefaultEuicc());
+    }
 }