Merge "Delay dialing normal routing emergency number in airplane mode" into udc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ecc4e0f..d36dfec 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -135,6 +135,7 @@
     <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
     <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
     <uses-permission android:name="android.permission.BIND_TELEPHONY_DATA_SERVICE" />
+    <uses-permission android:name="android.permission.BIND_SATELLITE_GATEWAY_SERVICE" />
     <uses-permission android:name="android.permission.BIND_SATELLITE_SERVICE" />
     <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
     <uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" />
diff --git a/res/layout/radio_info.xml b/res/layout/radio_info.xml
index 2efa1d4..ffe63de 100644
--- a/res/layout/radio_info.xml
+++ b/res/layout/radio_info.xml
@@ -19,7 +19,9 @@
 -->
 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:layoutDirection="locale"
+    android:textDirection="locale">
 
     <LinearLayout style="@style/info_layout"
         android:descendantFocusability="beforeDescendants"
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index c171c88..f7effe7 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -892,9 +892,9 @@
     <string name="radio_info_voice_network_type_label" msgid="2395347336419593265">"Tipus de xarxa de veu:"</string>
     <string name="radio_info_data_network_type_label" msgid="8886597029237501929">"Tipus de xarxa de dades:"</string>
     <string name="radio_info_override_network_type_label" msgid="4176280017221092005">"Substitució de tipus de xarxa:"</string>
-    <string name="radio_info_voice_raw_registration_state_label" msgid="2822988327145825128">"Estat de registre de les dades sense processar de Voice:"</string>
-    <string name="radio_info_data_raw_registration_state_label" msgid="2895895513822604539">"Estat de registre de les dades sense processar:"</string>
-    <string name="radio_info_wlan_data_raw_registration_state_label" msgid="6396894835757296612">"Estat de registre de les dades sense processar de la WLAN:"</string>
+    <string name="radio_info_voice_raw_registration_state_label" msgid="2822988327145825128">"Estat de registre de les dades sense tractar de Voice:"</string>
+    <string name="radio_info_data_raw_registration_state_label" msgid="2895895513822604539">"Estat de registre de les dades sense tractar:"</string>
+    <string name="radio_info_wlan_data_raw_registration_state_label" msgid="6396894835757296612">"Estat de registre de les dades sense tractar de la WLAN:"</string>
     <string name="phone_index_label" msgid="6222406512768964268">"Selecciona la guia telefònica"</string>
     <string name="radio_info_set_perferred_label" msgid="7408131389363136210">"Defineix el tipus de xarxa preferit:"</string>
     <string name="radio_info_ping_hostname_v4" msgid="6951237885381284790">"Fer ping a IPv4 de nom d\'amfitrió (www.google.com):"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index e69ca7d..7f31a9c 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -186,9 +186,9 @@
     <string name="manual_mode_disallowed_summary" msgid="3970048592179890197">"Tidak tersedia saat terhubung ke %1$s"</string>
     <string name="network_select_title" msgid="4117305053881611988">"Jaringan"</string>
     <string name="register_automatically" msgid="3907580547590554834">"Pendaftaran otomatis..."</string>
-    <string name="preferred_network_mode_title" msgid="5253395265169539830">"Jenis jaringan yang dipilih"</string>
+    <string name="preferred_network_mode_title" msgid="5253395265169539830">"Jenis jaringan preferensi"</string>
     <string name="preferred_network_mode_summary" msgid="3787989000044330064">"Ubah mode pengoperasian jaringan"</string>
-    <string name="preferred_network_mode_dialogtitle" msgid="2781447433514459696">"Jenis jaringan yang dipilih"</string>
+    <string name="preferred_network_mode_dialogtitle" msgid="2781447433514459696">"Jenis jaringan preferensi"</string>
     <string name="forbidden_network" msgid="5081729819561333023">"(terlarang)"</string>
     <string name="choose_network_title" msgid="5335832663422653082">"Pilih jaringan"</string>
     <string name="network_disconnected" msgid="8844141106841160825">"Terputus"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index c86c7ef..f74bbf4 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -86,8 +86,8 @@
     <string name="voicemail_notifications_preference_title" msgid="7829238858063382977">"Thông báo"</string>
     <string name="cell_broadcast_settings" msgid="8135324242541809924">"Phát sóng trong tình huống khẩn cấp"</string>
     <string name="call_settings" msgid="3677282690157603818">"Cài đặt cuộc gọi"</string>
-    <string name="additional_gsm_call_settings" msgid="1561980168685658846">"Tùy chọn cài đặt bổ sung"</string>
-    <string name="additional_gsm_call_settings_with_label" msgid="7973920539979524908">"Tùy chọn cài đặt bổ sung (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
+    <string name="additional_gsm_call_settings" msgid="1561980168685658846">"Chế độ cài đặt bổ sung"</string>
+    <string name="additional_gsm_call_settings_with_label" msgid="7973920539979524908">"Chế độ cài đặt bổ sung (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
     <string name="sum_gsm_call_settings" msgid="7964692601608878138">"Cài đặt cuộc gọi chỉ GSM bổ sung"</string>
     <string name="additional_cdma_call_settings" msgid="2178016561980611304">"Cài đặt cuộc gọi CDMA bổ sung"</string>
     <string name="sum_cdma_call_settings" msgid="3185825305136993636">"Cài đặt cuộc gọi chỉ CDMA bổ sung"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 0305a04..2ddbf1d 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -534,7 +534,7 @@
     <string name="notification_voicemail_no_vm_number" msgid="3423686009815186750">"沒有可用的留言信箱號碼"</string>
     <string name="notification_network_selection_title" msgid="255595526707809121">"沒有服務"</string>
     <string name="notification_network_selection_text" msgid="553288408722427659">"您所選取的網絡 (<xliff:g id="OPERATOR_NAME">%s</xliff:g>) 無法使用"</string>
-    <string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"開啟流動網絡、關閉飛行模式或關閉省電模式,以撥打電話。"</string>
+    <string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"開啟流動網絡、關閉飛行模式或關閉慳電模式,以撥打電話。"</string>
     <string name="incall_error_power_off" product="default" msgid="8131672264311208673">"關閉飛行模式以撥打電話。"</string>
     <string name="incall_error_power_off_wfc" msgid="9125661184694727052">"關閉飛行模式或連接無線網絡,以撥打電話。"</string>
     <string name="incall_error_power_off_thermal" product="default" msgid="8695809601655300168"><b>"電話過熱"</b>\n\n"無法完成此通話。請在電話冷卻後再試一次。\n\n您仍可進行緊急電話。"</string>
@@ -816,7 +816,7 @@
     <string name="callFailed_otasp_provisioning_in_process" msgid="3345666183602879326">"目前正在佈建裝置,無法撥打電話。"</string>
     <string name="callFailed_already_dialing" msgid="7250591188960691086">"系統正在撥打另一通電話,因此無法撥打電話。"</string>
     <string name="callFailed_already_ringing" msgid="2376603543544289303">"由於目前有尚未接聽的來電,因此無法撥打電話。請先接聽或拒絕來電,然後再撥打電話。"</string>
-    <string name="callFailed_calling_disabled" msgid="5010992739401206283">"通話功能已由 ro.telephony.disable-call 系統屬性停用,因此無法撥打電話。"</string>
+    <string name="callFailed_calling_disabled" msgid="5010992739401206283">"致電功能已由 ro.telephony.disable-call 系統屬性停用,因此無法打電話。"</string>
     <string name="callFailed_too_many_calls" msgid="2761754044990799580">"目前已有兩個通話正在進行,因此無法撥打電話。請先結束其中一個通話,或將兩個通話合併為一個會議,才撥打電話。"</string>
     <string name="supp_service_over_ut_precautions" msgid="2145018231396701311">"如要使用<xliff:g id="SUPP_SERVICE">%s</xliff:g>,請確保流動數據已開啟。您可以在流動網絡設定中變更此設定。"</string>
     <string name="supp_service_over_ut_precautions_roaming" msgid="670342104569972327">"如要使用<xliff:g id="SUPP_SERVICE">%s</xliff:g>,請確保流動數據和數據漫遊已開啟。您可以在流動網絡設定中變更此設定。"</string>
diff --git a/src/com/android/phone/CallNotifier.java b/src/com/android/phone/CallNotifier.java
index 14db930..73b61b6 100644
--- a/src/com/android/phone/CallNotifier.java
+++ b/src/com/android/phone/CallNotifier.java
@@ -40,8 +40,6 @@
 import com.android.internal.telephony.CallManager;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.PhoneFactory;
-import com.android.internal.telephony.SubscriptionController;
 import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaDisplayInfoRec;
 import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaSignalInfoRec;
 import com.android.internal.telephony.cdma.SignalToneUtil;
@@ -489,16 +487,9 @@
     }
 
     public void updatePhoneStateListeners(boolean isRefresh, int updateType, int subIdToUpdate) {
-        List<SubscriptionInfo> subInfos;
-        if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-            subInfos = SubscriptionManagerService.getInstance()
-                    .getActiveSubscriptionInfoList(mApplication.getOpPackageName(),
-                            mApplication.getAttributionTag());
-        } else {
-            subInfos = SubscriptionController.getInstance()
-                    .getActiveSubscriptionInfoList(mApplication.getOpPackageName(),
-                            mApplication.getAttributionTag());
-        }
+        List<SubscriptionInfo> subInfos = SubscriptionManagerService.getInstance()
+                .getActiveSubscriptionInfoList(mApplication.getOpPackageName(),
+                        mApplication.getAttributionTag());
 
         // Sort sub id list based on slot id, so that CFI/MWI notifications will be updated for
         // slot 0 first then slot 1. This is needed to ensure that when CFI or MWI is enabled for
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 9d11dfc..fa85f27 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -64,7 +64,6 @@
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConfigurationManager;
 import com.android.internal.telephony.PhoneFactory;
-import com.android.internal.telephony.SubscriptionInfoUpdater;
 import com.android.internal.telephony.TelephonyPermissions;
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 import com.android.internal.telephony.util.ArrayUtils;
@@ -127,8 +126,6 @@
     // CarrierService change monitoring
     @NonNull private CarrierServiceChangeCallback[] mCarrierServiceChangeCallbacks;
 
-    // SubscriptionInfoUpdater
-    @NonNull private final SubscriptionInfoUpdater mSubscriptionInfoUpdater;
     // Broadcast receiver for system events
     @NonNull
     private final BroadcastReceiver mSystemBroadcastReceiver = new ConfigLoaderBroadcastReceiver();
@@ -138,7 +135,7 @@
 
 
     // Message codes; see mHandler below.
-    // Request from SubscriptionInfoUpdater when SIM becomes absent or error.
+    // Request from UiccController when SIM becomes absent or error.
     private static final int EVENT_CLEAR_CONFIG = 0;
     // Has connected to default app.
     private static final int EVENT_CONNECTED_TO_DEFAULT = 3;
@@ -166,7 +163,7 @@
     private static final int EVENT_FETCH_DEFAULT_TIMEOUT = 14;
     // Fetching config timed out from a carrier app.
     private static final int EVENT_FETCH_CARRIER_TIMEOUT = 15;
-    // SubscriptionInfoUpdater has finished updating the sub for the carrier config.
+    // SubscriptionManagerService has finished updating the sub for the carrier config.
     private static final int EVENT_SUBSCRIPTION_INFO_UPDATED = 16;
     // Multi-SIM config changed.
     private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 17;
@@ -697,9 +694,7 @@
      * receiver for relevant events.
      */
     @VisibleForTesting
-    /* package */ CarrierConfigLoader(@NonNull Context context,
-            //TODO: Remove SubscriptionInfoUpdater.
-            @Nullable SubscriptionInfoUpdater subscriptionInfoUpdater, @NonNull Looper looper) {
+    /* package */ CarrierConfigLoader(@NonNull Context context, @NonNull Looper looper) {
         mContext = context;
         mPlatformCarrierConfigPackage =
                 mContext.getString(R.string.platform_carrier_config_package);
@@ -728,7 +723,6 @@
                     new HandlerExecutor(mHandler), mCarrierServiceChangeCallbacks[phoneId]);
         }
         logd("CarrierConfigLoader has started");
-        mSubscriptionInfoUpdater = subscriptionInfoUpdater;
 
         PhoneConfigurationManager.registerForMultiSimConfigChange(
                 mHandler, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
@@ -745,8 +739,7 @@
     /* package */ static CarrierConfigLoader init(@NonNull Context context) {
         synchronized (CarrierConfigLoader.class) {
             if (sInstance == null) {
-                sInstance = new CarrierConfigLoader(context,
-                        PhoneFactory.getSubscriptionInfoUpdater(), Looper.myLooper());
+                sInstance = new CarrierConfigLoader(context, Looper.myLooper());
                 // Make this service available through ServiceManager.
                 TelephonyFrameworkInitializer.getTelephonyServiceManager()
                         .getCarrierConfigServiceRegisterer().register(sInstance);
@@ -811,16 +804,10 @@
             configToSend.putAll(config);
         }
 
-        if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-            SubscriptionManagerService.getInstance().updateSubscriptionByCarrierConfig(
-                    phoneId, configPackageName, configToSend,
-                    () -> mHandler.obtainMessage(EVENT_SUBSCRIPTION_INFO_UPDATED, phoneId, -1)
-                            .sendToTarget());
-        } else {
-            mSubscriptionInfoUpdater.updateSubscriptionByCarrierConfigAndNotifyComplete(
-                    phoneId, configPackageName, configToSend,
-                    mHandler.obtainMessage(EVENT_SUBSCRIPTION_INFO_UPDATED, phoneId, -1));
-        }
+        SubscriptionManagerService.getInstance().updateSubscriptionByCarrierConfig(
+                phoneId, configPackageName, configToSend,
+                () -> mHandler.obtainMessage(EVENT_SUBSCRIPTION_INFO_UPDATED, phoneId, -1)
+                        .sendToTarget());
     }
 
     private void broadcastConfigChangedIntent(int phoneId) {
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 8849a77..36e5012 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -180,7 +180,6 @@
 import com.android.internal.telephony.ICallForwardingInfoCallback;
 import com.android.internal.telephony.IImsStateCallback;
 import com.android.internal.telephony.IIntegerConsumer;
-import com.android.internal.telephony.ILongConsumer;
 import com.android.internal.telephony.INumberVerificationCallback;
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.IccCard;
@@ -202,7 +201,6 @@
 import com.android.internal.telephony.SmsApplication;
 import com.android.internal.telephony.SmsController;
 import com.android.internal.telephony.SmsPermissions;
-import com.android.internal.telephony.SubscriptionController;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyPermissions;
 import com.android.internal.telephony.data.DataUtils;
@@ -411,7 +409,6 @@
     private final UserManager mUserManager;
     private final AppOpsManager mAppOps;
     private final MainThreadHandler mMainThreadHandler;
-    private final SubscriptionController mSubscriptionController;
     private final SharedPreferences mTelephonySharedPreferences;
     private final PhoneConfigurationManager mPhoneConfigurationManager;
     private final RadioInterfaceCapabilityController mRadioInterfaceCapabilities;
@@ -2462,11 +2459,6 @@
         mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);
         mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
         mMainThreadHandler = new MainThreadHandler();
-        if (!PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-            mSubscriptionController = SubscriptionController.getInstance();
-        } else {
-            mSubscriptionController = null;
-        }
         mTelephonySharedPreferences = PreferenceManager.getDefaultSharedPreferences(mApp);
         mNetworkScanRequestTracker = new NetworkScanRequestTracker();
         mPhoneConfigurationManager = PhoneConfigurationManager.getInstance();
@@ -3038,11 +3030,12 @@
                 + ",reason=" + reason + ",callingPackage=" + getCurrentPackageName());
         final long identity = Binder.clearCallingIdentity();
         try {
-            final Phone phone = getPhone(subId);
+            final Phone phone = getPhoneFromSubIdOrDefault(subId);
             if (phone != null) {
                 phone.setRadioPowerForReason(false, reason);
                 return true;
             } else {
+                loge("requestRadioPowerOffForReason: phone is null");
                 return false;
             }
         } finally {
@@ -3064,11 +3057,12 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            final Phone phone = getPhone(subId);
+            final Phone phone = getPhoneFromSubIdOrDefault(subId);
             if (phone != null) {
                 phone.setRadioPowerForReason(true, reason);
                 return true;
             } else {
+                loge("clearRadioPowerOffForReason: phone is null");
                 return false;
             }
         } finally {
@@ -3095,9 +3089,11 @@
                 return result;
             }
 
-            final Phone phone = getPhone(subId);
+            final Phone phone = getPhoneFromSubIdOrDefault(subId);
             if (phone != null) {
                 result.addAll(phone.getRadioPowerOffReasons());
+            } else {
+                loge("getRadioPowerOffReasons: phone is null");
             }
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -5496,11 +5492,8 @@
     }
 
     private boolean isActiveSubscription(int subId) {
-        if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-            return getSubscriptionManagerService().isActiveSubId(subId,
-                    mApp.getOpPackageName(), mApp.getFeatureId());
-        }
-        return mSubscriptionController.isActiveSubId(subId);
+        return getSubscriptionManagerService().isActiveSubId(subId,
+                mApp.getOpPackageName(), mApp.getFeatureId());
     }
 
     /**
@@ -7462,16 +7455,9 @@
                 return null;
             }
 
-            ParcelUuid groupUuid;
-            if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-                final SubscriptionInfo info = getSubscriptionManagerService()
-                        .getSubscriptionInfo(subId);
-                groupUuid = info.getGroupUuid();
-            } else {
-                final SubscriptionInfo info = mSubscriptionController
-                        .getSubscriptionInfo(subId);
-                groupUuid = info.getGroupUuid();
-            }
+            final SubscriptionInfo info = getSubscriptionManagerService()
+                    .getSubscriptionInfo(subId);
+            ParcelUuid groupUuid = info.getGroupUuid();
             // If it doesn't belong to any group, return just subscriberId of itself.
             if (groupUuid == null) {
                 return new String[]{subscriberId};
@@ -7479,16 +7465,9 @@
 
             // Get all subscriberIds from the group.
             final List<String> mergedSubscriberIds = new ArrayList<>();
-            List<SubscriptionInfo> groupInfos;
-            if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-                groupInfos = getSubscriptionManagerService()
-                        .getSubscriptionsInGroup(groupUuid, mApp.getOpPackageName(),
-                                mApp.getAttributionTag());
-            } else {
-                groupInfos = mSubscriptionController
-                        .getSubscriptionsInGroup(groupUuid, mApp.getOpPackageName(),
-                                mApp.getAttributionTag());
-            }
+            List<SubscriptionInfo> groupInfos = getSubscriptionManagerService()
+                    .getSubscriptionsInGroup(groupUuid, mApp.getOpPackageName(),
+                            mApp.getAttributionTag());
             for (SubscriptionInfo subInfo : groupInfos) {
                 subscriberId = telephonyManager.getSubscriberId(subInfo.getSubscriptionId());
                 if (subscriberId != null) {
@@ -8048,23 +8027,12 @@
         }
         final long identity = Binder.clearCallingIdentity();
         try {
-            SubscriptionInfo info;
-            if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-                info = getSubscriptionManagerService().getActiveSubscriptionInfo(subId,
-                        phone.getContext().getOpPackageName(),
-                        phone.getContext().getAttributionTag());
-                if (info == null) {
-                    log("getSimLocaleForSubscriber, inactive subId: " + subId);
-                    return null;
-                }
-            } else {
-                info = mSubscriptionController.getActiveSubscriptionInfo(subId,
-                        phone.getContext().getOpPackageName(),
-                        phone.getContext().getAttributionTag());
-                if (info == null) {
-                    log("getSimLocaleForSubscriber, inactive subId: " + subId);
-                    return null;
-                }
+            SubscriptionInfo info = getSubscriptionManagerService().getActiveSubscriptionInfo(subId,
+                    phone.getContext().getOpPackageName(),
+                    phone.getContext().getAttributionTag());
+            if (info == null) {
+                log("getSimLocaleForSubscriber, inactive subId: " + subId);
+                return null;
             }
             // Try and fetch the locale from the carrier properties or from the SIM language
             // preferences (EF-PL and EF-LI)...
@@ -8116,12 +8084,8 @@
      * NOTE: this method assumes permission checks are done and caller identity has been cleared.
      */
     private List<SubscriptionInfo> getActiveSubscriptionInfoListPrivileged() {
-        if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-            return getSubscriptionManagerService().getActiveSubscriptionInfoList(
-                    mApp.getOpPackageName(), mApp.getAttributionTag());
-        }
-        return mSubscriptionController.getActiveSubscriptionInfoList(mApp.getOpPackageName(),
-                mApp.getAttributionTag());
+        return getSubscriptionManagerService().getActiveSubscriptionInfoList(
+                mApp.getOpPackageName(), mApp.getAttributionTag());
     }
 
     private ActivityStatsTechSpecificInfo[] mLastModemActivitySpecificInfo = null;
@@ -8331,21 +8295,12 @@
                 .contains(callingPackage);
         try {
             // isActiveSubId requires READ_PHONE_STATE, which we already check for above
-            if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-                SubscriptionInfoInternal subInfo = getSubscriptionManagerService()
-                        .getSubscriptionInfoInternal(subId);
-                if (subInfo == null || !subInfo.isActive()) {
-                    Rlog.d(LOG_TAG, "getServiceStateForSubscriber returning null for inactive "
-                            + "subId=" + subId);
-                    return null;
-                }
-            } else {
-                if (!mSubscriptionController.isActiveSubId(subId, callingPackage,
-                        callingFeatureId)) {
-                    Rlog.d(LOG_TAG, "getServiceStateForSubscriber returning null for inactive "
-                            + "subId=" + subId);
-                    return null;
-                }
+            SubscriptionInfoInternal subInfo = getSubscriptionManagerService()
+                    .getSubscriptionInfoInternal(subId);
+            if (subInfo == null || !subInfo.isActive()) {
+                Rlog.d(LOG_TAG, "getServiceStateForSubscriber returning null for inactive "
+                        + "subId=" + subId);
+                return null;
             }
 
             ServiceState ss = phone.getServiceState();
@@ -12513,6 +12468,41 @@
     }
 
     /**
+     * This API can be used by only CTS to update satellite gateway service package name.
+     *
+     * @param servicePackageName The package name of the satellite gateway service.
+     * @return {@code true} if the satellite gateway service is set successfully,
+     * {@code false} otherwise.
+     */
+    public boolean setSatelliteGatewayServicePackageName(@Nullable String servicePackageName) {
+        Log.d(LOG_TAG, "setSatelliteGatewayServicePackageName - " + servicePackageName);
+        TelephonyPermissions.enforceShellOnly(
+                Binder.getCallingUid(), "setSatelliteGatewayServicePackageName");
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+                "setSatelliteGatewayServicePackageName");
+        return mSatelliteController.setSatelliteGatewayServicePackageName(servicePackageName);
+    }
+
+    /**
+     * This API can be used by only CTS to update the timeout duration in milliseconds that
+     * satellite should stay at listening mode to wait for the next incoming page before disabling
+     * listening mode.
+     *
+     * @param timeoutMillis The timeout duration in millisecond.
+     * @return {@code true} if the timeout duration is set successfully, {@code false} otherwise.
+     */
+    public boolean setSatelliteListeningTimeoutDuration(long timeoutMillis) {
+        Log.d(LOG_TAG, "setSatelliteListeningTimeoutDuration - " + timeoutMillis);
+        TelephonyPermissions.enforceShellOnly(
+                Binder.getCallingUid(), "setSatelliteListeningTimeoutDuration");
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+                "setSatelliteListeningTimeoutDuration");
+        return mSatelliteController.setSatelliteListeningTimeoutDuration(timeoutMillis);
+    }
+
+    /**
      * Check whether the caller (or self, if not processing an IPC) can read device identifiers.
      *
      * <p>This method behaves in one of the following ways:
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 53c7f4e..b444840 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -181,6 +181,10 @@
     private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
     private static final String SET_SATELLITE_SERVICE_PACKAGE_NAME =
             "set-satellite-service-package-name";
+    private static final String SET_SATELLITE_GATEWAY_SERVICE_PACKAGE_NAME =
+            "set-satellite-gateway-service-package-name";
+    private static final String SET_SATELLITE_LISTENING_TIMEOUT_DURATION =
+            "set-satellite-listening-timeout-duration";
 
     private static final String INVALID_ENTRY_ERROR = "An emergency number (only allow '0'-'9', "
             + "'*', '#' or '+') needs to be specified after -a in the command ";
@@ -364,6 +368,10 @@
                 return clearCarrierServicePackageOverride();
             case SET_SATELLITE_SERVICE_PACKAGE_NAME:
                 return handleSetSatelliteServicePackageNameCommand();
+            case SET_SATELLITE_GATEWAY_SERVICE_PACKAGE_NAME:
+                return handleSetSatelliteGatewayServicePackageNameCommand();
+            case SET_SATELLITE_LISTENING_TIMEOUT_DURATION:
+                return handleSetSatelliteListeningTimeoutDuration();
             default: {
                 return handleDefaultCommands(cmd);
             }
@@ -743,9 +751,19 @@
         pw.println("Satellite Commands:");
         pw.println("  set-satellite-service-package-name [-s SERVICE_PACKAGE_NAME]");
         pw.println("    Sets the package name of satellite service defined in");
-        pw.println("    SERVICE_PACKAGE_NAME to be the bound. Options are:");
+        pw.println("    SERVICE_PACKAGE_NAME to be bound. Options are:");
         pw.println("      -s: the satellite service package name that Telephony will bind to.");
         pw.println("          If no option is specified, it will bind to the default.");
+        pw.println("  set-satellite-gateway-service-package-name [-s SERVICE_PACKAGE_NAME]");
+        pw.println("    Sets the package name of satellite gateway service defined in");
+        pw.println("    SERVICE_PACKAGE_NAME to be bound. Options are:");
+        pw.println("      -s: the satellite gateway service package name that Telephony will bind");
+        pw.println("           to. If no option is specified, it will bind to the default.");
+        pw.println("  set-satellite-listening-timeout-duration [-t TIMEOUT_MILLIS]");
+        pw.println("    Sets the timeout duration in millis that satellite will stay at listening");
+        pw.println("    mode. Options are:");
+        pw.println("      -t: the timeout duration in milliseconds.");
+        pw.println("          If no option is specified, it will use the default values.");
     }
 
     private void onHelpImei() {
@@ -3116,6 +3134,70 @@
         return 0;
     }
 
+    private int handleSetSatelliteGatewayServicePackageNameCommand() {
+        PrintWriter errPw = getErrPrintWriter();
+        String serviceName = null;
+
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "-s": {
+                    serviceName = getNextArgRequired();
+                    break;
+                }
+            }
+        }
+        Log.d(LOG_TAG, "handleSetSatelliteGatewayServicePackageNameCommand: serviceName="
+                + serviceName);
+
+        try {
+            boolean result = mInterface.setSatelliteGatewayServicePackageName(serviceName);
+            if (VDBG) {
+                Log.v(LOG_TAG, "setSatelliteGatewayServicePackageName " + serviceName
+                        + ", result = " + result);
+            }
+            getOutPrintWriter().println(result);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "setSatelliteGatewayServicePackageName: " + serviceName
+                    + ", error = " + e.getMessage());
+            errPw.println("Exception: " + e.getMessage());
+            return -1;
+        }
+        return 0;
+    }
+
+    private int handleSetSatelliteListeningTimeoutDuration() {
+        PrintWriter errPw = getErrPrintWriter();
+        long timeoutMillis = 0;
+
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "-t": {
+                    timeoutMillis = Long.parseLong(getNextArgRequired());
+                    break;
+                }
+            }
+        }
+        Log.d(LOG_TAG, "handleSetSatelliteListeningTimeoutDuration: timeoutMillis="
+                + timeoutMillis);
+
+        try {
+            boolean result = mInterface.setSatelliteListeningTimeoutDuration(timeoutMillis);
+            if (VDBG) {
+                Log.v(LOG_TAG, "setSatelliteListeningTimeoutDuration " + timeoutMillis
+                        + ", result = " + result);
+            }
+            getOutPrintWriter().println(result);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "setSatelliteListeningTimeoutDuration: " + timeoutMillis
+                    + ", error = " + e.getMessage());
+            errPw.println("Exception: " + e.getMessage());
+            return -1;
+        }
+        return 0;
+    }
+
     private int handleCarrierRestrictionStatusCommand() {
         try {
             String MOCK_MODEM_SERVICE_NAME = "android.telephony.mockmodem.MockModemService";
diff --git a/src/com/android/phone/settings/AccessibilitySettingsFragment.java b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
index 4c29e65..8c4a343 100644
--- a/src/com/android/phone/settings/AccessibilitySettingsFragment.java
+++ b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
@@ -39,7 +39,6 @@
 import com.android.ims.ImsManager;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
-import com.android.internal.telephony.SubscriptionController;
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 import com.android.phone.PhoneGlobals;
 import com.android.phone.R;
@@ -184,12 +183,8 @@
             // Update RTT config with IMS Manager if the always-on carrier config isn't set to true.
             CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService(
                             Context.CARRIER_CONFIG_SERVICE);
-            int[] activeSubIds;
-            if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-                activeSubIds = SubscriptionManagerService.getInstance().getActiveSubIdList(true);
-            } else {
-                activeSubIds = SubscriptionController.getInstance().getActiveSubIdList(true);
-            }
+            int[] activeSubIds = SubscriptionManagerService.getInstance().getActiveSubIdList(true);
+
             for (int subId : activeSubIds) {
                 if (!configManager.getConfigForSubId(subId).getBoolean(
                         CarrierConfigManager.KEY_IGNORE_RTT_MODE_SETTING_BOOL, false)) {
@@ -271,15 +266,7 @@
     private boolean shouldShowRttSetting() {
         // Go through all the subs -- if we want to display the RTT setting for any of them, do
         // display it.
-        if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-            for (int subId : SubscriptionManagerService.getInstance().getActiveSubIdList(true)) {
-                if (PhoneGlobals.getInstance().phoneMgr.isRttSupported(subId)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-        for (int subId : SubscriptionController.getInstance().getActiveSubIdList(true)) {
+        for (int subId : SubscriptionManagerService.getInstance().getActiveSubIdList(true)) {
             if (PhoneGlobals.getInstance().phoneMgr.isRttSupported(subId)) {
                 return true;
             }
diff --git a/src/com/android/phone/vvm/RemoteVvmTaskManager.java b/src/com/android/phone/vvm/RemoteVvmTaskManager.java
index 7329854..daa5d67b 100644
--- a/src/com/android/phone/vvm/RemoteVvmTaskManager.java
+++ b/src/com/android/phone/vvm/RemoteVvmTaskManager.java
@@ -183,6 +183,7 @@
             if (targetPackage != null && !TextUtils.equals(packageName, targetPackage)) {
                 VvmLog.w(TAG, "target package " + targetPackage
                         + " is no longer the active VisualVoicemailService, ignoring");
+                continue;
             }
             ComponentInfo componentInfo = TelephonyUtils.getComponentInfo(info);
             return new ComponentName(componentInfo.packageName, componentInfo.name);
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 57e65ee..2b69b82 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -63,7 +63,6 @@
 import com.android.internal.telephony.ExponentialBackoff;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
-import com.android.internal.telephony.SubscriptionController;
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 import com.android.phone.PhoneGlobals;
 import com.android.phone.PhoneUtils;
@@ -550,38 +549,22 @@
                 return false;
             }
 
-            if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-                if (SubscriptionManagerService.getInstance() == null) {
-                    Log.d(this,
-                            "isEmergencyPreferredAccount: SubscriptionManagerService not "
-                                    + "available.");
-                    return false;
-                }
-                // Only set an emergency preference on devices with multiple active subscriptions
-                // (include opportunistic subscriptions) in this check.
-                // API says never null, but this can return null in testing.
-                int[] activeSubIds = SubscriptionManagerService.getInstance()
-                        .getActiveSubIdList(false);
-                if (activeSubIds == null || activeSubIds.length <= 1) {
-                    Log.d(this, "isEmergencyPreferredAccount: one or less active subscriptions.");
-                    return false;
-                }
-            } else {
-                SubscriptionController controller = SubscriptionController.getInstance();
-                if (controller == null) {
-                    Log.d(this,
-                            "isEmergencyPreferredAccount: SubscriptionController not available.");
-                    return false;
-                }
-                // Only set an emergency preference on devices with multiple active subscriptions
-                // (include opportunistic subscriptions) in this check.
-                // API says never null, but this can return null in testing.
-                int[] activeSubIds = controller.getActiveSubIdList(false);
-                if (activeSubIds == null || activeSubIds.length <= 1) {
-                    Log.d(this, "isEmergencyPreferredAccount: one or less active subscriptions.");
-                    return false;
-                }
+            if (SubscriptionManagerService.getInstance() == null) {
+                Log.d(this,
+                        "isEmergencyPreferredAccount: SubscriptionManagerService not "
+                                + "available.");
+                return false;
             }
+            // Only set an emergency preference on devices with multiple active subscriptions
+            // (include opportunistic subscriptions) in this check.
+            // API says never null, but this can return null in testing.
+            int[] activeSubIds = SubscriptionManagerService.getInstance()
+                    .getActiveSubIdList(false);
+            if (activeSubIds == null || activeSubIds.length <= 1) {
+                Log.d(this, "isEmergencyPreferredAccount: one or less active subscriptions.");
+                return false;
+            }
+
             // Check to see if this PhoneAccount is associated with the default Data subscription.
             if (!SubscriptionManager.isValidSubscriptionId(subId)) {
                 Log.d(this, "isEmergencyPreferredAccount: provided subId " + subId + "is not "
@@ -591,17 +574,10 @@
             int userDefaultData = SubscriptionManager.getDefaultDataSubscriptionId();
             boolean isActiveDataValid = SubscriptionManager.isValidSubscriptionId(activeDataSubId);
 
-            boolean isActiveDataOpportunistic;
-            if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-                SubscriptionInfo subInfo;
-                subInfo = SubscriptionManagerService.getInstance()
-                        .getSubscriptionInfo(activeDataSubId);
-                isActiveDataOpportunistic = isActiveDataValid && subInfo != null
-                        && subInfo.isOpportunistic();
-            } else {
-                isActiveDataOpportunistic = isActiveDataValid
-                        && SubscriptionController.getInstance().isOpportunistic(activeDataSubId);
-            }
+            SubscriptionInfo subInfo = SubscriptionManagerService.getInstance()
+                    .getSubscriptionInfo(activeDataSubId);
+            boolean isActiveDataOpportunistic = isActiveDataValid && subInfo != null
+                    && subInfo.isOpportunistic();
 
             // compare the activeDataSubId to the subId specified only if it is valid and not an
             // opportunistic subscription (only supports data). If not, use the current default
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 9f248b7..6d136b0 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -331,7 +331,6 @@
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
                         sendTelephonyConnectionEvent((String) args.arg1, (Bundle) args.arg2);
-
                     } finally {
                         args.recycle();
                     }
@@ -738,7 +737,13 @@
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = event;
             args.arg2 = extras;
-            mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget();
+            if (EVENT_MERGE_COMPLETE.equals(event)){
+                // To ensure the MERGE_COMPLETE event logs before the listeners are removed,
+                // circumvent the handler by sending the connection event directly:
+                sendTelephonyConnectionEvent(event, extras);
+            } else {
+                mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget();
+            }
         }
 
         @Override
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 113b47d..18b95e1 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -58,6 +58,7 @@
 import android.telephony.TelephonyManager;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.text.TextUtils;
 import android.util.Pair;
 import android.view.WindowManager;
@@ -73,7 +74,6 @@
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.RIL;
-import com.android.internal.telephony.SubscriptionController;
 import com.android.internal.telephony.d2d.Communicator;
 import com.android.internal.telephony.data.PhoneSwitcher;
 import com.android.internal.telephony.domainselection.DomainSelectionConnection;
@@ -131,7 +131,7 @@
 
     // Timeout before we terminate the outgoing DSDA call if HOLD did not complete in time on the
     // existing call.
-    private static final int DEFAULT_DSDA_OUTGOING_CALL_HOLD_TIMEOUT_MS = 1000;
+    private static final int DEFAULT_DSDA_OUTGOING_CALL_HOLD_TIMEOUT_MS = 2000;
     private static final String KEY_DOMAIN_COMPARE_FEATURE_ENABLED_FLAG =
             "is_domain_selection_compare_feature_enabled";
 
@@ -559,7 +559,11 @@
                 @Override
                 public void onOriginalConnectionConfigured(TelephonyConnection c) {
                     com.android.internal.telephony.Connection origConn = c.getOriginalConnection();
-                    if (origConn == null) return;
+                    if ((origConn == null) || (mEmergencyStateTracker == null)) {
+                        // mEmergencyStateTracker is null when no emergency call has been dialed
+                        // after bootup and normal call fails with 380 response.
+                        return;
+                    }
                     // Update the domain in the case that it changes,for example during initial
                     // setup or when there was an srvcc or internal redial.
                     mEmergencyStateTracker.onEmergencyCallDomainUpdated(
@@ -656,14 +660,14 @@
             if (c != null) {
                 switch (c.getState()) {
                     case Connection.STATE_HOLDING: {
-                        Log.d(LOG_TAG, "Connection " + connection
+                        Log.d(LOG_TAG, "Connection " + connection.getTelecomCallId()
                                 + " changed to STATE_HOLDING!");
                         mStateHoldingFuture.complete(true);
                         c.removeTelephonyConnectionListener(this);
                     }
                     break;
                     case Connection.STATE_DISCONNECTED: {
-                        Log.d(LOG_TAG, "Connection " + connection
+                        Log.d(LOG_TAG, "Connection " + connection.getTelecomCallId()
                                 + " changed to STATE_DISCONNECTED!");
                         mStateHoldingFuture.complete(false);
                         c.removeTelephonyConnectionListener(this);
@@ -1130,27 +1134,16 @@
                         return (phone.getState() == PhoneConstants.State.OFFHOOK)
                             || phone.getServiceStateTracker().isRadioOn();
                     } else {
-                        if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-                            SubscriptionInfoInternal subInfo = SubscriptionManagerService
-                                    .getInstance().getSubscriptionInfoInternal(phone.getSubId());
-                            // Wait until we are in service and ready to make calls. This can happen
-                            // when we power down the radio on bluetooth to save power on watches or
-                            // if it is a test emergency number and we have to wait for the device
-                            // to move IN_SERVICE before the call can take place over normal
-                            // routing.
-                            return (phone.getState() == PhoneConstants.State.OFFHOOK)
-                                    // Do not wait for voice in service on opportunistic SIMs.
-                                    || (subInfo != null && subInfo.isOpportunistic())
-                                    || serviceState == ServiceState.STATE_IN_SERVICE;
-                        }
+                        SubscriptionInfoInternal subInfo = SubscriptionManagerService
+                                .getInstance().getSubscriptionInfoInternal(phone.getSubId());
                         // Wait until we are in service and ready to make calls. This can happen
-                        // when we power down the radio on bluetooth to save power on watches or if
-                        // it is a test emergency number and we have to wait for the device to move
-                        // IN_SERVICE before the call can take place over normal routing.
+                        // when we power down the radio on bluetooth to save power on watches or
+                        // if it is a test emergency number and we have to wait for the device
+                        // to move IN_SERVICE before the call can take place over normal
+                        // routing.
                         return (phone.getState() == PhoneConstants.State.OFFHOOK)
                                 // Do not wait for voice in service on opportunistic SIMs.
-                                || SubscriptionController.getInstance().isOpportunistic(
-                                        phone.getSubId())
+                                || (subInfo != null && subInfo.isOpportunistic())
                                 || serviceState == ServiceState.STATE_IN_SERVICE;
                     }
                 }
@@ -1182,29 +1175,56 @@
                     return resultConnection;
                 } else {
                     if (mTelephonyManagerProxy.isConcurrentCallsPossible()) {
-                        delayDialForOtherSubHold(phone, request.getAccountHandle(), (result) -> {
-                            Log.d(this,
-                                    "onCreateOutgoingConn - delayDialForOtherSubHold result = "
-                                            + result);
-                            if (result) {
-                                placeOutgoingConnection(request, resultConnection, phone);
-                            } else {
-                                ((TelephonyConnection) resultConnection).hangup(
-                                        android.telephony.DisconnectCause.LOCAL);
-                            }
-                        });
-                        return resultConnection;
+                        Conferenceable c = maybeHoldCallsOnOtherSubs(request.getAccountHandle());
+                        if (c != null) {
+                            delayDialForOtherSubHold(phone, c, (success) -> {
+                                Log.d(this,
+                                        "onCreateOutgoingConn - delayDialForOtherSubHold"
+                                                + " success = " + success);
+                                if (success) {
+                                    placeOutgoingConnection(request, resultConnection,
+                                            phone);
+                                } else {
+                                    ((TelephonyConnection) resultConnection).hangup(
+                                            android.telephony.DisconnectCause.LOCAL);
+                                }
+                            });
+                            return resultConnection;
+                        }
                     }
-                    // The standard case.
                     return placeOutgoingConnection(request, resultConnection, phone);
                 }
             } else {
                 final Connection resultConnection = getTelephonyConnection(request, numberToDial,
                         true, handle, phone);
-                delayDialForDdsSwitch(phone, (result) -> {
-                    Log.i(this, "onCreateOutgoingConn - delayDialForDdsSwitch result = " + result);
-                        placeOutgoingConnection(request, resultConnection, phone);
-                });
+
+                CompletableFuture<Void> maybeHoldFuture = CompletableFuture.completedFuture(null);
+                if (mTelephonyManagerProxy.isConcurrentCallsPossible()
+                        && shouldHoldForEmergencyCall(phone)) {
+                    // If the PhoneAccountHandle was adjusted on building the TelephonyConnection,
+                    // the relevant PhoneAccountHandle will be updated in resultConnection.
+                    PhoneAccountHandle phoneAccountHandle =
+                            resultConnection.getPhoneAccountHandle() == null
+                            ? request.getAccountHandle() : resultConnection.getPhoneAccountHandle();
+                    Conferenceable c = maybeHoldCallsOnOtherSubs(phoneAccountHandle);
+                    if (c != null) {
+                        maybeHoldFuture = delayDialForOtherSubHold(phone, c, (success) -> {
+                            Log.i(this, "onCreateOutgoingConn emergency-"
+                                    + " delayDialForOtherSubHold success = " + success);
+                            if (!success) {
+                                // Terminates the existing call to make way for the emergency call.
+                                hangup(c, android.telephony.DisconnectCause
+                                        .OUTGOING_EMERGENCY_CALL_PLACED);
+                            }
+                        });
+                    }
+                }
+                Consumer<Boolean> ddsSwitchConsumer = (result) -> {
+                    Log.i(this, "onCreateOutgoingConn emergency-"
+                            + " delayDialForDdsSwitch result = " + result);
+                    placeOutgoingConnection(request, resultConnection, phone);
+                };
+                maybeHoldFuture.thenRun(() -> delayDialForDdsSwitch(phone, ddsSwitchConsumer));
                 return resultConnection;
             }
         }
@@ -1319,16 +1339,9 @@
             // Notify Telecom of the new Connection type.
             // TODO: Switch out the underlying connection instead of creating a new
             // one and causing UI Jank.
-            boolean noActiveSimCard;
-            if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-                noActiveSimCard = SubscriptionManagerService.getInstance()
-                        .getActiveSubInfoCount(phone.getContext().getOpPackageName(),
-                                phone.getContext().getAttributionTag()) == 0;
-            } else {
-                noActiveSimCard = SubscriptionController.getInstance()
-                        .getActiveSubInfoCount(phone.getContext().getOpPackageName(),
-                                phone.getContext().getAttributionTag()) == 0;
-            }
+            boolean noActiveSimCard = SubscriptionManagerService.getInstance()
+                    .getActiveSubInfoCount(phone.getContext().getOpPackageName(),
+                            phone.getContext().getAttributionTag()) == 0;
             // If there's no active sim card and the device is in emergency mode, use E account.
             addExistingConnection(mPhoneUtilsProxy.makePstnPhoneAccountHandleWithPrefix(
                     phone, "", isEmergencyNumber && noActiveSimCard), repConnection);
@@ -3005,7 +3018,7 @@
     }
 
     /**
-     * If needed, block until the the default data is is switched for outgoing emergency call, or
+     * If needed, block until the default data is switched for outgoing emergency call, or
      * timeout expires.
      * @param phone The Phone to switch the DDS on.
      * @param completeConsumer The consumer to call once the default data subscription has been
@@ -3160,37 +3173,30 @@
         return future;
     }
 
-    // If there are any live calls on the other subscription, sends a hold request for the live call
-    // and waits for the STATE_HOLDING confirmation, to sequence the dial of the outgoing call.
-    private void delayDialForOtherSubHold(Phone phone, PhoneAccountHandle phoneAccountHandle,
+    // Returns a future that waits for the STATE_HOLDING confirmation on the input
+    // {@link Conferenceable}, or times out.
+    private CompletableFuture<Void> delayDialForOtherSubHold(Phone phone, Conferenceable c,
             Consumer<Boolean> completeConsumer) {
-        Conferenceable c = maybeHoldCallsOnOtherSubs(phoneAccountHandle);
-        if (c == null) {
-            // Nothing to hold.
-            completeConsumer.accept(true);
-            return;
-        }
-
-        if (phone == null) {
+        if (c == null || phone == null) {
+            // Unexpected inputs
             completeConsumer.accept(false);
-            return;
+            return CompletableFuture.completedFuture(null);
         }
 
         try {
-            // We have dispatched a 'hold' command to a live call (Connection or Conference) on the
-            // other sub. Listen to state changed events to see if this entered hold state.
             CompletableFuture<Boolean> stateHoldingFuture = listenForHoldStateChanged(c);
             // a timeout that will complete the future to not block the outgoing call indefinitely.
             CompletableFuture<Boolean> timeout = new CompletableFuture<>();
             phone.getContext().getMainThreadHandler().postDelayed(
                     () -> timeout.complete(false), DEFAULT_DSDA_OUTGOING_CALL_HOLD_TIMEOUT_MS);
             // Ensure that the Consumer is completed on the main thread.
-            stateHoldingFuture.acceptEitherAsync(timeout, completeConsumer,
+            return stateHoldingFuture.acceptEitherAsync(timeout, completeConsumer,
                     phone.getContext().getMainExecutor());
         } catch (Exception e) {
             Log.w(this, "delayDialForOtherSubHold - exception= "
                     + e.getMessage());
             completeConsumer.accept(false);
+            return CompletableFuture.completedFuture(null);
         }
     }
 
@@ -3429,6 +3435,13 @@
      * Returns true if the state of the Phone is IN_SERVICE or available for emergency calling only.
      */
     private boolean isAvailableForEmergencyCalls(Phone phone) {
+        if (phone.getImsRegistrationTech() == ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM) {
+            // When a Phone is registered to Cross-SIM calling, there must always be a Phone on the
+            // other sub which is registered to cellular, so that must be selected.
+            Log.d(this, "isAvailableForEmergencyCalls: skipping over phone "
+                    + phone + " as it is registered to CROSS_SIM");
+            return false;
+        }
         return ServiceState.STATE_IN_SERVICE == phone.getServiceState().getState() ||
                 phone.getServiceState().isEmergencyOnly();
     }
@@ -3837,6 +3850,16 @@
         }
     }
 
+    private static void hangup(Conferenceable conferenceable, int code) {
+        if (conferenceable instanceof TelephonyConnection) {
+            ((TelephonyConnection) conferenceable).hangup(code);
+        } else if (conferenceable instanceof Conference) {
+            ((Conference) conferenceable).onDisconnect();
+        } else {
+            Log.w(LOG_TAG, "hangup(): Unexpected conferenceable! " + conferenceable);
+        }
+    }
+
      /**
      * Evaluates whether a connection or conference exists on subscriptions other than the one
      * corresponding to the existing {@link PhoneAccountHandle}.
@@ -3864,6 +3887,9 @@
                                 currentHandle))
                 .toList();
         if (!otherSubConferences.isEmpty()) {
+            Log.i(LOG_TAG, "maybeGetFirstConferenceable: found "
+                    + otherSubConferences.get(0).getTelecomCallId() + " on "
+                    + otherSubConferences.get(0).getPhoneAccountHandle());
             return otherSubConferences.get(0);
         }
 
@@ -3881,6 +3907,9 @@
                 Log.w(LOG_TAG, "Unexpected number of connections: "
                         + otherSubConnections.size() + " on other sub!");
             }
+            Log.i(LOG_TAG, "maybeGetFirstConferenceable: found "
+                    + otherSubConnections.get(0).getTelecomCallId() + " on "
+                    + otherSubConnections.get(0).getPhoneAccountHandle());
             return otherSubConnections.get(0);
         }
         return null;
diff --git a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
index b1c288c..6848c9f 100644
--- a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
+++ b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
@@ -82,6 +82,7 @@
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsManager;
 import android.telephony.ims.ImsMmTelManager;
+import android.telephony.ims.ImsReasonInfo;
 import android.telephony.ims.ProvisioningManager;
 import android.text.TextUtils;
 import android.util.LocalLog;
@@ -669,7 +670,8 @@
         mCancelSignal = new CancellationSignal();
         // In case dialing over Wi-Fi has failed, do not the change the domain preference.
         if (!wifiFailed) {
-            mLastPreferredNetworks = getNextPreferredNetworks(csPreferred, mTryEpsFallback);
+            mLastPreferredNetworks = getNextPreferredNetworks(csPreferred, mTryEpsFallback,
+                    !startVoWifiTimer);
         }
         mTryEpsFallback = false;
 
@@ -704,11 +706,13 @@
      *
      * @param csPreferred Indicates whether CS preferred scan is requested.
      * @param tryEpsFallback Indicates whether scan requested for EPS fallback.
+     * @param lastScanFailed Indicates whether this a scan request due to the failure of last scan
+     *        request.
      * @return The list of preferred network types.
      */
     @VisibleForTesting
     public @RadioAccessNetworkType List<Integer> getNextPreferredNetworks(boolean csPreferred,
-            boolean tryEpsFallback) {
+            boolean tryEpsFallback, boolean lastScanFailed) {
         if (mRequiresVoLteEnabled && !isAdvancedCallingSettingEnabled()) {
             // Emergency call over IMS is not supported.
             logi("getNextPreferredNetworks VoLte setting is not enabled.");
@@ -778,6 +782,23 @@
             }
         }
 
+        // There can be cases that dialing IMS call failed but the modem doesn't know this
+        // situation with some vendor solutions. For example, dialing failure due to the
+        // emergency registration failure.
+        // Remove the current RAT from the scan list to avoid modem select current PLMN.
+        // If the scan fails, the next scan will include this RAT again.
+        //
+        // TODO (b/278183420) Replace this with a better solution by adding indication
+        // of call setup failure to the scan request.
+        ImsReasonInfo reasonInfo = mSelectionAttributes.getPsDisconnectCause();
+        if (!lastScanFailed && reasonInfo != null
+                && reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED) {
+            logi("getNextPreferredNetworks remove " + mLastNetworkType);
+            if (preferredNetworks.size() > 1) {
+                preferredNetworks.remove(Integer.valueOf(mLastNetworkType));
+            }
+        }
+
         return preferredNetworks;
     }
 
diff --git a/testapps/TestSliceApp/app/src/main/AndroidManifest.xml b/testapps/TestSliceApp/app/src/main/AndroidManifest.xml
index 53754de..cea9e5f 100644
--- a/testapps/TestSliceApp/app/src/main/AndroidManifest.xml
+++ b/testapps/TestSliceApp/app/src/main/AndroidManifest.xml
@@ -32,5 +32,7 @@
       <meta-data android:name="android.service.carrier.LONG_LIVED_BINDING"
           android:value="true" />
     </service>
+    <property android:name="android.net.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES"
+              android:resource="@xml/self_certified_network_capabilities_both" />
   </application>
 </manifest>
diff --git a/testapps/TestSliceApp/app/src/main/res/xml/self_certified_network_capabilities_both.xml b/testapps/TestSliceApp/app/src/main/res/xml/self_certified_network_capabilities_both.xml
new file mode 100644
index 0000000..cd4d370
--- /dev/null
+++ b/testapps/TestSliceApp/app/src/main/res/xml/self_certified_network_capabilities_both.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<network-capabilities-declaration xmlns:android="http://schemas.android.com/apk/res/android">
+    <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_LATENCY"/>
+    <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_BANDWIDTH"/>
+</network-capabilities-declaration>
\ No newline at end of file
diff --git a/tests/src/com/android/phone/CarrierConfigLoaderTest.java b/tests/src/com/android/phone/CarrierConfigLoaderTest.java
index f29c123..b6f8ed8 100644
--- a/tests/src/com/android/phone/CarrierConfigLoaderTest.java
+++ b/tests/src/com/android/phone/CarrierConfigLoaderTest.java
@@ -40,7 +40,6 @@
 import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerThread;
-import android.os.Message;
 import android.os.PersistableBundle;
 import android.os.UserHandle;
 import android.service.carrier.CarrierIdentifier;
@@ -55,8 +54,6 @@
 
 import com.android.TelephonyTestBase;
 import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.PhoneFactory;
-import com.android.internal.telephony.SubscriptionInfoUpdater;
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 
 import org.junit.After;
@@ -90,7 +87,6 @@
     @Mock Resources mResources;
     @Mock PackageManager mPackageManager;
     @Mock PackageInfo mPackageInfo;
-    @Mock SubscriptionInfoUpdater mSubscriptionInfoUpdater;
     @Mock SubscriptionManagerService mSubscriptionManagerService;
     @Mock SharedPreferences mSharedPreferences;
     @Mock TelephonyRegistryManager mTelephonyRegistryManager;
@@ -136,8 +132,7 @@
         mHandlerThread.start();
 
         mTestableLooper = new TestableLooper(mHandlerThread.getLooper());
-        mCarrierConfigLoader = new CarrierConfigLoader(mContext, mSubscriptionInfoUpdater,
-                mTestableLooper.getLooper());
+        mCarrierConfigLoader = new CarrierConfigLoader(mContext, mTestableLooper.getLooper());
         mHandler = mCarrierConfigLoader.getHandler();
 
         // Clear all configs to have the same starting point.
@@ -279,15 +274,9 @@
         mTestableLooper.processAllMessages();
 
         assertThat(mCarrierConfigLoader.getOverrideConfig(DEFAULT_PHONE_ID).isEmpty()).isTrue();
-        if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-            verify(mSubscriptionManagerService).updateSubscriptionByCarrierConfig(
-                    eq(DEFAULT_PHONE_ID), eq(PLATFORM_CARRIER_CONFIG_PACKAGE),
-                    any(PersistableBundle.class), any(Runnable.class));
-        } else {
-            verify(mSubscriptionInfoUpdater).updateSubscriptionByCarrierConfigAndNotifyComplete(
-                    eq(DEFAULT_PHONE_ID), eq(PLATFORM_CARRIER_CONFIG_PACKAGE),
-                    any(PersistableBundle.class), any(Message.class));
-        }
+        verify(mSubscriptionManagerService).updateSubscriptionByCarrierConfig(
+                eq(DEFAULT_PHONE_ID), eq(PLATFORM_CARRIER_CONFIG_PACKAGE),
+                any(PersistableBundle.class), any(Runnable.class));
     }
 
     /**
@@ -308,15 +297,9 @@
 
         assertThat(mCarrierConfigLoader.getOverrideConfig(DEFAULT_PHONE_ID).getInt(
                 CARRIER_CONFIG_EXAMPLE_KEY)).isEqualTo(CARRIER_CONFIG_EXAMPLE_VALUE);
-        if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
-            verify(mSubscriptionManagerService).updateSubscriptionByCarrierConfig(
-                    eq(DEFAULT_PHONE_ID), eq(PLATFORM_CARRIER_CONFIG_PACKAGE),
-                    any(PersistableBundle.class), any(Runnable.class));
-        } else {
-            verify(mSubscriptionInfoUpdater).updateSubscriptionByCarrierConfigAndNotifyComplete(
-                    eq(DEFAULT_PHONE_ID), eq(PLATFORM_CARRIER_CONFIG_PACKAGE),
-                    any(PersistableBundle.class), any(Message.class));
-        }
+        verify(mSubscriptionManagerService).updateSubscriptionByCarrierConfig(
+                eq(DEFAULT_PHONE_ID), eq(PLATFORM_CARRIER_CONFIG_PACKAGE),
+                any(PersistableBundle.class), any(Runnable.class));
     }
 
     /**
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index c92fde9..fadfaaf 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -1711,6 +1711,110 @@
         assertTrue(tc1.wasHeld);
     }
 
+    // For 'Virtual DSDA' devices, if there is an existing call on sub1, an outgoing call on sub2
+    // will place the sub1 call on hold.
+    @Test
+    @SmallTest
+    public void testOutgoingCallOnOtherSubPutsFirstCallOnHoldForVirtualDsdaDevice()
+            throws Exception {
+        setupForCallTest();
+        when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
+        doNothing().when(mContext).startActivity(any());
+
+        mBinderStub.createConnection(PHONE_ACCOUNT_HANDLE_1, "TC@1",
+                new ConnectionRequest(PHONE_ACCOUNT_HANDLE_1, Uri.parse("tel:16505551212"),
+                        new Bundle()),
+                true, false, null);
+        waitForHandlerAction(mTestConnectionService.getHandler(), TIMEOUT_MS);
+        assertEquals(1, mTestConnectionService.getAllConnections().size());
+
+        TelephonyConnection connection1 = (TelephonyConnection)
+                mTestConnectionService.getAllConnections().toArray()[0];
+
+        TelephonyConnection connection2 = (TelephonyConnection) mTestConnectionService
+                .onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_2,
+                        createConnectionRequest(PHONE_ACCOUNT_HANDLE_2, "1234", "TC@2"));
+        assertNotNull("test connection was not set up correctly.", connection2);
+
+        // Simulates that connection1 is placed on HOLD.
+        connection1.setTelephonyConnectionOnHold();
+
+        verify(mPhone1).dial(anyString(), any(), any());
+        assertEquals(connection1.getState(), android.telecom.Connection.STATE_HOLDING);
+    }
+
+    // For 'Virtual DSDA' devices, if the carrier config 'KEY_ALLOW_HOLD_CALL_DURING_EMERGENCY_BOOL'
+    // is not configured, or set to true, an outgoing emergency call will place the existing call on
+    // a different sub on hold.
+    @Test
+    @SmallTest
+    public void testEmergencyCallOnOtherSubPutsFirstCallOnHoldForVirtualDsdaDevice()
+            throws Exception {
+        setupForCallTest();
+        when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
+        doNothing().when(mContext).startActivity(any());
+
+        doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
+        mBinderStub.createConnection(PHONE_ACCOUNT_HANDLE_1, "TC@1",
+                new ConnectionRequest(PHONE_ACCOUNT_HANDLE_1, Uri.parse("tel:16505551212"),
+                        new Bundle()),
+                true, false, null);
+        waitForHandlerAction(mTestConnectionService.getHandler(), TIMEOUT_MS);
+        assertEquals(1, mTestConnectionService.getAllConnections().size());
+
+        TelephonyConnection connection1 = (TelephonyConnection)
+                mTestConnectionService.getAllConnections().toArray()[0];
+
+        // Simulates an outgoing emergency call.
+        TelephonyConnection connection2 = (TelephonyConnection) mTestConnectionService
+                .onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_2,
+                        createConnectionRequest(PHONE_ACCOUNT_HANDLE_2,
+                                TEST_EMERGENCY_NUMBER, "TC@2"));
+        assertNotNull("test connection was not set up correctly.", connection2);
+
+        // Simulates that connection1 is placed on HOLD.
+        connection1.setTelephonyConnectionOnHold();
+
+        verify(mPhone1).dial(anyString(), any(), any());
+        assertEquals(connection1.getState(), android.telecom.Connection.STATE_HOLDING);
+    }
+
+    // For 'Virtual DSDA' devices If the carrier config 'KEY_ALLOW_HOLD_CALL_DURING_EMERGENCY_BOOL'
+    // is explicitly configured false, an outgoing emergency call will disconnect all existing
+    // calls, across subscriptions.
+    @Test
+    @SmallTest
+    public void testEmergencyCallOnOtherSubDisconnectsExistingCallForVirtualDsdaDevice()
+            throws Exception {
+        setupForCallTest();
+        when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
+        doNothing().when(mContext).startActivity(any());
+
+        doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
+        getTestContext().getCarrierConfig(0 /*subId*/).putBoolean(
+                CarrierConfigManager.KEY_ALLOW_HOLD_CALL_DURING_EMERGENCY_BOOL, false);
+
+        mBinderStub.createConnection(PHONE_ACCOUNT_HANDLE_1, "TC@1",
+                new ConnectionRequest(PHONE_ACCOUNT_HANDLE_1, Uri.parse("tel:16505551212"),
+                        new Bundle()),
+                true, false, null);
+        waitForHandlerAction(mTestConnectionService.getHandler(), TIMEOUT_MS);
+        assertEquals(1, mTestConnectionService.getAllConnections().size());
+
+        TelephonyConnection connection1 = (TelephonyConnection)
+                mTestConnectionService.getAllConnections().toArray()[0];
+
+        // Simulates an outgoing emergency call.
+        TelephonyConnection connection2 = (TelephonyConnection) mTestConnectionService
+                .onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_2,
+                        createConnectionRequest(PHONE_ACCOUNT_HANDLE_2,
+                                TEST_EMERGENCY_NUMBER, "TC@2"));
+        assertNotNull("test connection was not set up correctly.", connection2);
+
+        verify(mPhone1).dial(anyString(), any(), any());
+        assertEquals(connection1.getState(), android.telecom.Connection.STATE_DISCONNECTED);
+    }
+
     /**
      * Verifies that TelephonyManager is used to determine whether a connection is Emergency when
      * creating an outgoing connection.
diff --git a/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
index 0821943..72162b8 100644
--- a/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
@@ -97,6 +97,7 @@
 import android.telephony.WwanSelectorCallback;
 import android.telephony.ims.ImsManager;
 import android.telephony.ims.ImsMmTelManager;
+import android.telephony.ims.ImsReasonInfo;
 import android.telephony.ims.ProvisioningManager;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.TestableLooper;
@@ -1268,7 +1269,7 @@
 
         setupForScanListTest(bundle);
 
-        verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false));
+        verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false, false));
     }
 
     @Test
@@ -1282,7 +1283,7 @@
 
         setupForScanListTest(bundle);
 
-        verifyPsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false));
+        verifyPsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false, false));
     }
 
     @Test
@@ -1297,7 +1298,7 @@
 
         setupForScanListTest(bundle);
 
-        verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(false, false));
+        verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(false, false, false));
     }
 
     @Test
@@ -1312,7 +1313,7 @@
 
         setupForScanListTest(bundle);
 
-        verifyCsOnlyScanList(mDomainSelector.getNextPreferredNetworks(false, false));
+        verifyCsOnlyScanList(mDomainSelector.getNextPreferredNetworks(false, false, false));
 
     }
 
@@ -1327,7 +1328,7 @@
 
         setupForScanListTest(bundle);
 
-        verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false));
+        verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false, false));
     }
 
     @Test
@@ -1341,7 +1342,7 @@
 
         setupForScanListTest(bundle);
 
-        verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false));
+        verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false, false));
     }
 
     @Test
@@ -1357,7 +1358,7 @@
 
         setupForScanListTest(bundle);
 
-        verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(true, false));
+        verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(true, false, false));
     }
 
     @Test
@@ -1372,7 +1373,7 @@
 
         setupForScanListTest(bundle);
 
-        verifyCsOnlyScanList(mDomainSelector.getNextPreferredNetworks(true, false));
+        verifyCsOnlyScanList(mDomainSelector.getNextPreferredNetworks(true, false, false));
     }
 
     @Test
@@ -1389,7 +1390,7 @@
         bindImsService();
         processAllMessages();
 
-        verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false));
+        verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false, false));
     }
 
     @Test
@@ -1406,7 +1407,7 @@
         bindImsService();
         processAllMessages();
 
-        verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false));
+        verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false, false));
     }
 
     @Test
@@ -1424,7 +1425,7 @@
         bindImsService();
         processAllMessages();
 
-        verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(false, false));
+        verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(false, false, false));
     }
 
     @Test
@@ -1441,7 +1442,7 @@
         bindImsService();
         processAllMessages();
 
-        verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false));
+        verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false, false));
     }
 
     @Test
@@ -1458,7 +1459,7 @@
         bindImsService();
         processAllMessages();
 
-        verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false));
+        verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false, false));
     }
 
     @Test
@@ -1477,7 +1478,7 @@
         bindImsService();
         processAllMessages();
 
-        verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(true, false));
+        verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(true, false, false));
     }
 
     @Test
@@ -1493,7 +1494,7 @@
 
         setupForScanListTest(bundle);
 
-        List<Integer> networks = mDomainSelector.getNextPreferredNetworks(false, true);
+        List<Integer> networks = mDomainSelector.getNextPreferredNetworks(false, true, false);
 
         assertFalse(networks.isEmpty());
         assertTrue(networks.contains(EUTRAN));
@@ -1648,6 +1649,36 @@
                 .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_TEMP_FAILURE));
     }
 
+    @Test
+    public void testDefaultEpsImsRegisteredSelectPsEmergencyRegFailed() throws Exception {
+        createSelector(SLOT_0_SUB_ID);
+        unsolBarringInfoChanged(false);
+
+        EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+                NetworkRegistrationInfo.DOMAIN_PS,
+                true, true, 0, 0, "", "");
+        SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+        mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+        processAllMessages();
+
+        bindImsService();
+
+        verifyPsDialed();
+
+        attr = new SelectionAttributes.Builder(SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+                .setEmergency(true)
+                .setEmergencyRegResult(regResult)
+                .setPsDisconnectCause(
+                        new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED, 0, null))
+                .build();
+        mDomainSelector.reselectDomain(attr);
+        processAllMessages();
+
+        verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+                any(), anyInt(), any(), any());
+        assertFalse(mAccessNetwork.contains(EUTRAN));
+    }
+
     private void setupForScanListTest(PersistableBundle bundle) throws Exception {
         setupForScanListTest(bundle, false);
     }