Remove protected broadcast from preferred tty mode am: b49a7d7b50

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/services/Telephony/+/12673457

Change-Id: If085a8750f9d9aecddcaa8cad9d44d7ec817514b
diff --git a/ecc/input/OWNERS b/ecc/input/OWNERS
new file mode 100644
index 0000000..d9ecbb7
--- /dev/null
+++ b/ecc/input/OWNERS
@@ -0,0 +1,5 @@
+set noparent
+
+djkrause@google.com
+satk@google.com
+somakala@google.com
\ No newline at end of file
diff --git a/ecc/output/OWNERS b/ecc/output/OWNERS
new file mode 100644
index 0000000..d9ecbb7
--- /dev/null
+++ b/ecc/output/OWNERS
@@ -0,0 +1,5 @@
+set noparent
+
+djkrause@google.com
+satk@google.com
+somakala@google.com
\ No newline at end of file
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index fcd4a20..b1982ea 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -471,7 +471,7 @@
     <string name="simContacts_emptyLoading" msgid="4989040293858675483">"‏جارٍ القراءة من شريحة SIM..."</string>
     <string name="simContacts_empty" msgid="1135632055473689521">"‏ليس هناك جهات اتصال على شريحة SIM."</string>
     <string name="simContacts_title" msgid="2714029230160136647">"حدد جهات اتصال لاستيرادها"</string>
-    <string name="simContacts_airplaneMode" msgid="4654884030631503808">"‏عليك إيقاف وضع الطائرة لاستيراد جهات الاتصال من شريحة SIM."</string>
+    <string name="simContacts_airplaneMode" msgid="4654884030631503808">"‏عليك إيقاف وضع الطيران لاستيراد جهات الاتصال من شريحة SIM."</string>
     <string name="enable_pin" msgid="967674051730845376">"‏تفعيل/إيقاف رمز PIN لبطاقة SIM"</string>
     <string name="change_pin" msgid="3657869530942905790">"‏تغيير رمز PIN لبطاقة SIM"</string>
     <string name="enter_pin_text" msgid="3182311451978663356">"‏رمز PIN لبطاقة SIM:"</string>
@@ -484,7 +484,7 @@
     <string name="disable_sim_pin" msgid="3112303905548613752">"‏محو رقم التعريف الشخصي لبطاقة SIM"</string>
     <string name="enable_sim_pin" msgid="445461050748318980">"‏تعيين رقم التعريف الشخصي لبطاقة SIM"</string>
     <string name="enable_in_progress" msgid="4135305985717272592">"جارٍ تعيين رقم التعريف الشخصي…"</string>
-    <string name="enable_pin_ok" msgid="2877428038280804256">"تم تعيين رقم التعريف الشخصي"</string>
+    <string name="enable_pin_ok" msgid="2877428038280804256">"تم ضبط رقم التعريف الشخصي"</string>
     <string name="disable_pin_ok" msgid="888505244389647754">"تم محو رقم التعريف الشخصي"</string>
     <string name="pin_failed" msgid="4527347792881939652">"رقم التعريف الشخصي غير صحيح"</string>
     <string name="pin_changed" msgid="7291153750090452808">"تم تحديث رقم التعريف الشخصي"</string>
@@ -522,9 +522,9 @@
     <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="default" msgid="8131672264311208673">"عليك إيقاف وضع الطائرة لإجراء مكالمة."</string>
-    <string name="incall_error_power_off_wfc" msgid="9125661184694727052">"عليك إيقاف وضع الطائرة أو الاتصال بشبكة لاسلكية لإجراء مكالمة."</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_ecm_emergency_only" msgid="5622379058883722080">"ينبغي الخروج من وضع معاودة الاتصال بالطوارئ لإجراء مكالمة غير طارئة."</string>
     <string name="incall_error_emergency_only" msgid="8786127461027964653">"غير مسجل على الشبكة."</string>
     <string name="incall_error_out_of_service" msgid="1927265196942672791">"شبكة الجوال غير متاحة."</string>
@@ -552,7 +552,7 @@
     <string name="emergency_call_shortcut_hint" msgid="1290485125107779500">"انقر مجددًا للاتصال بالرقم <xliff:g id="EMERGENCY_NUMBER">%s</xliff:g>"</string>
     <string name="emergency_enable_radio_dialog_message" msgid="1695305158151408629">"جارٍ تفعيل اللاسلكي..."</string>
     <string name="emergency_enable_radio_dialog_retry" msgid="4329131876852608587">"لا تتوفر خدمة. جارٍ إعادة المحاولة…"</string>
-    <string name="radio_off_during_emergency_call" msgid="8011154134040481609">"لا يمكن دخول وضع الطائرة أثناء إجراء مكالمة طوارئ."</string>
+    <string name="radio_off_during_emergency_call" msgid="8011154134040481609">"لا يمكن دخول وضع الطيران أثناء إجراء مكالمة طوارئ."</string>
     <string name="dial_emergency_error" msgid="825822413209026039">"يتعذر الاتصال. لا يعد <xliff:g id="NON_EMERGENCY_NUMBER">%s</xliff:g> رقم طوارئ."</string>
     <string name="dial_emergency_empty_error" msgid="2785803395047793634">"يتعذر الاتصال. يمكنك طلب رقم طوارئ."</string>
     <string name="dial_emergency_calling_not_available" msgid="6485846193794727823">"مكالمة الطوارئ غير متوفرة"</string>
@@ -719,7 +719,7 @@
     <string name="mobile_data_activate_button" msgid="1139792516354374612">"إضافة بيانات"</string>
     <string name="mobile_data_activate_cancel_button" msgid="3530174817572005860">"إلغاء"</string>
     <string name="clh_card_title_call_ended_txt" msgid="5977978317527299698">"تم إنهاء الاتصال"</string>
-    <string name="clh_callFailed_powerOff_txt" msgid="8279934912560765361">"تفعيل وضع الطائرة"</string>
+    <string name="clh_callFailed_powerOff_txt" msgid="8279934912560765361">"تفعيل وضع الطيران"</string>
     <string name="clh_callFailed_simError_txt" msgid="5128538525762326413">"‏تعذر الوصول إلى شريحة SIM"</string>
     <string name="clh_incall_error_out_of_service_txt" msgid="2736010617446749869">"شبكة الجوّال غير متوفرة"</string>
     <string name="clh_callFailed_unassigned_number_txt" msgid="141967660286695682">"حدثت مشكلة في رقم الهاتف الذي تحاول الاتصال به. رمز الخطأ 1."</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index e94fae3..72e9651 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -430,7 +430,7 @@
     <string name="manage_fdn_list" msgid="3341716430375195441">"Markatze finkoko zenbakien zerrenda"</string>
     <string name="fdn_list_with_label" msgid="1409655283510382556">"Markatze finkoko zenbakiak (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
     <string name="fdn_activation" msgid="2178637004710435895">"Markatze finkoko zenbakiaren aktibazioa"</string>
-    <string name="fdn_enabled" msgid="7017355494808056447">"Markatze finkoko zenbakiak gaituta daude"</string>
+    <string name="fdn_enabled" msgid="7017355494808056447">"Markatze finkoko zenbakiak gaituta"</string>
     <string name="fdn_disabled" msgid="6696468878037736600">"Markatze finkoko zenbakiak desgaituta daude"</string>
     <string name="enable_fdn" msgid="4830555730418033723">"Gaitu markatze finkoko zenbakiak"</string>
     <string name="disable_fdn" msgid="3918794950264647541">"Desgaitu markatze finkoko zenbakia"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 06af978..d6c23fb 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -464,9 +464,9 @@
     <string name="delete_fdn_contact" msgid="7027405651994507077">"Туруктуу терүү номерин жок кылуу"</string>
     <string name="deleting_fdn_contact" msgid="6872320570844460428">"Туруктуу терүү номери жок кылынууда…"</string>
     <string name="fdn_contact_deleted" msgid="1680714996763848838">"Туруктуу терүү номери өчүрүлдү."</string>
-    <string name="pin2_invalid" msgid="2313954262684494442">"БНТ жаңыртылган жок, анткени туура эмес PIN-код киргизилди."</string>
-    <string name="fdn_invalid_number" msgid="9067189814657840439">"Уруксат берилген номер жаңыртылган жок, себеби жазылган номердин саны <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g> ашпашы керек."</string>
-    <string name="pin2_or_fdn_invalid" msgid="7542639487955868181">"БНТ жаңыртылган жок. PIN2 туура эмес, же телефон номуру жараксыз."</string>
+    <string name="pin2_invalid" msgid="2313954262684494442">"БНТ жаңырган жок, анткени туура эмес PIN-код киргизилди."</string>
+    <string name="fdn_invalid_number" msgid="9067189814657840439">"Уруксат берилген номер жаңырган жок, себеби жазылган номердин саны <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g> ашпашы керек."</string>
+    <string name="pin2_or_fdn_invalid" msgid="7542639487955868181">"БНТ жаңырган жок. PIN2 туура эмес, же телефон номуру жараксыз."</string>
     <string name="fdn_failed" msgid="216592346853420250">"БНТ иши кыйрады."</string>
     <string name="simContacts_emptyLoading" msgid="4989040293858675483">"SIM-картадан окулууда…"</string>
     <string name="simContacts_empty" msgid="1135632055473689521">"SIM картаңызда байланыштар жок."</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index f65f539..ec05b1b 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -648,7 +648,7 @@
     <string name="voicemail_number_not_set" msgid="8831561283386938155">"सेट गरेको छैन"</string>
     <string name="other_settings" msgid="8895088007393598447">"अन्य कल सेटिङहरू"</string>
     <string name="calling_via_template" msgid="1791323450703751750">"<xliff:g id="PROVIDER_NAME">%s</xliff:g> को मार्फत कल गर्दै"</string>
-    <string name="contactPhoto" msgid="7885089213135154834">"सम्पर्क तस्बिर"</string>
+    <string name="contactPhoto" msgid="7885089213135154834">"सम्पर्क फोटो"</string>
     <string name="goPrivate" msgid="4645108311382209551">"निजी जानुहोस्"</string>
     <string name="selectContact" msgid="1527612842599767382">"सम्पर्क चयन गर्नुहोस्"</string>
     <string name="not_voice_capable" msgid="2819996734252084253">"भ्वाइस कल गर्ने समर्थित छैन"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index e5b958f..9f7ab07 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -506,7 +506,7 @@
     <string name="pin2_attempts" msgid="5625178102026453023">\n"Je hebt nog <xliff:g id="NUMBER">%d</xliff:g> pogingen."</string>
     <string name="pin2_unblocked" msgid="4481107908727789303">"PIN2 niet langer geblokkeerd"</string>
     <string name="pin2_error_exception" msgid="8116103864600823641">"Netwerk- of simkaartfout"</string>
-    <string name="doneButton" msgid="7371209609238460207">"Gereed"</string>
+    <string name="doneButton" msgid="7371209609238460207">"Klaar"</string>
     <string name="voicemail_settings_number_label" msgid="1265118640154688162">"Voicemailnummer"</string>
     <string name="card_title_dialing" msgid="8742182654254431781">"Kiezen"</string>
     <string name="card_title_redialing" msgid="18130232613559964">"Opnieuw bellen"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index d4c5aa9..585f332 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -22,7 +22,7 @@
     <string name="phoneIconLabel" msgid="3015941229249651419">"電話"</string>
     <string name="fdnListLabel" msgid="4119121875004244097">"固定撥號清單"</string>
     <string name="unknown" msgid="8279698889921830815">"不明"</string>
-    <string name="private_num" msgid="4487990167889159992">"私人號碼"</string>
+    <string name="private_num" msgid="4487990167889159992">"隱藏號碼"</string>
     <string name="payphone" msgid="7936735771836716941">"公用電話"</string>
     <string name="onHold" msgid="6132725550015899006">"通話保留"</string>
     <string name="carrier_mmi_msg_title" msgid="6050165242447507034">"「<xliff:g id="MMICARRIER">%s</xliff:g>」的訊息"</string>
diff --git a/sip/res/values-sq/strings.xml b/sip/res/values-sq/strings.xml
index 1b83380..5c50085 100644
--- a/sip/res/values-sq/strings.xml
+++ b/sip/res/values-sq/strings.xml
@@ -32,7 +32,7 @@
     <string name="saving_account" msgid="3390358043846687266">"Po ruan llogarinë…"</string>
     <string name="removing_account" msgid="1544132880414780408">"Po heq llogarinë…"</string>
     <string name="sip_menu_save" msgid="4377112554203123060">"Ruaj"</string>
-    <string name="sip_menu_discard" msgid="1883166691772895243">"Injoro"</string>
+    <string name="sip_menu_discard" msgid="1883166691772895243">"Hiq"</string>
     <string name="alert_dialog_close" msgid="1734746505531110706">"Mbyll profilin"</string>
     <string name="alert_dialog_ok" msgid="7806760618798687406">"Në rregull"</string>
     <string name="close_profile" msgid="3756064641769751774">"Mbyll"</string>
diff --git a/src/com/android/phone/CallBarringEditPreference.java b/src/com/android/phone/CallBarringEditPreference.java
index b8e3250..757600e 100644
--- a/src/com/android/phone/CallBarringEditPreference.java
+++ b/src/com/android/phone/CallBarringEditPreference.java
@@ -26,6 +26,8 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
 import android.text.method.DigitsKeyListener;
 import android.text.method.PasswordTransformationMethod;
 import android.util.AttributeSet;
@@ -35,7 +37,6 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
-import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
@@ -109,7 +110,7 @@
         if (!skipReading) {
             // Query call barring status
             mPhone.getCallBarring(mFacility, "", mHandler.obtainMessage(
-                    MyHandler.MESSAGE_GET_CALL_BARRING), CommandsInterface.SERVICE_CLASS_VOICE);
+                    MyHandler.MESSAGE_GET_CALL_BARRING), getServiceClassForCallBarring(mPhone));
             if (mTcpListener != null) {
                 mTcpListener.onStarted(this, true);
             }
@@ -204,7 +205,7 @@
             // Send set call barring message to RIL layer.
             mPhone.setCallBarring(mFacility, !mIsActivated, password,
                     mHandler.obtainMessage(MyHandler.MESSAGE_SET_CALL_BARRING),
-                    CommandsInterface.SERVICE_CLASS_VOICE);
+                    getServiceClassForCallBarring(mPhone));
             if (mTcpListener != null) {
                 mTcpListener.onStarted(this, false);
             }
@@ -218,6 +219,18 @@
         }
     }
 
+    private static int getServiceClassForCallBarring(Phone phone) {
+        int serviceClass = CarrierConfigManager.SERVICE_CLASS_VOICE;
+        PersistableBundle carrierConfig = PhoneGlobals.getInstance()
+                .getCarrierConfigForSubId(phone.getSubId());
+        if (carrierConfig != null) {
+            serviceClass = carrierConfig.getInt(
+                    CarrierConfigManager.KEY_CALL_BARRING_DEFAULT_SERVICE_CLASS_INT,
+                    CarrierConfigManager.SERVICE_CLASS_VOICE);
+        }
+        return serviceClass;
+    }
+
     void updateSummaryText() {
         notifyChanged();
         notifyDependencyChange(shouldDisableDependents());
@@ -327,8 +340,7 @@
                     pref.mFacility,
                     "",
                     obtainMessage(MESSAGE_GET_CALL_BARRING, 0, MESSAGE_SET_CALL_BARRING,
-                            ar.exception),
-                    CommandsInterface.SERVICE_CLASS_VOICE);
+                            ar.exception), getServiceClassForCallBarring(pref.mPhone));
         }
     }
 }
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 866e481..37a0618 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -99,10 +99,16 @@
     private PersistableBundle[] mPersistentOverrideConfigs;
     // Carrier configs that are provided via the override test API, indexed by phone ID.
     private PersistableBundle[] mOverrideConfigs;
+    // Carrier configs to override code default when there is no SIM inserted
+    private PersistableBundle mNoSimConfig;
     // Service connection for binding to config app.
     private CarrierServiceConnection[] mServiceConnection;
+    // Service connection for binding to carrier config app for no SIM config.
+    private CarrierServiceConnection[] mServiceConnectionForNoSimConfig;
     // Whether we are bound to a service for each phone
     private boolean[] mServiceBound;
+    // Whether we are bound to a service for no SIM config
+    private boolean[] mServiceBoundForNoSimConfig;
     // Whether we have sent config change broadcast for each phone id.
     private boolean[] mHasSentConfigChange;
     // Whether the broadcast was sent from EVENT_SYSTEM_UNLOCKED, to track rebroadcasts
@@ -150,6 +156,16 @@
     private static final int EVENT_SUBSCRIPTION_INFO_UPDATED = 16;
     // Multi-SIM config changed.
     private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 17;
+    // Attempt to fetch from default app or read from XML for no SIM case.
+    private static final int EVENT_DO_FETCH_DEFAULT_FOR_NO_SIM_CONFIG = 18;
+    // No SIM config has been loaded from default app (or cache).
+    private static final int EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_DONE = 19;
+    // Has connected to default app for no SIM config.
+    private static final int EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG = 20;
+    // Bind timed out for the default app when trying to fetch no SIM config.
+    private static final int EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT = 21;
+    // Fetching config timed out from the default app for no SIM config.
+    private static final int EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT = 22;
 
     private static final int BIND_TIMEOUT_MILLIS = 30000;
 
@@ -505,6 +521,118 @@
                 case EVENT_MULTI_SIM_CONFIG_CHANGED:
                     onMultiSimConfigChanged();
                     break;
+
+                case EVENT_DO_FETCH_DEFAULT_FOR_NO_SIM_CONFIG: {
+                    PersistableBundle config =
+                            restoreNoSimConfigFromXml(mPlatformCarrierConfigPackage);
+
+                    if (config != null) {
+                        logd("Loaded no SIM config from XML. package="
+                                + mPlatformCarrierConfigPackage);
+                        mNoSimConfig = config;
+                        sendMessage(
+                                obtainMessage(
+                                        EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_DONE,
+                                            phoneId, -1));
+                    } else {
+                        // No cached config, so fetch it from the default app.
+                        if (bindToConfigPackage(
+                                mPlatformCarrierConfigPackage,
+                                phoneId,
+                                EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG)) {
+                            sendMessageDelayed(
+                                    obtainMessage(
+                                            EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT,
+                                                phoneId, -1), BIND_TIMEOUT_MILLIS);
+                        } else {
+                            broadcastConfigChangedIntent(phoneId, false);
+                            // TODO: We *must* call unbindService even if bindService returns false.
+                            // (And possibly if SecurityException was thrown.)
+                            loge("binding to default app to fetch no SIM config: "
+                                    + mPlatformCarrierConfigPackage + " fails");
+                        }
+                    }
+                    break;
+                }
+
+                case EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_DONE: {
+                    broadcastConfigChangedIntent(phoneId, false);
+                    break;
+                }
+
+                case EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT:
+                case EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT: {
+                    loge("Bind/fetch time out for no SIM config from "
+                            + mPlatformCarrierConfigPackage);
+                    removeMessages(EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_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 (mServiceConnectionForNoSimConfig[phoneId] != null) {
+                        // If a ResponseReceiver callback is in the queue when this happens, we will
+                        // unbind twice and throw an exception.
+                        unbindIfBoundForNoSimConfig(mContext,
+                                mServiceConnectionForNoSimConfig[phoneId], phoneId);
+                    }
+                    broadcastConfigChangedIntent(phoneId, false);
+                    break;
+                }
+
+                case EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG: {
+                    removeMessages(EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT);
+                    final CarrierServiceConnection conn = (CarrierServiceConnection) msg.obj;
+                    // If new service connection has been created, unbind.
+                    if (mServiceConnectionForNoSimConfig[phoneId] != conn || conn.service == null) {
+                        unbindIfBoundForNoSimConfig(mContext, conn, phoneId);
+                        break;
+                    }
+
+                    // ResultReceiver callback will execute in this Handler's thread.
+                    final ResultReceiver resultReceiver =
+                            new ResultReceiver(this) {
+                                @Override
+                                public void onReceiveResult(int resultCode, Bundle resultData) {
+                                    unbindIfBoundForNoSimConfig(mContext, conn, phoneId);
+                                    // If new service connection has been created, this is stale.
+                                    if (mServiceConnectionForNoSimConfig[phoneId] != conn) {
+                                        loge("Received response for stale request.");
+                                        return;
+                                    }
+                                    removeMessages(EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT);
+                                    if (resultCode == RESULT_ERROR || resultData == null) {
+                                        // On error, abort config fetching.
+                                        loge("Failed to get no SIM carrier config");
+                                        return;
+                                    }
+                                    PersistableBundle config =
+                                            resultData.getParcelable(KEY_CONFIG_BUNDLE);
+                                    saveNoSimConfigToXml(mPlatformCarrierConfigPackage, config);
+                                    mNoSimConfig = config;
+                                    sendMessage(
+                                            obtainMessage(
+                                                    EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_DONE,
+                                                        phoneId, -1));
+                                }
+                            };
+                    // Now fetch the config asynchronously from the ICarrierService.
+                    try {
+                        ICarrierService carrierService =
+                                ICarrierService.Stub.asInterface(conn.service);
+                        carrierService.getCarrierConfig(null, resultReceiver);
+                        logdWithLocalLog("Fetch no sim config from default app: "
+                                + mPlatformCarrierConfigPackage);
+                    } catch (RemoteException e) {
+                        loge("Failed to get no sim carrier config from default app: " +
+                                mPlatformCarrierConfigPackage + " err: " + e.toString());
+                        unbindIfBoundForNoSimConfig(mContext, conn, phoneId);
+                        break; // So we don't set a timeout.
+                    }
+                    sendMessageDelayed(
+                            obtainMessage(
+                                    EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT,
+                                        phoneId, -1), BIND_TIMEOUT_MILLIS);
+                    break;
+                }
             }
         }
     }
@@ -539,10 +667,13 @@
         mConfigFromCarrierApp = new PersistableBundle[numPhones];
         mPersistentOverrideConfigs = new PersistableBundle[numPhones];
         mOverrideConfigs = new PersistableBundle[numPhones];
+        mNoSimConfig = new PersistableBundle();
         mServiceConnection = new CarrierServiceConnection[numPhones];
         mServiceBound = new boolean[numPhones];
         mHasSentConfigChange = new boolean[numPhones];
         mFromSystemUnlocked = new boolean[numPhones];
+        mServiceConnectionForNoSimConfig = new CarrierServiceConnection[numPhones];
+        mServiceBoundForNoSimConfig = new boolean[numPhones];
         // Make this service available through ServiceManager.
         TelephonyFrameworkInitializer
                 .getTelephonyServiceManager().getCarrierConfigServiceRegisterer().register(this);
@@ -568,7 +699,7 @@
         }
     }
 
-    private void clearConfigForPhone(int phoneId, boolean sendBroadcast) {
+    private void clearConfigForPhone(int phoneId, boolean fetchNoSimConfig) {
         /* Ignore clear configuration request if device is being shutdown. */
         Phone phone = PhoneFactory.getPhone(phoneId);
         if (phone != null) {
@@ -582,7 +713,12 @@
         mServiceConnection[phoneId] = null;
         mHasSentConfigChange[phoneId] = false;
 
-        if (sendBroadcast) broadcastConfigChangedIntent(phoneId, false);
+        if (fetchNoSimConfig) {
+            // To fetch no SIM config
+            mHandler.sendMessage(
+                    mHandler.obtainMessage(
+                            EVENT_DO_FETCH_DEFAULT_FOR_NO_SIM_CONFIG, phoneId, -1));
+        }
     }
 
     private void notifySubscriptionInfoUpdater(int phoneId) {
@@ -661,11 +797,21 @@
         logdWithLocalLog("Binding to " + pkgName + " for phone " + phoneId);
         Intent carrierService = new Intent(CarrierService.CARRIER_SERVICE_INTERFACE);
         carrierService.setPackage(pkgName);
-        mServiceConnection[phoneId] = new CarrierServiceConnection(phoneId, pkgName, eventId);
+        CarrierServiceConnection serviceConnection =  new CarrierServiceConnection(
+                phoneId, pkgName, eventId);
+        if (eventId == EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG) {
+            mServiceConnectionForNoSimConfig[phoneId] = serviceConnection;
+        } else {
+            mServiceConnection[phoneId] = serviceConnection;
+        }
         try {
-            if (mContext.bindService(carrierService, mServiceConnection[phoneId],
+            if (mContext.bindService(carrierService, serviceConnection,
                     Context.BIND_AUTO_CREATE)) {
-                mServiceBound[phoneId] = true;
+                if (eventId == EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG) {
+                    mServiceBoundForNoSimConfig[phoneId] = true;
+                } else {
+                    mServiceBound[phoneId] = true;
+                }
                 return true;
             } else {
                 return false;
@@ -767,26 +913,39 @@
      *
      * In case of errors or invalid input, no file will be written.
      *
-     * @param packageName the name of the package from which we fetched this bundle.
-     * @param extraString An extra string to be used in the XML file name.
-     * @param phoneId     the phone ID.
-     * @param carrierId   contains all carrier-identifying information.
-     * @param config      the bundle to be written. Null will be treated as an empty bundle.
+     * @param packageName   the name of the package from which we fetched this bundle.
+     * @param extraString   An extra string to be used in the XML file name.
+     * @param phoneId       the phone ID.
+     * @param carrierId     contains all carrier-identifying information.
+     * @param config        the bundle to be written. Null will be treated as an empty bundle.
+     * @param isNoSimConfig whether this is invoked for noSimConfig or not.
      */
     private void saveConfigToXml(String packageName, @NonNull String extraString, int phoneId,
-            CarrierIdentifier carrierId, PersistableBundle config) {
-        if (SubscriptionManager.getSimStateForSlotIndex(phoneId)
-                != TelephonyManager.SIM_STATE_LOADED) {
-            loge("Skip save config because SIM records are not loaded.");
+            CarrierIdentifier carrierId, PersistableBundle config, boolean isNoSimConfig) {
+        if (packageName == null) {
+            loge("Cannot save config with null packageName");
             return;
         }
 
-        final String iccid = getIccIdForPhoneId(phoneId);
-        final int cid = carrierId.getSpecificCarrierId();
-        if (packageName == null || iccid == null) {
-            loge("Cannot save config with null packageName or iccid.");
-            return;
+        String fileName;
+        if (isNoSimConfig) {
+            fileName = getFilenameForNoSimConfig(packageName);
+        } else {
+            if (SubscriptionManager.getSimStateForSlotIndex(phoneId)
+                    != TelephonyManager.SIM_STATE_LOADED) {
+                loge("Skip save config because SIM records are not loaded.");
+                return;
+            }
+
+            final String iccid = getIccIdForPhoneId(phoneId);
+            final int cid = carrierId.getSpecificCarrierId();
+            if (iccid == null) {
+                loge("Cannot save config with null iccid.");
+                return;
+            }
+            fileName = getFilenameForConfig(packageName, extraString, iccid, cid);
         }
+
         // b/32668103 Only save to file if config isn't empty.
         // In case of failure, not caching an empty bundle will
         // try loading config again on next power on or sim loaded.
@@ -807,9 +966,7 @@
 
         FileOutputStream outFile = null;
         try {
-            outFile = new FileOutputStream(
-                    new File(mContext.getFilesDir(),
-                            getFilenameForConfig(packageName, extraString, iccid, cid)));
+            outFile = new FileOutputStream(new File(mContext.getFilesDir(), fileName));
             config.putString(KEY_VERSION, version);
             config.writeToStream(outFile);
             outFile.flush();
@@ -819,6 +976,15 @@
         }
     }
 
+    private void saveConfigToXml(String packageName, @NonNull String extraString, int phoneId,
+            CarrierIdentifier carrierId, PersistableBundle config) {
+        saveConfigToXml(packageName, extraString, phoneId, carrierId, config, false);
+    }
+
+    private void saveNoSimConfigToXml(String packageName, PersistableBundle config) {
+        saveConfigToXml(packageName, "", -1, null, config, true);
+    }
+
     /**
      * Reads a bundle from an XML file.
      *
@@ -828,38 +994,48 @@
      * In case of errors, or if the saved config is from a different package version than the
      * current version, then null will be returned.
      *
-     * @param packageName the name of the package from which we fetched this bundle.
-     * @param extraString An extra string to be used in the XML file name.
-     * @param phoneId     the phone ID.
+     * @param packageName    the name of the package from which we fetched this bundle.
+     * @param extraString    An extra string to be used in the XML file name.
+     * @param phoneId        the phone ID.
+     * @param isNoSimConfig  whether this is invoked for noSimConfig or not.
      * @return the bundle from the XML file. Returns null if there is no saved config, the saved
      * version does not match, or reading config fails.
      */
     private PersistableBundle restoreConfigFromXml(String packageName, @NonNull String extraString,
-            int phoneId) {
+            int phoneId, boolean isNoSimConfig) {
+        if (packageName == null) {
+            loge("Cannot restore config with null packageName");
+        }
         final String version = getPackageVersion(packageName);
         if (version == null) {
             loge("Failed to get package version for: " + packageName);
             return null;
         }
-        if (SubscriptionManager.getSimStateForSlotIndex(phoneId)
-                != TelephonyManager.SIM_STATE_LOADED) {
-            loge("Skip restoring config because SIM records are not yet loaded.");
-            return null;
-        }
 
-        final String iccid = getIccIdForPhoneId(phoneId);
-        final int cid = getSpecificCarrierIdForPhoneId(phoneId);
-        if (packageName == null || iccid == null) {
-            loge("Cannot restore config with null packageName or iccid.");
-            return null;
+        String fileName;
+        if (isNoSimConfig) {
+            fileName = getFilenameForNoSimConfig(packageName);
+        } else {
+            if (SubscriptionManager.getSimStateForSlotIndex(phoneId)
+                    != TelephonyManager.SIM_STATE_LOADED) {
+                loge("Skip restore config because SIM records are not loaded.");
+                return null;
+            }
+
+            final String iccid = getIccIdForPhoneId(phoneId);
+            final int cid = getSpecificCarrierIdForPhoneId(phoneId);
+            if (iccid == null) {
+                loge("Cannot restore config with null iccid.");
+                return null;
+            }
+            fileName = getFilenameForConfig(packageName, extraString, iccid, cid);
         }
 
         PersistableBundle restoredBundle = null;
         File file = null;
         FileInputStream inFile = null;
         try {
-            file = new File(mContext.getFilesDir(),
-                    getFilenameForConfig(packageName, extraString, iccid, cid));
+            file = new File(mContext.getFilesDir(),fileName);
             inFile = new FileInputStream(file);
 
             restoredBundle = PersistableBundle.readFromStream(inFile);
@@ -883,6 +1059,15 @@
         return restoredBundle;
     }
 
+    private PersistableBundle restoreConfigFromXml(String packageName, @NonNull String extraString,
+            int phoneId) {
+        return restoreConfigFromXml(packageName, extraString, phoneId, false);
+    }
+
+    private PersistableBundle restoreNoSimConfigFromXml(String packageName) {
+        return restoreConfigFromXml(packageName, "", -1, true);
+    }
+
     /**
      * Clears cached carrier config.
      * This deletes all saved XML files associated with the given package name. If packageName is
@@ -912,7 +1097,8 @@
     }
 
     /** Builds a canonical file name for a config file. */
-    private String getFilenameForConfig(@NonNull String packageName, @NonNull String extraString,
+    private static String getFilenameForConfig(
+            @NonNull String packageName, @NonNull String extraString,
             @NonNull String iccid, int cid) {
         // the same carrier should have a single copy of XML file named after carrier id.
         // However, it's still possible that platform doesn't recognize the current sim carrier,
@@ -921,6 +1107,11 @@
         return "carrierconfig-" + packageName + extraString + "-" + iccid + "-" + cid + ".xml";
     }
 
+    /** Builds a canonical file name for no SIM config file. */
+    private String getFilenameForNoSimConfig(@NonNull String packageName) {
+        return "carrierconfig-" + packageName + "-" + "nosim" + ".xml";
+    }
+
     /** Return the current version code of a package, or null if the name is not found. */
     private String getPackageVersion(String packageName) {
         try {
@@ -995,6 +1186,10 @@
             if (config != null) {
                 retConfig.putAll(config);
             }
+        } else {
+            if (mNoSimConfig != null) {
+                retConfig.putAll(mNoSimConfig);
+            }
         }
         return retConfig;
     }
@@ -1104,6 +1299,14 @@
         }
     }
 
+    private void unbindIfBoundForNoSimConfig(Context context, CarrierServiceConnection conn,
+            int phoneId) {
+        if (mServiceBoundForNoSimConfig[phoneId]) {
+            mServiceBoundForNoSimConfig[phoneId] = false;
+            context.unbindService(conn);
+        }
+    }
+
     /**
      * If {@code args} contains {@link #DUMP_ARG_REQUESTING_PACKAGE} and a following package name,
      * we'll also call {@link IBinder#dump} on the default carrier service (if bound) and the
@@ -1144,6 +1347,7 @@
             printConfig(mOverrideConfigs[i], indentPW, "mOverrideConfigs");
         }
 
+        printConfig(mNoSimConfig, indentPW, "mNoSimConfig");
         indentPW.println("CarrierConfigLoadingLog=");
         mCarrierConfigLoadingLog.dump(fd, indentPW, args);
 
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 8f987b7..be1872f 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -120,6 +120,7 @@
     private static final int EVENT_RESTART_SIP = 14;
     private static final int EVENT_DATA_ROAMING_SETTINGS_CHANGED = 15;
     private static final int EVENT_MOBILE_DATA_SETTINGS_CHANGED = 16;
+    private static final int EVENT_CARRIER_CONFIG_CHANGED = 17;
 
     // The MMI codes are also used by the InCallScreen.
     public static final int MMI_INITIATE = 51;
@@ -303,6 +304,12 @@
                 case EVENT_MOBILE_DATA_SETTINGS_CHANGED:
                     updateDataRoamingStatus();
                     break;
+                case EVENT_CARRIER_CONFIG_CHANGED:
+                    int subId = (Integer) msg.obj;
+                    // The voicemail number could be overridden by carrier config, so need to
+                    // refresh the message waiting (voicemail) indicator.
+                    refreshMwiIndicator(subId);
+                    break;
             }
         }
     };
@@ -708,6 +715,12 @@
                 if (VDBG) Log.v(LOG_TAG, "carrier config changed.");
                 updateDataRoamingStatus();
                 updateLimitedSimFunctionForDualSim();
+                int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
+                        SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+                if (SubscriptionManager.isValidSubscriptionId(subId)) {
+                    mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARRIER_CONFIG_CHANGED,
+                            new Integer(subId)));
+                }
             } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
                 // We also need to pay attention when default data subscription changes.
                 if (VDBG) Log.v(LOG_TAG, "default data sub changed.");
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 5dd568c..865f59b 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -5532,11 +5532,13 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            Settings.Global.putInt(mApp.getContentResolver(),
-                    Settings.Global.PREFERRED_NETWORK_MODE + subId, networkType);
-
             Boolean success = (Boolean) sendRequest(
                     CMD_SET_PREFERRED_NETWORK_TYPE, networkType, subId);
+
+            if (success) {
+                Settings.Global.putInt(mApp.getContentResolver(),
+                        Settings.Global.PREFERRED_NETWORK_MODE + subId, networkType);
+            }
             if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
             return success;
         } finally {
@@ -6326,6 +6328,14 @@
     @Override
     public int getRadioAccessFamily(int phoneId, String callingPackage) {
         Phone phone = PhoneFactory.getPhone(phoneId);
+        try {
+            TelephonyPermissions
+                    .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+                            mApp, phone.getSubId(), "getRadioAccessFamily");
+        } catch (SecurityException e) {
+            EventLog.writeEvent(0x534e4554, "150857259", -1, "Missing Permission");
+            throw e;
+        }
         int raf = RadioAccessFamily.RAF_UNKNOWN;
         if (phone == null) {
             return raf;
@@ -6811,6 +6821,13 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
+            // isActiveSubId requires READ_PHONE_STATE, which we already check for above
+            if (!mSubscriptionController.isActiveSubId(subId, callingPackage, callingFeatureId)) {
+                Rlog.d(LOG_TAG,
+                        "getServiceStateForSubscriber returning null for inactive subId=" + subId);
+                return null;
+            }
+
             final Phone phone = getPhone(subId);
             if (phone == null) {
                 return null;
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 0348389..d24b4e3 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -22,14 +22,16 @@
 import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.RemoteException;
+import android.provider.BlockedNumberContract;
 import android.telephony.CarrierConfigManager;
-import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.feature.ImsFeature;
 import android.util.Log;
 
 import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
 import com.android.internal.telephony.util.TelephonyUtils;
 
@@ -56,6 +58,7 @@
     private static final String IMS_SUBCOMMAND = "ims";
     private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
     private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
+    private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
     private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
     private static final String DATA_TEST_MODE = "data";
     private static final String DATA_ENABLE = "enable";
@@ -82,6 +85,7 @@
 
     private SubscriptionManager mSubscriptionManager;
     private CarrierConfigManager mCarrierConfigManager;
+    private Context mContext;
 
     private enum CcType {
         BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
@@ -132,6 +136,7 @@
                 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
         mSubscriptionManager = (SubscriptionManager)
                 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+        mContext = context;
     }
 
     @Override
@@ -153,6 +158,8 @@
             }
             case DATA_TEST_MODE:
                 return handleDataTestModeCommand();
+            case END_BLOCK_SUPPRESSION:
+                return handleEndBlockSuppressionCommand();
             default: {
                 return handleDefaultCommands(cmd);
             }
@@ -169,12 +176,15 @@
         pw.println("    IMS Commands.");
         pw.println("  emergency-number-test-mode");
         pw.println("    Emergency Number Test Mode Commands.");
+        pw.println("  end-block-suppression");
+        pw.println("    End Block Suppression command.");
         pw.println("  data");
         pw.println("    Data Test Mode Commands.");
         pw.println("  cc");
         pw.println("    Carrier Config Commands.");
         onHelpIms();
         onHelpEmergencyNumber();
+        onHelpEndBlockSupperssion();
         onHelpDataTestMode();
         onHelpCc();
     }
@@ -242,6 +252,13 @@
         pw.println("      -p: get the full emergency number list in the test mode.");
     }
 
+    private void onHelpEndBlockSupperssion() {
+        PrintWriter pw = getOutPrintWriter();
+        pw.println("End Block Suppression command:");
+        pw.println("  end-block-suppression: disable suppressing blocking by contact");
+        pw.println("                         with emergency services.");
+    }
+
     private void onHelpCc() {
         PrintWriter pw = getOutPrintWriter();
         pw.println("Carrier Config Commands:");
@@ -723,17 +740,21 @@
         try {
             slotId = Integer.parseInt(slotString);
         } catch (NumberFormatException e) {
+            getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
+            return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        }
+
+        if (!SubscriptionManager.isValidPhoneId(slotId)) {
             getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
             return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
         }
 
-        SubscriptionInfo subInfo =
-                mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(slotId);
-        if (subInfo == null) {
+        Phone phone = PhoneFactory.getPhone(slotId);
+        if (phone == null) {
             getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
             return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
         }
-        return subInfo.getSubscriptionId();
+        return phone.getSubId();
     }
 
     private boolean checkShellUid() {
@@ -1169,4 +1190,15 @@
         }
         return bundle;
     }
+
+    private int handleEndBlockSuppressionCommand() {
+        if (!checkShellUid()) {
+            return -1;
+        }
+
+        if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
+            BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
+        }
+        return 0;
+    }
 }
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 816348a..76cdd53 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -268,7 +268,7 @@
 
                 @Override
                 public void onExtrasChanged(Connection c, Bundle extras) {
-                    Log.v(this, "onExtrasChanged: c=" + c + " Extras=" + extras);
+                    Log.v(this, "onExtrasChanged: c=" + c + " Extras=" + Rlog.pii(LOG_TAG, extras));
                     updateExtras(extras);
                 }
 
@@ -438,6 +438,7 @@
 
         mTelephonyConnectionService = telephonyConnectionService;
         setConferenceHost(conferenceHost);
+        setVideoProvider(conferenceHost, conferenceHost.getVideoProvider());
 
         int capabilities = Connection.CAPABILITY_MUTE |
                 Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN;
diff --git a/src/com/android/services/telephony/ImsConferenceController.java b/src/com/android/services/telephony/ImsConferenceController.java
index 6d3d4c2..7cf9415 100644
--- a/src/com/android/services/telephony/ImsConferenceController.java
+++ b/src/com/android/services/telephony/ImsConferenceController.java
@@ -403,6 +403,20 @@
         conferenceHostConnection.setVideoPauseSupported(connection.getVideoPauseSupported());
         conferenceHostConnection.setManageImsConferenceCallSupported(
                 connection.isManageImsConferenceCallSupported());
+        // WARNING: do not try to copy the video provider from connection to
+        // conferenceHostConnection here.  In connection.cloneConnection, part of the clone
+        // process is to set the original connection so it's already set:
+        // conferenceHostConnection.setVideoProvider(connection.getVideoProvider());
+        // There is a subtle concurrency issue here where at the time of merge, the
+        // TelephonyConnection potentially has the WRONG video provider set on it (compared to
+        // the ImsPhoneConnection (ie original connection) which has the correct one.
+        // If you follow the logic in ImsPhoneCallTracker#onCallMerged through, what happens is the
+        // new post-merge video provider is set on the ImsPhoneConnection.  That informs it's
+        // listeners (e.g. TelephonyConnection) via a handler.  We immediately change the multiparty
+        // start of the host connection and ImsPhoneCallTracker starts the setup we are
+        // performing here.  When cloning TelephonyConnection, we get the right VideoProvider
+        // because it is copied from the originalConnection, not using the potentially stale value
+        // in the TelephonyConnection.
 
         PhoneAccountHandle phoneAccountHandle = null;
 
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 356407a..9ee117d 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -1535,10 +1535,17 @@
         if (phone == null || TextUtils.isEmpty(number) || !phone.getServiceState().getRoaming()) {
             return false;
         }
+        boolean allowPrefixIms = true;
         String[] blockPrefixes = null;
         CarrierConfigManager cfgManager = (CarrierConfigManager)
                 phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
         if (cfgManager != null) {
+            allowPrefixIms = cfgManager.getConfigForSubId(phone.getSubId()).getBoolean(
+                    CarrierConfigManager.KEY_SUPPORT_IMS_CALL_FORWARDING_WHILE_ROAMING_BOOL,
+                    true);
+            if (allowPrefixIms && useImsForAudioOnlyCall(phone)) {
+                return false;
+            }
             blockPrefixes = cfgManager.getConfigForSubId(phone.getSubId()).getStringArray(
                     CarrierConfigManager.KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY);
         }
@@ -1553,6 +1560,14 @@
         return false;
     }
 
+    private boolean useImsForAudioOnlyCall(Phone phone) {
+        Phone imsPhone = phone.getImsPhone();
+
+        return imsPhone != null
+                && (imsPhone.isVolteEnabled() || imsPhone.isWifiCallingEnabled())
+                && (imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE);
+    }
+
     private boolean isRadioOn() {
         boolean result = false;
         for (Phone phone : mPhoneFactoryProxy.getPhones()) {