Merge "Create module-specific Hal versions"
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 677869e..cb1277f 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -213,6 +213,7 @@
     @VisibleForTesting
     public interface SubscriptionManagerProxy {
         int getDefaultVoicePhoneId();
+        int getDefaultDataPhoneId();
         int getSimStateForSlotIdx(int slotId);
         int getPhoneId(int subId);
     }
@@ -224,6 +225,11 @@
         }
 
         @Override
+        public int getDefaultDataPhoneId() {
+            return getPhoneId(SubscriptionManager.getDefaultDataSubscriptionId());
+        }
+
+        @Override
         public int getSimStateForSlotIdx(int slotId) {
             return SubscriptionManager.getSimStateForSlotIndex(slotId);
         }
@@ -2168,39 +2174,57 @@
     /**
      * Retrieves the most sensible Phone to use for an emergency call using the following Priority
      *  list (for multi-SIM devices):
-     *  1) The User's SIM preference for Voice calling
-     *  2) The First Phone that is currently IN_SERVICE or is available for emergency calling
-     *  3) Prioritize phones that have the dialed emergency number as part of their emergency
+     *  1) The Phone that is in emergency SMS mode
+     *  2) The phone based on User's SIM preference of Voice calling or Data in order
+     *  3) The First Phone that is currently IN_SERVICE or is available for emergency calling
+     *  4) Prioritize phones that have the dialed emergency number as part of their emergency
      *     number list
-     *  4) If there is a PUK locked SIM, compare the SIMs that are not PUK locked. If all the SIMs
-     *     are locked, skip to condition 5).
-     *  5) The Phone with more Capabilities.
-     *  6) The First Phone that has a SIM card in it (Starting from Slot 0...N)
-     *  7) The Default Phone (Currently set as Slot 0)
+     *  5) If there is a PUK locked SIM, compare the SIMs that are not PUK locked. If all the SIMs
+     *     are locked, skip to condition 6).
+     *  6) The Phone with more Capabilities.
+     *  7) The First Phone that has a SIM card in it (Starting from Slot 0...N)
+     *  8) The Default Phone (Currently set as Slot 0)
      */
     @VisibleForTesting
+    @NonNull
     public Phone getFirstPhoneForEmergencyCall(List<Phone> phonesWithEmergencyNumber) {
-        // 1)
+        int phoneCount = mTelephonyManagerProxy.getPhoneCount();
+        for (int i = 0; i < phoneCount; i++) {
+            Phone phone = mPhoneFactoryProxy.getPhone(i);
+            // 1)
+            if (phone != null && phone.isInEmergencySmsMode()) {
+                if (isAvailableForEmergencyCalls(phone)) {
+                    if (phonesWithEmergencyNumber == null
+                            || phonesWithEmergencyNumber.contains(phone)) {
+                        return phone;
+                    }
+                }
+            }
+        }
+
+        // 2)
         int phoneId = mSubscriptionManagerProxy.getDefaultVoicePhoneId();
+        if (phoneId == SubscriptionManager.INVALID_PHONE_INDEX) {
+            phoneId = mSubscriptionManagerProxy.getDefaultDataPhoneId();
+        }
         if (phoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
-            Phone defaultPhone = mPhoneFactoryProxy.getPhone(phoneId);
-            if (defaultPhone != null && isAvailableForEmergencyCalls(defaultPhone)) {
+            Phone selectedPhone = mPhoneFactoryProxy.getPhone(phoneId);
+            if (selectedPhone != null && isAvailableForEmergencyCalls(selectedPhone)) {
                 if (phonesWithEmergencyNumber == null
-                        || phonesWithEmergencyNumber.contains(defaultPhone)) {
-                    return defaultPhone;
+                        || phonesWithEmergencyNumber.contains(selectedPhone)) {
+                    return selectedPhone;
                 }
             }
         }
 
         Phone firstPhoneWithSim = null;
-        int phoneCount = mTelephonyManagerProxy.getPhoneCount();
         List<SlotStatus> phoneSlotStatus = new ArrayList<>(phoneCount);
         for (int i = 0; i < phoneCount; i++) {
             Phone phone = mPhoneFactoryProxy.getPhone(i);
             if (phone == null) {
                 continue;
             }
-            // 2)
+            // 3)
             if (isAvailableForEmergencyCalls(phone)) {
                 if (phonesWithEmergencyNumber == null
                         || phonesWithEmergencyNumber.contains(phone)) {
@@ -2210,7 +2234,7 @@
                     return phone;
                 }
             }
-            // 5)
+            // 6)
             // Store the RAF Capabilities for sorting later.
             int radioAccessFamily = phone.getRadioAccessFamily();
             SlotStatus status = new SlotStatus(i, radioAccessFamily, phone.getSubId());
@@ -2218,7 +2242,7 @@
             Log.i(this, "getFirstPhoneForEmergencyCall, RAF:" +
                 Integer.toHexString(radioAccessFamily) + " saved for Phone Id:" + i + " subId:"
                 + phone.getSubId());
-            // 4)
+            // 5)
             // Report Slot's PIN/PUK lock status for sorting later.
             int simState = mSubscriptionManagerProxy.getSimStateForSlotIdx(i);
             // Record SimState.
@@ -2228,7 +2252,7 @@
                 status.isLocked = true;
             }
 
-            // 3) Store if the Phone has the corresponding emergency number
+            // 4) Store if the Phone has the corresponding emergency number
             if (phonesWithEmergencyNumber != null) {
                 for (Phone phoneWithEmergencyNumber : phonesWithEmergencyNumber) {
                     if (phoneWithEmergencyNumber != null
@@ -2237,7 +2261,7 @@
                     }
                 }
             }
-            // 6)
+            // 7)
             if (firstPhoneWithSim == null &&
                 (phone.getSubId() != SubscriptionManager.INVALID_SIM_SLOT_INDEX)) {
                 // The slot has a SIM card inserted (and an active subscription), but is not in
@@ -2249,16 +2273,21 @@
                     firstPhoneWithSim.getPhoneId());
             }
         }
-        // 7)
+        // 8)
         if (firstPhoneWithSim == null && phoneSlotStatus.isEmpty()) {
-            if (phonesWithEmergencyNumber == null || phonesWithEmergencyNumber.isEmpty()) {
-                // No Phones available, get the default
-                Log.i(this, "getFirstPhoneForEmergencyCall, return default phone");
-                return  mPhoneFactoryProxy.getDefaultPhone();
+            if (phonesWithEmergencyNumber != null) {
+                for (Phone phoneWithEmergencyNumber : phonesWithEmergencyNumber) {
+                    if (phoneWithEmergencyNumber != null) {
+                        return phoneWithEmergencyNumber;
+                    }
+                }
             }
-            return phonesWithEmergencyNumber.get(0);
+
+            // No Phones available, get the default
+            Log.i(this, "getFirstPhoneForEmergencyCall, return default phone");
+            return  mPhoneFactoryProxy.getDefaultPhone();
         } else {
-            // 5)
+            // 6)
             final int defaultPhoneId = mPhoneFactoryProxy.getDefaultPhone().getPhoneId();
             final Phone firstOccupiedSlot = firstPhoneWithSim;
             if (!phoneSlotStatus.isEmpty()) {
@@ -2321,7 +2350,7 @@
                         "with highest capability");
                 return mPhoneFactoryProxy.getPhone(mostCapablePhoneId);
             } else {
-                // 6)
+                // 7)
                 return firstPhoneWithSim;
             }
         }
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index f2209db..553dbc9 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -192,6 +192,54 @@
     /**
      * Prerequisites:
      * - MSIM Device, two slots with SIMs inserted
+     * - Slot 0 is IN_SERVICE, Slot 1 is OUT_OF_SERVICE (emergency calls only)
+     * - Slot 1 is in Emergency SMS Mode
+     *
+     * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone
+     */
+    @Test
+    @SmallTest
+    public void testEmergencySmsModeSimEmergencyOnly() {
+        Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_IN_SERVICE,
+                false /*isEmergencyOnly*/);
+        Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
+                true /*isEmergencyOnly*/);
+        setDefaultPhone(slot0Phone);
+        setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
+        setEmergencySmsMode(slot1Phone, true);
+
+        Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
+
+        assertEquals(slot1Phone, resultPhone);
+    }
+
+    /**
+     * Prerequisites:
+     * - MSIM Device, two slots with SIMs inserted
+     * - Slot 0 is IN_SERVICE, Slot 1 is OUT_OF_SERVICE
+     * - Slot 1 is in Emergency SMS Mode
+     *
+     * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone
+     */
+    @Test
+    @SmallTest
+    public void testEmergencySmsModeSimOutOfService() {
+        Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_IN_SERVICE,
+                false /*isEmergencyOnly*/);
+        Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
+                false /*isEmergencyOnly*/);
+        setDefaultPhone(slot0Phone);
+        setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
+        setEmergencySmsMode(slot1Phone, true);
+
+        Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
+
+        assertEquals(slot0Phone, resultPhone);
+    }
+
+    /**
+     * Prerequisites:
+     * - MSIM Device, two slots with SIMs inserted
      * - Users default Voice SIM choice is IN_SERVICE
      *
      * Result: getFirstPhoneForEmergencyCall returns the default Voice SIM choice.
@@ -214,6 +262,52 @@
     /**
      * Prerequisites:
      * - MSIM Device, two slots with SIMs inserted
+     * - Users default data SIM choice is OUT_OF_SERVICE (emergency calls only)
+     *
+     * Result: getFirstPhoneForEmergencyCall returns the default data SIM choice.
+     */
+    @Test
+    @SmallTest
+    public void testDefaultDataSimEmergencyOnly() {
+        Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_IN_SERVICE,
+                false /*isEmergencyOnly*/);
+        Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
+                true /*isEmergencyOnly*/);
+        setDefaultPhone(slot0Phone);
+        setupDeviceConfig(slot0Phone, slot1Phone, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+        setDefaultDataPhoneId(SLOT_1_PHONE_ID);
+
+        Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
+
+        assertEquals(slot1Phone, resultPhone);
+    }
+
+    /**
+     * Prerequisites:
+     * - MSIM Device, two slots with SIMs inserted
+     * - Users default data SIM choice is OUT_OF_SERVICE
+     *
+     * Result: getFirstPhoneForEmergencyCall does not return the default data SIM choice.
+     */
+    @Test
+    @SmallTest
+    public void testDefaultDataSimOutOfService() {
+        Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_IN_SERVICE,
+                false /*isEmergencyOnly*/);
+        Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
+                false /*isEmergencyOnly*/);
+        setDefaultPhone(slot0Phone);
+        setupDeviceConfig(slot0Phone, slot1Phone, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+        setDefaultDataPhoneId(SLOT_1_PHONE_ID);
+
+        Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
+
+        assertEquals(slot0Phone, resultPhone);
+    }
+
+    /**
+     * Prerequisites:
+     * - MSIM Device, two slots with SIMs inserted
      * - Slot 0 is OUT_OF_SERVICE, Slot 1 is OUT_OF_SERVICE (emergency calls only)
      *
      * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone
@@ -1615,10 +1709,18 @@
         when(mPhoneFactoryProxy.getPhone(eq(SLOT_1_PHONE_ID))).thenReturn(slot1Phone);
     }
 
+    private void setDefaultDataPhoneId(int defaultDataPhoneId) {
+        when(mSubscriptionManagerProxy.getDefaultDataPhoneId()).thenReturn(defaultDataPhoneId);
+    }
+
     private void setPhoneRadioAccessFamily(Phone phone, int radioAccessFamily) {
         when(phone.getRadioAccessFamily()).thenReturn(radioAccessFamily);
     }
 
+    private void setEmergencySmsMode(Phone phone, boolean isInEmergencySmsMode) {
+        when(phone.isInEmergencySmsMode()).thenReturn(isInEmergencySmsMode);
+    }
+
     private void setPhoneSlotState(int slotId, int slotState) {
         when(mSubscriptionManagerProxy.getSimStateForSlotIdx(slotId)).thenReturn(slotState);
     }