Merge "Set EuiccPrivilegedActionUiDispatcherActivity theme." into qt-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 3ecb2b8..6326008 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -83,6 +83,7 @@
     <protected-broadcast android:name= "com.android.internal.telephony.CARRIER_VVM_PACKAGE_INSTALLED" />
     <protected-broadcast android:name= "com.android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO" />
     <protected-broadcast android:name= "com.android.internal.telephony.ACTION_CARRIER_CERTIFICATE_DOWNLOAD" />
+    <protected-broadcast android:name= "com.android.internal.telephony.OPEN_DEFAULT_SMS_APP" />
     <protected-broadcast android:name= "android.telephony.action.SIM_CARD_STATE_CHANGED" />
     <protected-broadcast android:name= "android.telephony.action.SIM_APPLICATION_STATE_CHANGED" />
     <protected-broadcast android:name= "android.telephony.action.SIM_SLOT_STATUS_CHANGED" />
diff --git a/ecc/input/eccdata.txt b/ecc/input/eccdata.txt
index 403cad7..bf5d92c 100644
--- a/ecc/input/eccdata.txt
+++ b/ecc/input/eccdata.txt
@@ -600,8 +600,11 @@
 countries {
   iso_code: "DE"
   eccs {
-    phone_number: "112"
+    phone_number: "110"
     types: POLICE
+  }
+  eccs {
+    phone_number: "112"
     types: AMBULANCE
     types: FIRE
   }
diff --git a/ecc/output/eccdata b/ecc/output/eccdata
index 679bc36..2b9007a 100644
--- a/ecc/output/eccdata
+++ b/ecc/output/eccdata
Binary files differ
diff --git a/res/layout/emergency_information.xml b/res/layout/emergency_information.xml
index e925479..524387f 100644
--- a/res/layout/emergency_information.xml
+++ b/res/layout/emergency_information.xml
@@ -53,7 +53,7 @@
                     android:maxLines="1"
                     android:ellipsize="end"
                     android:lineHeight="@dimen/emergency_info_name_line_height"
-                    android:fontFamily="google-sans"
+                    android:fontFamily="@*android:string/config_headlineFontFamily"
                     android:textAppearance="@style/HeadlineTextAppearance"/>
                 <TextView
                     android:id="@+id/emergency_info_hint"
@@ -99,7 +99,7 @@
                 android:maxLines="2"
                 android:ellipsize="end"
                 android:lineHeight="@dimen/confirmed_emergency_info_line_height"
-                android:fontFamily="google-sans"
+                android:fontFamily="@*android:string/config_headlineFontFamily"
                 android:textAppearance="@style/PhoneCallHintTextAppearance"
                 android:text="@string/emergency_information_confirm_hint"/>
         </LinearLayout>
diff --git a/res/layout/emergency_shortcut_button.xml b/res/layout/emergency_shortcut_button.xml
index 2828926..3c5eaa2 100644
--- a/res/layout/emergency_shortcut_button.xml
+++ b/res/layout/emergency_shortcut_button.xml
@@ -57,7 +57,7 @@
                     android:maxLines="1"
                     android:ellipsize="end"
                     android:lineHeight="@dimen/phone_number_line_height"
-                    android:fontFamily="google-sans"
+                    android:fontFamily="@*android:string/config_headlineFontFamily"
                     android:textAppearance="@style/PhoneNumberTextAppearance"/>
                 <TextView
                     android:id="@+id/phone_number_description"
@@ -124,7 +124,7 @@
                     android:maxLines="2"
                     android:ellipsize="end"
                     android:lineHeight="@dimen/phone_call_hint_line_height"
-                    android:fontFamily="google-sans"
+                    android:fontFamily="@*android:string/config_headlineFontFamily"
                     android:textAppearance="@style/PhoneCallHintTextAppearance"/>
             </FrameLayout>
         </LinearLayout>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index dbc0af4..39c6d75 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -622,7 +622,7 @@
     <string name="preference_category_ringtone" msgid="5197960752529332721">"रिंगटोन और कंपन"</string>
     <string name="pstn_connection_service_label" msgid="1743245930577325900">"अंतर्निहित सिम कार्ड"</string>
     <string name="enable_video_calling_title" msgid="7237253660669000899">"वीडियो कॉलिंग चालू करें"</string>
-    <string name="enable_video_calling_dialog_msg" msgid="8948186136957417948">"वीडियो कॉलिंग चालू करने के लिए, आपको नेटवर्क सेटिंग में उन्‍नत 4G LTE मोड सक्षम करना होगा."</string>
+    <string name="enable_video_calling_dialog_msg" msgid="8948186136957417948">"वीडियो कॉलिंग चालू करने के लिए, आपको नेटवर्क सेटिंग में बेहतर 4G LTE मोड सक्षम करना होगा."</string>
     <string name="enable_video_calling_dialog_settings" msgid="576528473599603249">"नेटवर्क सेटिंग"</string>
     <string name="enable_video_calling_dialog_close" msgid="7411471282167927991">"बंद करें"</string>
     <string name="sim_label_emergency_calls" msgid="4847699229529306397">"आपातकालीन कॉल"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 020f3da..5400ad4 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -592,12 +592,12 @@
     <string name="phone_in_ecm_call_notification_text" msgid="4611608947314729773">"डेटा कनेक्शन अक्षम केले"</string>
     <string name="phone_in_ecm_notification_complete_time" msgid="7730376844178948351">"<xliff:g id="COMPLETETIME">%s</xliff:g> पर्यंत कोणतेही डेटा कनेक्‍शन नाही"</string>
     <plurals name="alert_dialog_exit_ecm" formatted="false" msgid="7179911675595441201">
-      <item quantity="one">फोन <xliff:g id="COUNT_1">%s</xliff:g> मिनिटासाठी आणीबाणी कॉलबॅक मोडमध्ये राहील. या मोडमध्ये असताना डेटा कनेक्शन वापरणारे कोणतेही अ‍ॅप्लिकेशन वापरले जाऊ शकत नाहीत. तुम्ही आता बाहेर पडू इच्छिता?</item>
       <item quantity="other">फोन <xliff:g id="COUNT_1">%s</xliff:g> मिनिटांसाठी आणीबाणी कॉलबॅक मोडमध्ये राहील. या मोडमध्ये असताना डेटा कनेक्शन वापरणारे कोणतेही अ‍ॅप्लिकेशन वापरले जाऊ शकत नाहीत. तुम्ही आता बाहेर पडू इच्छिता?</item>
+      <item quantity="one">फोन <xliff:g id="COUNT_0">%s</xliff:g> मिनिटासाठी आणीबाणी कॉलबॅक मोडमध्ये राहील. या मोडमध्ये असताना डेटा कनेक्शन वापरणारे कोणतेही अ‍ॅप वापरले जाऊ शकत नाहीत. तुम्ही आता बाहेर पडू इच्छिता?</item>
     </plurals>
     <plurals name="alert_dialog_not_avaialble_in_ecm" formatted="false" msgid="8042973425225093895">
-      <item quantity="one">आणीबाणी कॉलबॅक मोडमध्ये असताना निवडलेली क्रिया उपलब्ध नसते. फोन <xliff:g id="COUNT_1">%s</xliff:g> मिनिटासाठी या मोडमध्ये राहील. तुम्ही आता बाहेर पडू इच्छिता?</item>
       <item quantity="other">आणीबाणी कॉलबॅक मोडमध्ये असताना निवडलेली क्रिया उपलब्ध नसते. फोन <xliff:g id="COUNT_1">%s</xliff:g> मिनिटांसाठी या मोडमध्ये राहील. तुम्ही आता बाहेर पडू इच्छिता?</item>
+      <item quantity="one">आणीबाणी कॉलबॅक मोडमध्ये असताना निवडलेली क्रिया उपलब्ध नसते. फोन <xliff:g id="COUNT_0">%s</xliff:g> मिनिटासाठी या मोडमध्ये राहील. तुम्ही आता बाहेर पडू इच्छिता?</item>
     </plurals>
     <string name="alert_dialog_in_ecm_call" msgid="1886723687211887104">"आणीबाणीच्‍या कॉलमध्‍ये असताना निवडलेली क्रिया उपलब्‍ध नसते."</string>
     <string name="progress_dialog_exiting_ecm" msgid="4835734101617817074">"आणीबाणी कॉलबॅक मोडमधून बाहेर पडत आहे"</string>
@@ -762,8 +762,8 @@
     <string name="supp_service_outgoing_calls_barred" msgid="1962644621292054081">"जाणारे कॉल अवरोधित केले."</string>
     <string name="supp_service_call_forwarding_active" msgid="1253134771682248735">"कॉल फॉरवर्ड होत आहे."</string>
     <string name="supp_service_additional_call_forwarded" msgid="5228624725214727315">"अतिरिक्‍त कॉल फॉरवर्ड केला."</string>
-    <string name="supp_service_additional_ect_connected" msgid="6396964292513707102">"भडक कॉल ट्रांसफर करणे पूर्ण झाले."</string>
-    <string name="supp_service_additional_ect_connecting" msgid="5443373059716058480">"भडक कॉल ट्रांसफर होत आहे."</string>
+    <string name="supp_service_additional_ect_connected" msgid="6396964292513707102">"भडक कॉल ट्रान्सफर करणे पूर्ण झाले."</string>
+    <string name="supp_service_additional_ect_connecting" msgid="5443373059716058480">"भडक कॉल ट्रान्सफर होत आहे."</string>
     <string name="supp_service_call_on_hold" msgid="1478976782361795422">"कॉल होल्डवर आहे."</string>
     <string name="supp_service_call_resumed" msgid="1656475289958070674">"कॉल पुन्‍‍‍‍हा सुरू झाला."</string>
     <string name="supp_service_deflected_call" msgid="138970419873492166">"कॉल वळवला."</string>
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index c9fd205..ffb7292 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -442,6 +442,10 @@
                 }
             }
             mButtonWifiCalling.setSummary(resId);
+            Intent intent = mButtonWifiCalling.getIntent();
+            if (intent != null) {
+                intent.putExtra(Settings.EXTRA_SUB_ID, mPhone.getSubId());
+            }
             prefSet.addPreference(mButtonWifiCalling);
         }
 
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 8299d86..e2e30ec 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -316,12 +316,17 @@
                 case EVENT_BIND_DEFAULT_TIMEOUT:
                 case EVENT_FETCH_DEFAULT_TIMEOUT:
                 {
-                    // If a ResponseReceiver callback is in the queue when this happens, we will
-                    // unbind twice and throw an exception.
-                    mContext.unbindService(mServiceConnection[phoneId]);
-                    removeMessages(EVENT_FETCH_DEFAULT_TIMEOUT);
-                    broadcastConfigChangedIntent(phoneId);
                     loge("bind/fetch time out from " + mPlatformCarrierConfigPackage);
+                    removeMessages(EVENT_FETCH_DEFAULT_TIMEOUT);
+                    // If we attempted to bind to the app, but the service connection is null due to
+                    // the race condition that clear config event happens before bind/fetch complete
+                    // then config was cleared while we were waiting and we should not continue.
+                    if (mServiceConnection[phoneId] != null) {
+                        // If a ResponseReceiver callback is in the queue when this happens, we will
+                        // unbind twice and throw an exception.
+                        mContext.unbindService(mServiceConnection[phoneId]);
+                        broadcastConfigChangedIntent(phoneId);
+                    }
                     notifySubscriptionInfoUpdater(phoneId);
                     break;
                 }
@@ -441,16 +446,20 @@
                 case EVENT_BIND_CARRIER_TIMEOUT:
                 case EVENT_FETCH_CARRIER_TIMEOUT:
                 {
-                    // If a ResponseReceiver callback is in the queue when this happens, we will
-                    // unbind twice and throw an exception.
-                    mContext.unbindService(mServiceConnection[phoneId]);
-                    removeMessages(EVENT_FETCH_CARRIER_TIMEOUT);
-                    broadcastConfigChangedIntent(phoneId);
                     loge("bind/fetch from carrier app timeout");
+                    removeMessages(EVENT_FETCH_CARRIER_TIMEOUT);
+                    // If we attempted to bind to the app, but the service connection is null due to
+                    // the race condition that clear config event happens before bind/fetch complete
+                    // then config was cleared while we were waiting and we should not continue.
+                    if (mServiceConnection[phoneId] != null) {
+                        // If a ResponseReceiver callback is in the queue when this happens, we will
+                        // unbind twice and throw an exception.
+                        mContext.unbindService(mServiceConnection[phoneId]);
+                        broadcastConfigChangedIntent(phoneId);
+                    }
                     notifySubscriptionInfoUpdater(phoneId);
                     break;
                 }
-
                 case EVENT_FETCH_CARRIER_DONE:
                 {
                     // If we attempted to bind to the app, but the service connection is null, then
diff --git a/src/com/android/phone/EmergencyAssistanceHelper.java b/src/com/android/phone/EmergencyAssistanceHelper.java
index b4e4421..1bf212e 100644
--- a/src/com/android/phone/EmergencyAssistanceHelper.java
+++ b/src/com/android/phone/EmergencyAssistanceHelper.java
@@ -29,7 +29,6 @@
 import android.os.Process;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
-import android.util.FeatureFlagUtils;
 import android.util.Log;
 
 import com.android.internal.util.CollectionUtils;
@@ -51,10 +50,6 @@
     public static String getIntentAction(Context context) {
         String action = context.getResources().getString(R.string.config_emergency_app_intent);
         if (!action.isEmpty()) {
-            // TODO: remove feature flag and this temporary intent once Emergency app was replaced.
-            if (!FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SAFETY_HUB)) {
-                return "com.android.emergency.action.EMERGENCY_ASSISTANCE";
-            }
             return action;
         }
 
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index de3fffc..942c1e2 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -569,9 +569,8 @@
         if (DBG) log("showDataDisconnectedRoaming()...");
 
         // "Mobile network settings" screen / dialog
-        Intent intent = new Intent(mContext, com.android.phone.MobileNetworkSettings.class);
+        Intent intent = new Intent(Settings.ACTION_DATA_ROAMING_SETTINGS);
         intent.putExtra(Settings.EXTRA_SUB_ID, subId);
-        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
         PendingIntent contentIntent = PendingIntent.getActivity(mContext, subId, intent, 0);
 
         final CharSequence contentText = mContext.getText(R.string.roaming_reenable_message);
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index a9757d1..7d25661 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -172,6 +172,7 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.NoSuchElementException;
 import java.util.Set;
 
 /**
@@ -248,6 +249,8 @@
     private static final int EVENT_REQUEST_CELL_INFO_UPDATE_DONE = 67;
     private static final int CMD_REQUEST_ENABLE_MODEM = 68;
     private static final int EVENT_ENABLE_MODEM_DONE = 69;
+    private static final int CMD_GET_MODEM_STATUS = 70;
+    private static final int EVENT_GET_MODEM_STATUS_DONE = 71;
 
     // Parameters of select command.
     private static final int SELECT_COMMAND = 0xA4;
@@ -1117,10 +1120,42 @@
                     ar = (AsyncResult) msg.obj;
                     request = (MainThreadRequest) ar.userObj;
                     request.result = (ar.exception == null);
+                    int phoneId = request.phone.getPhoneId();
                     //update the cache as modem status has changed
-                    mPhoneConfigurationManager.addToPhoneStatusCache(
-                            request.phone.getPhoneId(), msg.arg1 == 1);
-                    updateModemStateMetrics();
+                    if ((boolean) request.result) {
+                        mPhoneConfigurationManager.addToPhoneStatusCache(phoneId, msg.arg1 == 1);
+                        updateModemStateMetrics();
+                    } else {
+                        Log.e(LOG_TAG, msg.what + " failure. Not updating modem status."
+                                + ar.exception);
+                    }
+                    notifyRequester(request);
+                    break;
+                case CMD_GET_MODEM_STATUS:
+                    request = (MainThreadRequest) msg.obj;
+                    onCompleted = obtainMessage(EVENT_GET_MODEM_STATUS_DONE, request);
+                    PhoneConfigurationManager.getInstance()
+                            .getPhoneStatusFromModem(request.phone, onCompleted);
+                    break;
+                case EVENT_GET_MODEM_STATUS_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+                    int id = request.phone.getPhoneId();
+                    if (ar.exception == null && ar.result != null) {
+                        request.result = ar.result;
+                        //update the cache as modem status has changed
+                        mPhoneConfigurationManager.addToPhoneStatusCache(id,
+                                (boolean) request.result);
+                    } else {
+                        // Return true if modem status cannot be retrieved. For most cases,
+                        // modem status is on. And for older version modems, GET_MODEM_STATUS
+                        // and disable modem are not supported. Modem is always on.
+                        // TODO: this should be fixed in R to support a third
+                        // status UNKNOWN b/131631629
+                        request.result = true;
+                        Log.e(LOG_TAG, msg.what + " failure. Not updating modem status."
+                                + ar.exception);
+                    }
                     notifyRequester(request);
                     break;
                 default:
@@ -3032,10 +3067,8 @@
         final long identity = Binder.clearCallingIdentity();
         try {
             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
-            boolean isRoaming = TelephonyManager.from(
-                    getPhone(subId).getContext()).isNetworkRoaming(subId);
             ImsManager.getInstance(mApp,
-                    getSlotIndexOrException(subId)).setWfcNonPersistent(isCapable, mode, isRoaming);
+                    getSlotIndexOrException(subId)).setWfcNonPersistent(isCapable, mode);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -4945,7 +4978,7 @@
     }
 
     @Override
-    public String[] getMergedSubscriberIds(String callingPackage) {
+    public String[] getMergedSubscriberIds(int subId, String callingPackage) {
         // This API isn't public, so no need to provide a valid subscription ID - we're not worried
         // about carrier-privileged callers not having access.
         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
@@ -4954,6 +4987,9 @@
             return null;
         }
 
+        // Clear calling identity, when calling TelephonyManager, because callerUid must be
+        // the process, where TelephonyManager was instantiated.
+        // Otherwise AppOps check will fail.
         final long identity  = Binder.clearCallingIdentity();
         try {
             final Context context = mApp;
@@ -4962,12 +4998,10 @@
 
             // Figure out what subscribers are currently active
             final ArraySet<String> activeSubscriberIds = new ArraySet<>();
-            // Clear calling identity, when calling TelephonyManager, because callerUid must be
-            // the process, where TelephonyManager was instantiated.
-            // Otherwise AppOps check will fail.
 
-            final int[] subIds = sub.getActiveSubscriptionIdList();
-            for (int subId : subIds) {
+            // Only consider subs which match the current subId
+            // This logic can be simplified. See b/131189269 for progress.
+            if (isActiveSubscription(subId)) {
                 activeSubscriberIds.add(tele.getSubscriberId(subId));
             }
 
@@ -6300,14 +6334,16 @@
 
     @Override
     public List<UiccCardInfo> getUiccCardsInfo(String callingPackage) {
+        boolean hasReadPermission = false;
         try {
             enforceReadPrivilegedPermission("getUiccCardsInfo");
+            hasReadPermission = true;
         } catch (SecurityException e) {
             // even without READ_PRIVILEGED_PHONE_STATE, we allow the call to continue if the caller
             // has carrier privileges on an active UICC
             if (checkCarrierPrivilegesForPackageAnyPhone(callingPackage)
                         != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
-                throw new SecurityException("Caller does not have carrier privileges on any UICC");
+                throw new SecurityException("Caller does not have permission.");
             }
         }
 
@@ -6315,27 +6351,30 @@
         try {
             UiccController uiccController = UiccController.getInstance();
             ArrayList<UiccCardInfo> cardInfos = uiccController.getAllUiccCardInfos();
-
-            ApplicationInfo ai = mApp.getPackageManager().getApplicationInfo(callingPackage, 0);
-            if ((ai.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
-                // Remove private info if the caller doesn't have access
-                ArrayList<UiccCardInfo> filteredInfos = new ArrayList<>();
-                for (UiccCardInfo cardInfo : cardInfos) {
-                    UiccCard card = uiccController.getUiccCard(cardInfo.getSlotIndex());
-                    UiccProfile profile = card.getUiccProfile();
-                    if (profile.getCarrierPrivilegeStatus(mApp.getPackageManager(), callingPackage)
-                            != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
-                        filteredInfos.add(cardInfo.getUnprivileged());
-                    } else {
-                        filteredInfos.add(cardInfo);
-                    }
-                }
-                return filteredInfos;
+            if (hasReadPermission) {
+                return cardInfos;
             }
-            return cardInfos;
-        } catch (PackageManager.NameNotFoundException e) {
-            // This should not happen since we pass the package info in from TelephonyManager
-            throw new SecurityException("Invalid calling package.");
+
+            // Remove private info if the caller doesn't have access
+            ArrayList<UiccCardInfo> filteredInfos = new ArrayList<>();
+            for (UiccCardInfo cardInfo : cardInfos) {
+                // For an inactive eUICC, the UiccCard will be null even though the UiccCardInfo
+                // is available
+                UiccCard card = uiccController.getUiccCardForSlot(cardInfo.getSlotIndex());
+                if (card == null || card.getUiccProfile() == null) {
+                    // assume no access if the card or profile is unavailable
+                    filteredInfos.add(cardInfo.getUnprivileged());
+                    continue;
+                }
+                UiccProfile profile = card.getUiccProfile();
+                if (profile.getCarrierPrivilegeStatus(mApp.getPackageManager(), callingPackage)
+                        == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+                    filteredInfos.add(cardInfo);
+                } else {
+                    filteredInfos.add(cardInfo.getUnprivileged());
+                }
+            }
+            return filteredInfos;
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -6816,7 +6855,11 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            return PhoneConfigurationManager.getInstance().getPhoneStatus(phone);
+            try {
+                return mPhoneConfigurationManager.getPhoneStatusFromCache(phone.getPhoneId());
+            } catch (NoSuchElementException ex) {
+                return (Boolean) sendRequest(CMD_GET_MODEM_STATUS, null, phone, null);
+            }
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index fd7eeb2..498625d 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -177,6 +177,8 @@
         public int capabilities;
         // By default, we will assume that the slots are not locked.
         public boolean isLocked = false;
+        // Is the emergency number associated with the slot
+        public boolean hasDialedEmergencyNumber = false;
 
         public SlotStatus(int slotId, int capabilities) {
             this.slotId = slotId;
@@ -1356,31 +1358,41 @@
         if (potentialEmergencyPhones.size() > 0) {
             Log.i(this, "getPhoneForEmergencyCall, Phone Id that supports emergency number:"
                     + potentialEmergencyPhones.get(0).getPhoneId());
-            return potentialEmergencyPhones.get(0);
+            return getFirstPhoneForEmergencyCall(potentialEmergencyPhones);
         }
         // c)
         return getFirstPhoneForEmergencyCall();
     }
 
+    @VisibleForTesting
+    public Phone getFirstPhoneForEmergencyCall() {
+        return getFirstPhoneForEmergencyCall(null);
+    }
+
     /**
      * 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) If there is a PUK locked SIM, compare the SIMs that are not PUK locked. If all the SIMs
-     *     are locked, skip to condition 4).
-     *  4) The Phone with more Capabilities.
-     *  5) The First Phone that has a SIM card in it (Starting from Slot 0...N)
-     *  6) The Default Phone (Currently set as Slot 0)
+     *  3) 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)
      */
     @VisibleForTesting
-    public Phone getFirstPhoneForEmergencyCall() {
+    public Phone getFirstPhoneForEmergencyCall(List<Phone> phonesWithEmergencyNumber) {
         // 1)
         int phoneId = mSubscriptionManagerProxy.getDefaultVoicePhoneId();
         if (phoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
             Phone defaultPhone = mPhoneFactoryProxy.getPhone(phoneId);
             if (defaultPhone != null && isAvailableForEmergencyCalls(defaultPhone)) {
-                return defaultPhone;
+                if (phonesWithEmergencyNumber == null
+                        || phonesWithEmergencyNumber.contains(defaultPhone)) {
+                    return defaultPhone;
+                }
             }
         }
 
@@ -1394,25 +1406,38 @@
             }
             // 2)
             if (isAvailableForEmergencyCalls(phone)) {
-                // the slot has the radio on & state is in service.
-                Log.i(this, "getFirstPhoneForEmergencyCall, radio on & in service, Phone Id:" + i);
-                return phone;
+                if (phonesWithEmergencyNumber == null
+                        || phonesWithEmergencyNumber.contains(phone)) {
+                    // the slot has the radio on & state is in service.
+                    Log.i(this,
+                            "getFirstPhoneForEmergencyCall, radio on & in service, Phone Id:" + i);
+                    return phone;
+                }
             }
-            // 4)
+            // 5)
             // Store the RAF Capabilities for sorting later.
             int radioAccessFamily = phone.getRadioAccessFamily();
             SlotStatus status = new SlotStatus(i, radioAccessFamily);
             phoneSlotStatus.add(status);
             Log.i(this, "getFirstPhoneForEmergencyCall, RAF:" +
                     Integer.toHexString(radioAccessFamily) + " saved for Phone Id:" + i);
-            // 3)
+            // 4)
             // Report Slot's PIN/PUK lock status for sorting later.
             int simState = mSubscriptionManagerProxy.getSimStateForSlotIdx(i);
             if (simState == TelephonyManager.SIM_STATE_PIN_REQUIRED ||
                     simState == TelephonyManager.SIM_STATE_PUK_REQUIRED) {
                 status.isLocked = true;
             }
-            // 5)
+            // 3) Store if the Phone has the corresponding emergency number
+            if (phonesWithEmergencyNumber != null) {
+                for (Phone phoneWithEmergencyNumber : phonesWithEmergencyNumber) {
+                    if (phoneWithEmergencyNumber != null
+                            && phoneWithEmergencyNumber.getPhoneId() == i) {
+                        status.hasDialedEmergencyNumber = true;
+                    }
+                }
+            }
+            // 6)
             if (firstPhoneWithSim == null && mTelephonyManagerProxy.hasIccCard(i)) {
                 // The slot has a SIM card inserted, but is not in service, so keep track of this
                 // Phone. Do not return because we want to make sure that none of the other Phones
@@ -1422,19 +1447,28 @@
                         firstPhoneWithSim.getPhoneId());
             }
         }
-        // 6)
+        // 7)
         if (firstPhoneWithSim == null && phoneSlotStatus.isEmpty()) {
-            // No Phones available, get the default.
-            Log.i(this, "getFirstPhoneForEmergencyCall, return default phone");
-            return mPhoneFactoryProxy.getDefaultPhone();
+            if (phonesWithEmergencyNumber == null || phonesWithEmergencyNumber.isEmpty()) {
+                // No Phones available, get the default
+                Log.i(this, "getFirstPhoneForEmergencyCall, return default phone");
+                return  mPhoneFactoryProxy.getDefaultPhone();
+            }
+            return phonesWithEmergencyNumber.get(0);
         } else {
-            // 4)
+            // 5)
             final int defaultPhoneId = mPhoneFactoryProxy.getDefaultPhone().getPhoneId();
             final Phone firstOccupiedSlot = firstPhoneWithSim;
             if (!phoneSlotStatus.isEmpty()) {
                 // Only sort if there are enough elements to do so.
                 if (phoneSlotStatus.size() > 1) {
                     Collections.sort(phoneSlotStatus, (o1, o2) -> {
+                        if (!o1.hasDialedEmergencyNumber && o2.hasDialedEmergencyNumber) {
+                            return -1;
+                        }
+                        if (o1.hasDialedEmergencyNumber && !o2.hasDialedEmergencyNumber) {
+                            return 1;
+                        }
                         // First start by seeing if either of the phone slots are locked. If they
                         // are, then sort by non-locked SIM first. If they are both locked, sort
                         // by capability instead.
@@ -1480,7 +1514,7 @@
                         "with highest capability");
                 return mPhoneFactoryProxy.getPhone(mostCapablePhoneId);
             } else {
-                // 5)
+                // 6)
                 return firstPhoneWithSim;
             }
         }