Merge "Check for null call id in ConnectionServiceWrapper"
diff --git a/res/raw/InCallQualityNotification.ogg b/res/raw/InCallQualityNotification.ogg
new file mode 100644
index 0000000..84c029a
--- /dev/null
+++ b/res/raw/InCallQualityNotification.ogg
Binary files differ
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index d79343f..53817b3 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -16,7 +16,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="telecommAppLabel" product="default" msgid="3077225713817780583">"Zənglərin İdarə Olunması"</string>
+    <string name="telecommAppLabel" product="default" msgid="3077225713817780583">"Zənglərin idarəolunması"</string>
     <string name="userCallActivityLabel" product="default" msgid="3605391260292846248">"Telefon"</string>
     <string name="unknown" msgid="6993977514360123431">"Naməlum"</string>
     <string name="notification_missedCallTitle" msgid="5060387047205532974">"Buraxılmış zəng"</string>
@@ -96,16 +96,16 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="8243532328969433172">"Başqa bir tətbiqdəki zəng səbəbilə çağrı edilə bilməz."</string>
     <string name="notification_channel_incoming_call" msgid="5245550964701715662">"Gələn zənglər"</string>
     <string name="notification_channel_missed_call" msgid="7168893015283909012">"Buraxılmış zənglər"</string>
-    <string name="notification_channel_call_blocking" msgid="2028807677868598710">"Zəngi Bloklama"</string>
+    <string name="notification_channel_call_blocking" msgid="2028807677868598710">"Zəng bloklanması"</string>
     <string name="notification_channel_background_calls" msgid="7785659903711350506">"Arxa fon zəngləri"</string>
-    <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Əlaqəsi kəsilmiş zənglər"</string>
-    <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Xəta baş verən telefon tətbiqləri"</string>
+    <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Kəsilmiş zənglər"</string>
+    <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Tətbiq xətaları"</string>
     <string name="alert_outgoing_call" msgid="5319895109298927431">"Bu zəngin yerləşdirilməsi <xliff:g id="OTHER_APP">%1$s</xliff:g> zəngini sonlandıracaq."</string>
     <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Bu zəngi necə etməyi seçin"</string>
     <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> istifadə edərək zəngi yönləndirin"</string>
     <string name="alert_place_unredirect_outgoing_call" msgid="2467608535225764006">"Telefon nömrəmdən istifadə edərək zəng edin"</string>
     <string name="alert_redirect_outgoing_call_timeout" msgid="5568101425637373060">"<xliff:g id="OTHER_APP">%1$s</xliff:g> ilə zəng etmək mümkün deyil. Başqa zəng yönləndirmə tətbiqindən istifadə edin və ya yardım üçün developerlə əlaqə saxlayın."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="7311523114822507178">"Zəngi Bloklama"</string>
+    <string name="phone_settings_call_blocking_txt" msgid="7311523114822507178">"Zəng bloklanması"</string>
     <string name="phone_settings_number_not_in_contact_txt" msgid="2602249106007265757">"Kontaktda olmayan nömrələr"</string>
     <string name="phone_settings_number_not_in_contact_summary_txt" msgid="963327038085718969">"Kontaktda göstərilməyən nömrələri blok edin"</string>
     <string name="phone_settings_private_num_txt" msgid="6339272760338475619">"Şəxsi"</string>
@@ -114,10 +114,10 @@
     <string name="phone_settings_payphone_summary_txt" msgid="3936631076065563665">"Ödənişli telefon zənglərini blok edin"</string>
     <string name="phone_settings_unknown_txt" msgid="3577926178354772728">"Naməlum"</string>
     <string name="phone_settings_unknown_summary_txt" msgid="5446657192535779645">"Naməlum şəxslərdən gələn zəngləri blok edin"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="2895809176537908791">"Zəngi Bloklama"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="1713632946174016619">"Zəngi Bloklama deaktivdir"</string>
+    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="2895809176537908791">"Zəng bloklanması"</string>
+    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="1713632946174016619">"Zəng bloklanmır"</string>
     <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="6629412508584507377">"Təcili zəng edildi"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="3140411733995271126">"Təcili zənglərə cavab verənlərin Sizinlə əlaqə saxlamalarına icazə vermək üçün Zəngi Bloklama deaktiv edilib."</string>
+    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="3140411733995271126">"Təcili xidmətlərin sizinlə əlaqə saxlamaları üçün zənglər bloklanmır."</string>
     <string name="developer_title" msgid="9146088855661672353">"Telecom Tərtibatçı Menyusu"</string>
     <string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Təcili zəng zamanı zəng edilə bilməz."</string>
 </resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index c434ecc..f60d207 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -57,9 +57,9 @@
     <string name="change_default_dialer_dialog_affirmative" msgid="8604665314757739550">"Als Standard festlegen"</string>
     <string name="change_default_dialer_dialog_negative" msgid="8648669840052697821">"Abbrechen"</string>
     <string name="change_default_dialer_warning_message" msgid="8461963987376916114">"<xliff:g id="NEW_APP">%s</xliff:g> wird alle Anruffunktionen steuern. Nur vertrauenswürdige Apps sollten als Standard-Telefon-App festgelegt werden."</string>
-    <string name="change_default_call_screening_dialog_title" msgid="5365787219927262408">"<xliff:g id="NEW_APP">%s</xliff:g> als Standard-App für Call Screening festlegen?"</string>
-    <string name="change_default_call_screening_warning_message_for_disable_old_app" msgid="2039830033533243164">"Das Call Screening mit <xliff:g id="OLD_APP">%s</xliff:g> ist nicht mehr möglich."</string>
-    <string name="change_default_call_screening_warning_message" msgid="9020537562292754269">"<xliff:g id="NEW_APP">%s</xliff:g> kann Informationen zu Anrufern, die nicht in deinen Kontakten gespeichert sind, erkennen und die Anrufe blockieren. Du solltest nur Apps, denen du vertraust, als Standard-App für das Call Screening festlegen."</string>
+    <string name="change_default_call_screening_dialog_title" msgid="5365787219927262408">"<xliff:g id="NEW_APP">%s</xliff:g> als Standard-App für Anruf-Filter festlegen?"</string>
+    <string name="change_default_call_screening_warning_message_for_disable_old_app" msgid="2039830033533243164">"Der Anruf-Filter mit <xliff:g id="OLD_APP">%s</xliff:g> ist nicht mehr möglich."</string>
+    <string name="change_default_call_screening_warning_message" msgid="9020537562292754269">"<xliff:g id="NEW_APP">%s</xliff:g> kann Informationen zu Anrufern, die nicht in deinen Kontakten gespeichert sind, erkennen und die Anrufe blockieren. Du solltest nur Apps, denen du vertraust, als Standard-App für den Anruf-Filter festlegen."</string>
     <string name="change_default_call_screening_dialog_affirmative" msgid="7162433828280058647">"Als Standard festlegen"</string>
     <string name="change_default_call_screening_dialog_negative" msgid="1839266125623106342">"Abbrechen"</string>
     <string name="blocked_numbers" msgid="8322134197039865180">"Blockierte Nummern"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index c8956cd..1191f52 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -85,9 +85,9 @@
     <string name="answering_ends_other_call" msgid="8653544281903986641">"Erantzuten baduzu, amaitu egingo da <xliff:g id="CALL_VIA">%1$s</xliff:g> deia"</string>
     <string name="answering_ends_other_calls" msgid="3702302838456922535">"Erantzuten baduzu, amaitu egingo dira <xliff:g id="CALL_VIA">%1$s</xliff:g> deiak"</string>
     <string name="answering_ends_other_video_call" msgid="8572022039304239958">"Erantzuten baduzu, amaitu egingo da <xliff:g id="CALL_VIA">%1$s</xliff:g> bideo-deia"</string>
-    <string name="answering_ends_other_managed_call" msgid="4031778317409881805">"Erantzuten baduzu, amaitu egingo da uneko deia"</string>
-    <string name="answering_ends_other_managed_calls" msgid="3974069768615307659">"Erantzuten baduzu, amaitu egingo dira uneko deiak"</string>
-    <string name="answering_ends_other_managed_video_call" msgid="1988508241432031327">"Erantzuten baduzu, amaitu egingo da uneko bideo-deia"</string>
+    <string name="answering_ends_other_managed_call" msgid="4031778317409881805">"Erantzuten baduzu, amaitu egingo da oraingo deia"</string>
+    <string name="answering_ends_other_managed_calls" msgid="3974069768615307659">"Erantzuten baduzu, amaitu egingo dira oraingo deiak"</string>
+    <string name="answering_ends_other_managed_video_call" msgid="1988508241432031327">"Erantzuten baduzu, amaitu egingo da oraingo bideo-deia"</string>
     <string name="answer_incoming_call" msgid="2045888814782215326">"Erantzun"</string>
     <string name="decline_incoming_call" msgid="922147089348451310">"Baztertu"</string>
     <string name="cant_call_due_to_no_supported_service" msgid="1635626384149947077">"Ezin da egin deia, ez dagoelako mota honetako deiak onartzen duen deiak egiteko konturik."</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index cf57d62..74cdf7e 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -55,13 +55,13 @@
     <string name="add_vm_number_str" msgid="5179510133063168998">"Lisää numero"</string>
     <string name="change_default_dialer_dialog_title" msgid="5861469279421508060">"Valitaanko <xliff:g id="NEW_APP">%s</xliff:g> oletuspuhelinsovellukseksi?"</string>
     <string name="change_default_dialer_dialog_affirmative" msgid="8604665314757739550">"Aseta oletukseksi"</string>
-    <string name="change_default_dialer_dialog_negative" msgid="8648669840052697821">"Peruuta"</string>
+    <string name="change_default_dialer_dialog_negative" msgid="8648669840052697821">"Peru"</string>
     <string name="change_default_dialer_warning_message" msgid="8461963987376916114">"<xliff:g id="NEW_APP">%s</xliff:g> voi hallita kaikkia puhelutoimintoja. Aseta oletuspuhelinsovellukseksi vain luotettava sovellus."</string>
     <string name="change_default_call_screening_dialog_title" msgid="5365787219927262408">"Määritetäänkö <xliff:g id="NEW_APP">%s</xliff:g> puheluseulonnan oletussovellukseksi?"</string>
     <string name="change_default_call_screening_warning_message_for_disable_old_app" msgid="2039830033533243164">"<xliff:g id="OLD_APP">%s</xliff:g> ei voi enää seuloa puheluita."</string>
     <string name="change_default_call_screening_warning_message" msgid="9020537562292754269">"<xliff:g id="NEW_APP">%s</xliff:g> näkee tietoa soittajista, jotka eivät ole yhteystiedoissasi, ja pystyy estämään heiltä tulevat puhelut. Puheluseulonnan oletussovellukseksi kannattaa määrittää vain sellainen sovellus, johon luotat."</string>
     <string name="change_default_call_screening_dialog_affirmative" msgid="7162433828280058647">"Määritä oletussovellus"</string>
-    <string name="change_default_call_screening_dialog_negative" msgid="1839266125623106342">"Peruuta"</string>
+    <string name="change_default_call_screening_dialog_negative" msgid="1839266125623106342">"Peru"</string>
     <string name="blocked_numbers" msgid="8322134197039865180">"Estetyt numerot"</string>
     <string name="blocked_numbers_msg" msgid="2797422132329662697">"Et voi vastaanottaa puheluita tai tekstiviestejä estetyistä numeroista."</string>
     <string name="block_number" msgid="3784343046852802722">"Lisää numero"</string>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index 7455080..731618a 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -16,13 +16,13 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="telecommAppLabel" product="default" msgid="3077225713817780583">"કૉલ સંચાલન"</string>
+    <string name="telecommAppLabel" product="default" msgid="3077225713817780583">"કૉલ મેનેજમેન્ટ"</string>
     <string name="userCallActivityLabel" product="default" msgid="3605391260292846248">"ફોન"</string>
     <string name="unknown" msgid="6993977514360123431">"અજાણ્યું"</string>
     <string name="notification_missedCallTitle" msgid="5060387047205532974">"ચૂકી ગયેલો કૉલ"</string>
     <string name="notification_missedWorkCallTitle" msgid="6965463282259034953">"ચૂકી ગયેલ કાર્ય કૉલ"</string>
-    <string name="notification_missedCallsTitle" msgid="3910479625507893809">"છૂટેલા કૉલ્સ"</string>
-    <string name="notification_missedCallsMsg" msgid="5055782736170916682">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> છૂટેલા કૉલ્સ"</string>
+    <string name="notification_missedCallsTitle" msgid="3910479625507893809">"ચૂકી ગયેલા કૉલ"</string>
+    <string name="notification_missedCallsMsg" msgid="5055782736170916682">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> ચૂકી ગયેલા કૉલ"</string>
     <string name="notification_missedCallTicker" msgid="6731461957487087769">"<xliff:g id="MISSED_CALL_FROM">%s</xliff:g> નો કૉલ ચૂકી ગયાં"</string>
     <string name="notification_missedCall_call_back" msgid="7900333283939789732">"કૉલ બેક"</string>
     <string name="notification_missedCall_message" msgid="4054698824390076431">"સંદેશ"</string>
@@ -95,7 +95,7 @@
     <string name="cant_call_due_to_ongoing_calls" msgid="6379163795277824868">"તમારા <xliff:g id="OTHER_CALL">%1$s</xliff:g> કૉલને કારણે કૉલ કરી શકતાં નથી."</string>
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="8243532328969433172">"અન્ય ઍપ્લિકેશનમાં કૉલને કારણે કૉલ કરી શકતાં નથી."</string>
     <string name="notification_channel_incoming_call" msgid="5245550964701715662">"ઇનકમિંગ કૉલ"</string>
-    <string name="notification_channel_missed_call" msgid="7168893015283909012">"છૂટેલા કૉલ"</string>
+    <string name="notification_channel_missed_call" msgid="7168893015283909012">"ચૂકી ગયેલા કૉલ"</string>
     <string name="notification_channel_call_blocking" msgid="2028807677868598710">"કૉલ બ્લૉક કરી રહ્યાં છીએ"</string>
     <string name="notification_channel_background_calls" msgid="7785659903711350506">"બૅકગ્રાઉન્ડ કૉલ"</string>
     <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"ડિસ્કનેક્ટ કરેલા કૉલ"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index ed623b8..4562a5f 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -16,7 +16,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="telecommAppLabel" product="default" msgid="3077225713817780583">"कॉल प्रबंधन"</string>
+    <string name="telecommAppLabel" product="default" msgid="3077225713817780583">"कॉल मैनेजमेंट"</string>
     <string name="userCallActivityLabel" product="default" msgid="3605391260292846248">"फ़ोन"</string>
     <string name="unknown" msgid="6993977514360123431">"अज्ञात"</string>
     <string name="notification_missedCallTitle" msgid="5060387047205532974">"छूटी कॉल"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index ff38e54..d341565 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -16,7 +16,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="telecommAppLabel" product="default" msgid="3077225713817780583">"Upravljanje pozivom"</string>
+    <string name="telecommAppLabel" product="default" msgid="3077225713817780583">"Upravljanje pozivima"</string>
     <string name="userCallActivityLabel" product="default" msgid="3605391260292846248">"Telefon"</string>
     <string name="unknown" msgid="6993977514360123431">"Nepoznato"</string>
     <string name="notification_missedCallTitle" msgid="5060387047205532974">"Propušteni poziv"</string>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 6987dab..98a3bc1 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -115,7 +115,7 @@
     <string name="phone_settings_unknown_txt" msgid="3577926178354772728">"Անհայտ համարներ"</string>
     <string name="phone_settings_unknown_summary_txt" msgid="5446657192535779645">"Արգելափակել անհայտ համարներից եկող զանգերը"</string>
     <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="2895809176537908791">"Զանգերի արգելափակում"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="1713632946174016619">"Զանգերի արգելափակումն անջատած է"</string>
+    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="1713632946174016619">"Զանգերի արգելափակումն անջատված է"</string>
     <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="6629412508584507377">"Կատարվեց շտապ կանչ"</string>
     <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="3140411733995271126">"Զանգերի արգելափակումն անջատվել է, որպեսզի արտակարգ ծառայությունները կարողանան ձեզ զանգել:"</string>
     <string name="developer_title" msgid="9146088855661672353">"Telecom-ի մշակողի ընտրացանկ"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index bd87d66..a11d8d2 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -99,7 +99,7 @@
     <string name="notification_channel_call_blocking" msgid="2028807677868598710">"着信のブロック"</string>
     <string name="notification_channel_background_calls" msgid="7785659903711350506">"バックグラウンドでの通話"</string>
     <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"通話の切断"</string>
-    <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"スマートフォン アプリがクラッシュしたとき"</string>
+    <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"通話アプリがクラッシュしたとき"</string>
     <string name="alert_outgoing_call" msgid="5319895109298927431">"この通話を発信すると、<xliff:g id="OTHER_APP">%1$s</xliff:g> の通話が終了します。"</string>
     <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"通話の発信方法を選択してください"</string>
     <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> を使用して通話をリダイレクト"</string>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 6e0bb59..dff4d0a 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -98,7 +98,7 @@
     <string name="notification_channel_missed_call" msgid="7168893015283909012">"ಮಿಸ್ಡ್‌ ಕಾಲ್‍‍ಗಳು"</string>
     <string name="notification_channel_call_blocking" msgid="2028807677868598710">"ಕರೆ ನಿರ್ಬಂಧಿಸುವಿಕೆ"</string>
     <string name="notification_channel_background_calls" msgid="7785659903711350506">"ಹಿನ್ನೆಲೆ ಕರೆಗಳು"</string>
-    <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"ಕರೆಗಳ ಕನೆಕ್ಷನ್ ಅನ್ನು ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"ಡಿಸ್ಕನೆಕ್ಟ್ ಮಾಡಲಾದ ಕರೆಗಳು"</string>
     <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"ಕ್ರ್ಯಾಶ್ ಆಗಿರುವ ಫೋನ್ ಆ್ಯಪ್‌ಗಳು"</string>
     <string name="alert_outgoing_call" msgid="5319895109298927431">"ಈ ಕರೆಯನ್ನು ಮಾಡುವುದರಿಂದ ನಿಮ್ಮ <xliff:g id="OTHER_APP">%1$s</xliff:g> ಕರೆಯು ಅಂತ್ಯಗೊಳ್ಳುತ್ತದೆ."</string>
     <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"ಈ ಕರೆ ಮಾಡುವುದು ಹೇಗೆ ಎಂಬುದನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 99e211f..a9b3cc3 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -98,7 +98,7 @@
     <string name="notification_channel_missed_call" msgid="7168893015283909012">"Пропуштени повици"</string>
     <string name="notification_channel_call_blocking" msgid="2028807677868598710">"Блокирање повици"</string>
     <string name="notification_channel_background_calls" msgid="7785659903711350506">"Повици во заднина"</string>
-    <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Исклучени повици"</string>
+    <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Прекинати повици"</string>
     <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Паднати апликации за телефон"</string>
     <string name="alert_outgoing_call" msgid="5319895109298927431">"Ако се воспостави повиков, вашиот повик на <xliff:g id="OTHER_APP">%1$s</xliff:g> ќе заврши."</string>
     <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Изберете како да се воспостави повиков"</string>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index c1b3124..4d94c1a 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -98,7 +98,7 @@
     <string name="notification_channel_missed_call" msgid="7168893015283909012">"လွတ်သွားသော ဖုန်းခေါ်ဆိုမှုများ"</string>
     <string name="notification_channel_call_blocking" msgid="2028807677868598710">"ခေါ်ဆိုမှု ပိတ်ထားခြင်း"</string>
     <string name="notification_channel_background_calls" msgid="7785659903711350506">"နောက်ခံမှ ခေါ်ဆိုမှုများ"</string>
-    <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"ခေါ်ဆိုမှုများကို ဖြတ်တောက်လိုက်သည်"</string>
+    <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"ပြတ်တောက်သွားသည့် ခေါ်ဆိုမှုများ"</string>
     <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"ရပ်တန့်သွားသော ဖုန်းအက်ပ်များ"</string>
     <string name="alert_outgoing_call" msgid="5319895109298927431">"ဤခေါ်ဆိုမှု ပြုလုပ်ပါက <xliff:g id="OTHER_APP">%1$s</xliff:g> သုံးပြီးပြောနေခြင်းကို ဖြတ်ပစ်ပါမည်။"</string>
     <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"ဤခေါ်ဆိုမှု ပြုလုပ်ပုံကို ရွေးချယ်ပါ"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 1e2b32f..5d7eef0 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -22,7 +22,7 @@
     <string name="notification_missedCallTitle" msgid="5060387047205532974">"छुटेका कल"</string>
     <string name="notification_missedWorkCallTitle" msgid="6965463282259034953">"छुटेको कार्यको कल"</string>
     <string name="notification_missedCallsTitle" msgid="3910479625507893809">"छुटेका कल"</string>
-    <string name="notification_missedCallsMsg" msgid="5055782736170916682">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> छुटेका कलहरू"</string>
+    <string name="notification_missedCallsMsg" msgid="5055782736170916682">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> मिस कलहरू"</string>
     <string name="notification_missedCallTicker" msgid="6731461957487087769">"<xliff:g id="MISSED_CALL_FROM">%s</xliff:g>बाट छुटेका कल"</string>
     <string name="notification_missedCall_call_back" msgid="7900333283939789732">"फेरि कल गर्नुहोस्"</string>
     <string name="notification_missedCall_message" msgid="4054698824390076431">"सन्देश"</string>
@@ -30,9 +30,9 @@
     <string name="notification_disconnectedCall_body" msgid="600491714584417536">"आपत्‌कालीन कल गरिएको हुनाले <xliff:g id="CALLER">%s</xliff:g> लाई गरिएको कल विच्छेद गरियो।"</string>
     <string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"आपत्‌कालीन कल जारी रहेको हुनाले तपाईंको कल विच्छेद गरिएको छ।"</string>
     <string name="notification_audioProcessing_title" msgid="1619035039880584575">"पृष्ठभूमिको कल"</string>
-    <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ले एउटा कल पृष्ठभूमिमा राखेको छ। कल गरेको बेला यो अनुप्रयोगले अडियोमाथि पहुँच राखेर प्ले गरिरहेको हुन सक्छ।"</string>
+    <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ले एउटा कल पृष्ठभूमिमा राखेको छ। कल गरेको बेला यो एपले अडियोमाथि पहुँच राखेर प्ले गरिरहेको हुन सक्छ।"</string>
     <string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> ले काम गर्न छाड्यो"</string>
-    <string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"कल गर्नका लागि तपाईंको यन्त्रमा पहिल्यैदेखि रहेको फोन एप प्रयोग गरियो"</string>
+    <string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"कल गर्नका लागि तपाईंको डिभाइसमा पहिल्यैदेखि रहेको फोन एप प्रयोग गरियो"</string>
     <string name="accessibility_call_muted" msgid="2968461092554300779">"कल म्युट भयो।"</string>
     <string name="accessibility_speakerphone_enabled" msgid="555386652061614267">"स्पिकरफोन सक्षम भयो।"</string>
     <string name="respond_via_sms_canned_response_1" msgid="6332561460870382561">"अहिले कुरा गर्न मिल्दैन। के भइरहेको छ?"</string>
@@ -47,20 +47,20 @@
     <string name="respond_via_sms_failure_format" msgid="5198680980054596391">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> मा सन्देश पठाउन सकिएन।"</string>
     <string name="enable_account_preference_title" msgid="6949224486748457976">"कलिङ खाताहरू"</string>
     <string name="outgoing_call_not_allowed_user_restriction" msgid="3424338207838851646">"आपत्‌कालीन कलहरूलाई मात्र अनुमति दिइएको छ।"</string>
-    <string name="outgoing_call_not_allowed_no_permission" msgid="8590468836581488679">"यो अनुप्रयोगले फोनको अनुमति बिना बहिर्गमन कलहरू गर्न सक्दैन।"</string>
+    <string name="outgoing_call_not_allowed_no_permission" msgid="8590468836581488679">"यो एपले फोनको अनुमति बिना बहिर्गमन कलहरू गर्न सक्दैन।"</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="7665135102566099778">"एक कल गर्नको लागि, एक वैध नम्बर प्रविष्टि गर्नुहोस्।"</string>
     <string name="duplicate_video_call_not_allowed" msgid="5754746140185781159">"यस समयमा कल थप गर्न सकिँदैन।"</string>
     <string name="no_vm_number" msgid="2179959110602180844">"भ्वाइसमेल नम्बर हराइरहेको छ"</string>
     <string name="no_vm_number_msg" msgid="1339245731058529388">"SIM कार्डमा कुनै पनि भ्वाइसमेल नम्बर भण्डारण भएको छैन।"</string>
     <string name="add_vm_number_str" msgid="5179510133063168998">"नम्बर थप्नुहोस्"</string>
-    <string name="change_default_dialer_dialog_title" msgid="5861469279421508060">"तपाईंको पूर्वनिर्धारित फोन एप <xliff:g id="NEW_APP">%s</xliff:g> बनाउने हो?"</string>
-    <string name="change_default_dialer_dialog_affirmative" msgid="8604665314757739550">"पूर्वनिर्धारित रूपमा सेट गर्नुहोस्"</string>
+    <string name="change_default_dialer_dialog_title" msgid="5861469279421508060">"तपाईंको डिफल्ट फोन एप <xliff:g id="NEW_APP">%s</xliff:g> बनाउने हो?"</string>
+    <string name="change_default_dialer_dialog_affirmative" msgid="8604665314757739550">"डिफल्ट रूपमा सेट गर्नुहोस्"</string>
     <string name="change_default_dialer_dialog_negative" msgid="8648669840052697821">"रद्द गर्नुहोस्"</string>
-    <string name="change_default_dialer_warning_message" msgid="8461963987376916114">"<xliff:g id="NEW_APP">%s</xliff:g> कलका सबै पक्षहरूलाई स्थापित गर्न र नियन्त्रण गर्न सक्षम हुने छ। तपाईंलाई विश्वास लाग्ने एपहरूलाई मात्र फोनमा पूर्वनिर्धारित एपका रूपमा सेट गर्नुपर्छ।"</string>
-    <string name="change_default_call_screening_dialog_title" msgid="5365787219927262408">"तपाईंको पूर्वनिर्धारित कल स्क्रिन एप <xliff:g id="NEW_APP">%s</xliff:g> बनाउने हो?"</string>
+    <string name="change_default_dialer_warning_message" msgid="8461963987376916114">"<xliff:g id="NEW_APP">%s</xliff:g> कलका सबै पक्षहरूलाई स्थापित गर्न र नियन्त्रण गर्न सक्षम हुने छ। तपाईंलाई विश्वास लाग्ने एपहरूलाई मात्र फोनमा डिफल्ट एपका रूपमा सेट गर्नुपर्छ।"</string>
+    <string name="change_default_call_screening_dialog_title" msgid="5365787219927262408">"तपाईंको डिफल्ट कल स्क्रिन एप <xliff:g id="NEW_APP">%s</xliff:g> बनाउने हो?"</string>
     <string name="change_default_call_screening_warning_message_for_disable_old_app" msgid="2039830033533243164">"<xliff:g id="OLD_APP">%s</xliff:g> ले अब उप्रान्त कलहरू स्क्रिन गर्न सक्ने छैनन्‌।"</string>
-    <string name="change_default_call_screening_warning_message" msgid="9020537562292754269">"<xliff:g id="NEW_APP">%s</xliff:g> ले तपाईंको सम्पर्कमा नभएका कल गर्ने व्यक्तिका जानकारी हेर्न सक्छ र तिनीहरूमाथि रोक लगाउन सक्छ। तपाईंलाई विश्वास लाग्ने एपहरूलाई मात्र कल स्क्रिन पूर्वनिर्धारित एपका रूपमा सेट गर्नुपर्छ।"</string>
-    <string name="change_default_call_screening_dialog_affirmative" msgid="7162433828280058647">"पूर्वनिर्धारित रूपमा सेट गर्नुहोस्"</string>
+    <string name="change_default_call_screening_warning_message" msgid="9020537562292754269">"<xliff:g id="NEW_APP">%s</xliff:g> ले तपाईंको सम्पर्कमा नभएका कल गर्ने व्यक्तिका जानकारी हेर्न सक्छ र तिनीहरूमाथि रोक लगाउन सक्छ। तपाईंलाई विश्वास लाग्ने एपहरूलाई मात्र कल स्क्रिन डिफल्ट एपका रूपमा सेट गर्नुपर्छ।"</string>
+    <string name="change_default_call_screening_dialog_affirmative" msgid="7162433828280058647">"डिफल्ट रूपमा सेट गर्नुहोस्"</string>
     <string name="change_default_call_screening_dialog_negative" msgid="1839266125623106342">"रद्द गर्नुहोस्"</string>
     <string name="blocked_numbers" msgid="8322134197039865180">"रोकिएका नम्बरहरू"</string>
     <string name="blocked_numbers_msg" msgid="2797422132329662697">"तपाईँले रोक लगाइएका नम्बरहरूबाट फोन वा टेक्स्ट म्यासेजहरू प्राप्त गर्नुहुने छैन।"</string>
@@ -73,7 +73,7 @@
     <string name="non_primary_user" msgid="315564589279622098">"यन्त्रको मालिकले रोकिएका नम्बरहरूलाई हेर्न र व्यवस्थापन गर्न सक्छ।"</string>
     <string name="delete_icon_description" msgid="5335959254954774373">"अनब्लक गर्नुहोस्"</string>
     <string name="blocked_numbers_butter_bar_title" msgid="582982373755950791">"रोक लगाउने काम अस्थायी रूपमा निष्क्रिय छ"</string>
-    <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"तपाईँले आपत्‌कालीन नम्बरमा डायल गरेपछि वा पाठ सन्देश पठाएपछि आपत्‌कालीन सेवाहरूले तपाईँलाई सम्पर्क गर्न सकून् भन्ने कुरा सुनिश्चित गर्न कलमाथिको अवरोध निष्क्रिय गरिन्छ।"</string>
+    <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"तपाईँले आपत्‌कालीन नम्बरमा डायल गरेपछि वा टेक्स्ट म्यासेज पठाएपछि आपत्‌कालीन सेवाहरूले तपाईँलाई सम्पर्क गर्न सकून् भन्ने कुरा सुनिश्चित गर्न कलमाथिको अवरोध निष्क्रिय गरिन्छ।"</string>
     <string name="blocked_numbers_butter_bar_button" msgid="2704456308072489793">"अब पुन:-सक्रिय गर्नुहोस्"</string>
     <string name="blocked_numbers_number_blocked_message" msgid="4314736791180919167">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> माथि रोक लगाइयो"</string>
     <string name="blocked_numbers_number_unblocked_message" msgid="2933071624674945601">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> माथिको रोक हटाइयो"</string>
@@ -95,11 +95,11 @@
     <string name="cant_call_due_to_ongoing_calls" msgid="6379163795277824868">"तपाईंका <xliff:g id="OTHER_CALL">%1$s</xliff:g> कलहरूका कारण कल गर्न सकिँदैन।"</string>
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="8243532328969433172">"अर्को अनुप्रयोगमा जारी कलका कारण कल गर्न सकिँदैन।"</string>
     <string name="notification_channel_incoming_call" msgid="5245550964701715662">"आगमन कलहरू"</string>
-    <string name="notification_channel_missed_call" msgid="7168893015283909012">"छुटेका कलहरू"</string>
+    <string name="notification_channel_missed_call" msgid="7168893015283909012">"मिस कलहरू"</string>
     <string name="notification_channel_call_blocking" msgid="2028807677868598710">"कलमाथि रोक लगाउने सुविधा"</string>
     <string name="notification_channel_background_calls" msgid="7785659903711350506">"ब्याकग्राउन्डका कलहरू"</string>
     <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"विच्छेद गरिएका कल"</string>
-    <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"क्र्यास भएका फोन एपहरू"</string>
+    <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"फोनमा रहेका क्र्यास भएका एपहरू"</string>
     <string name="alert_outgoing_call" msgid="5319895109298927431">"यो कल गर्नुले तपाईंको <xliff:g id="OTHER_APP">%1$s</xliff:g> कल अन्त्य गर्दछ।"</string>
     <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"यो कल गर्ने तरिका छनौट गर्नुहोस्"</string>
     <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"<xliff:g id="OTHER_APP">%1$s</xliff:g> प्रयोग गरी कल रिडाइरेक्ट गर्नुहोस्"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index e0061a7..e3ca712 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -55,7 +55,7 @@
     <string name="add_vm_number_str" msgid="5179510133063168998">"ନମ୍ବର୍ ଯୋଡ଼ନ୍ତୁ"</string>
     <string name="change_default_dialer_dialog_title" msgid="5861469279421508060">"<xliff:g id="NEW_APP">%s</xliff:g>କୁ ଆପଣଙ୍କ ଫୋନ୍‌ର ଡିଫଲ୍ଟ ଆପ୍ କରିବେ?"</string>
     <string name="change_default_dialer_dialog_affirmative" msgid="8604665314757739550">"ଡିଫଲ୍ଟ ସେଟ୍ କରନ୍ତୁ"</string>
-    <string name="change_default_dialer_dialog_negative" msgid="8648669840052697821">"କ୍ୟାନ୍ସଲ୍‍ କରନ୍ତୁ"</string>
+    <string name="change_default_dialer_dialog_negative" msgid="8648669840052697821">"ବାତିଲ୍‍ କରନ୍ତୁ"</string>
     <string name="change_default_dialer_warning_message" msgid="8461963987376916114">"<xliff:g id="NEW_APP">%s</xliff:g> କଲ୍ କରିବା ଏବଂ କଲ୍‌ର ସମସ୍ତ ଦିଗକୁ ନିୟନ୍ତ୍ରଣ କରିବାରେ ସକ୍ଷମ ହେବ। କେବଳ ନିଜର ଭରସାଯୋଗ୍ୟ ଆପ୍‌କୁ ଡିଫଲ୍ଟ ଫୋନ୍ ଆପ୍ ଭାବେ ସେଟ୍ କରିବା ଉଚିତ୍।"</string>
     <string name="change_default_call_screening_dialog_title" msgid="5365787219927262408">"<xliff:g id="NEW_APP">%s</xliff:g>କୁ ଆପଣଙ୍କ ଡିଫଲ୍ଟ କଲ୍ ସ୍କ୍ରିନିଂ ଆପ୍ କରିବେ?"</string>
     <string name="change_default_call_screening_warning_message_for_disable_old_app" msgid="2039830033533243164">"<xliff:g id="OLD_APP">%s</xliff:g> କଲ୍ ସ୍କ୍ରିନ୍‌ କରିପାରିରିବେ ନାହିଁ।"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 70c4566..b646cbb 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -75,7 +75,7 @@
     <string name="blocked_numbers_butter_bar_title" msgid="582982373755950791">"Blockeringen har inaktiverats tillfälligt"</string>
     <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"När du ringer eller sms:ar ett nödnummer inaktiveras blockering för att säkerställa att räddningstjänsten kan kontakta dig."</string>
     <string name="blocked_numbers_butter_bar_button" msgid="2704456308072489793">"Återaktivera nu"</string>
-    <string name="blocked_numbers_number_blocked_message" msgid="4314736791180919167">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> blockerade"</string>
+    <string name="blocked_numbers_number_blocked_message" msgid="4314736791180919167">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> har blockerats"</string>
     <string name="blocked_numbers_number_unblocked_message" msgid="2933071624674945601">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> avblockerat"</string>
     <string name="blocked_numbers_block_emergency_number_message" msgid="4198550501500893890">"Det går inte att blockera nödnummer."</string>
     <string name="blocked_numbers_number_already_blocked_message" msgid="2301270825735665458">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> är redan blockerat."</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 8b8a40c..d1142f7 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -43,7 +43,7 @@
     <string name="respond_via_sms_setting_title_2" msgid="4914853536609553457">"Hariri majibu ya haraka"</string>
     <string name="respond_via_sms_setting_summary" msgid="8054571501085436868"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="6579353156073272157">"Majibu ya haraka"</string>
-    <string name="respond_via_sms_confirmation_format" msgid="2932395476561267842">"Ujumbe uliotumwa kwa <xliff:g id="PHONE_NUMBER">%s</xliff:g> ."</string>
+    <string name="respond_via_sms_confirmation_format" msgid="2932395476561267842">"Ujumbe umetumwa kwa <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="respond_via_sms_failure_format" msgid="5198680980054596391">"Imeshindwa kutuma SMS kwa <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="6949224486748457976">"Akaunti za simu"</string>
     <string name="outgoing_call_not_allowed_user_restriction" msgid="3424338207838851646">"Piga simu za dharura pekee."</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 58eb225..e6deb9c 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -16,7 +16,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="telecommAppLabel" product="default" msgid="3077225713817780583">"కాల్ నిర్వహణ"</string>
+    <string name="telecommAppLabel" product="default" msgid="3077225713817780583">"కాల్ మేనేజ్‌మెంట్"</string>
     <string name="userCallActivityLabel" product="default" msgid="3605391260292846248">"ఫోన్"</string>
     <string name="unknown" msgid="6993977514360123431">"తెలియదు"</string>
     <string name="notification_missedCallTitle" msgid="5060387047205532974">"సమాధానం ఇవ్వని కాల్"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index bbda818..6080b06 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -26,7 +26,7 @@
     <string name="notification_missedCallTicker" msgid="6731461957487087769">"来自<xliff:g id="MISSED_CALL_FROM">%s</xliff:g>的未接电话"</string>
     <string name="notification_missedCall_call_back" msgid="7900333283939789732">"回拨"</string>
     <string name="notification_missedCall_message" msgid="4054698824390076431">"发短信"</string>
-    <string name="notification_disconnectedCall_title" msgid="1790131923692416928">"已中断的通话"</string>
+    <string name="notification_disconnectedCall_title" msgid="1790131923692416928">"通话中断"</string>
     <string name="notification_disconnectedCall_body" msgid="600491714584417536">"由于要进行紧急呼叫,与 <xliff:g id="CALLER">%s</xliff:g> 的通话已中断。"</string>
     <string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"由于要进行紧急呼叫,您的通话已中断。"</string>
     <string name="notification_audioProcessing_title" msgid="1619035039880584575">"后台通话"</string>
@@ -98,8 +98,8 @@
     <string name="notification_channel_missed_call" msgid="7168893015283909012">"未接电话"</string>
     <string name="notification_channel_call_blocking" msgid="2028807677868598710">"来电屏蔽"</string>
     <string name="notification_channel_background_calls" msgid="7785659903711350506">"后台通话"</string>
-    <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"已中断的通话"</string>
-    <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"崩溃的手机应用"</string>
+    <string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"通话中断"</string>
+    <string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"手机应用崩溃"</string>
     <string name="alert_outgoing_call" msgid="5319895109298927431">"拨打此电话将导致<xliff:g id="OTHER_APP">%1$s</xliff:g>通话结束。"</string>
     <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"选择拨打此电话的方式"</string>
     <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"使用<xliff:g id="OTHER_APP">%1$s</xliff:g>转移呼叫"</string>
diff --git a/res/values/config.xml b/res/values/config.xml
index 9cbbf46..b0e50b0 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -69,4 +69,8 @@
     <!-- When true, the options in the call blocking settings to block restricted and unknown
          callers are combined into a single toggle. -->
     <bool name="combine_options_to_block_restricted_and_unknown_callers">true</bool>
+
+    <!-- When set, Telecom will attempt to bind to the {@link CallDiagnosticService} implementation
+         defined by the app with this package name. -->
+    <string name="call_diagnostic_service_package_name"></string>
 </resources>
diff --git a/scripts/aosp_tag_preupload.py b/scripts/aosp_tag_preupload.py
index 77a9714..17f5058 100755
--- a/scripts/aosp_tag_preupload.py
+++ b/scripts/aosp_tag_preupload.py
@@ -49,7 +49,7 @@
 
 def _is_in_aosp():
   branch_info = subprocess.check_output(["git", "branch", "-vv"])
-  return re.search(AOSP_BRANCH_REGEX, branch_info) is not None
+  return re.search(AOSP_BRANCH_REGEX, str(branch_info)) is not None
 
 def _check_aosp_message(aosp_line):
   if re.search(AOSP_COMMIT_LINK_REGEX, aosp_line):
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index c5f3bde..16bb551 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -37,11 +37,13 @@
 import android.os.UserHandle;
 import android.provider.CallLog;
 import android.provider.ContactsContract.Contacts;
+import android.telecom.BluetoothCallQualityReport;
 import android.telecom.CallAudioState;
 import android.telecom.CallerInfo;
 import android.telecom.Conference;
 import android.telecom.Connection;
 import android.telecom.ConnectionService;
+import android.telecom.DiagnosticCall;
 import android.telecom.DisconnectCause;
 import android.telecom.GatewayInfo;
 import android.telecom.InCallService;
@@ -156,6 +158,8 @@
                                  Bundle extras, boolean isLegacy);
         void onHandoverFailed(Call call, int error);
         void onHandoverComplete(Call call);
+        void onBluetoothCallQualityReport(Call call, BluetoothCallQualityReport report);
+        void onReceivedDeviceToDeviceMessage(Call call, int messageType, int messageValue);
     }
 
     public abstract static class ListenerBase implements Listener {
@@ -244,6 +248,10 @@
         public void onHandoverFailed(Call call, int error) {}
         @Override
         public void onHandoverComplete(Call call) {}
+        @Override
+        public void onBluetoothCallQualityReport(Call call, BluetoothCallQualityReport report) {}
+        @Override
+        public void onReceivedDeviceToDeviceMessage(Call call, int messageType, int messageValue) {}
     }
 
     private final CallerInfoLookupHelper.OnQueryCompleteListener mCallerInfoQueryListener =
@@ -647,6 +655,13 @@
     private String mCallScreeningComponentName;
 
     /**
+     * When {@code true} indicates this call originated from a SIM-based {@link PhoneAccount}.
+     * A sim-based {@link PhoneAccount} is one with {@link PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION}
+     * set.
+     */
+    private boolean mIsSimCall;
+
+    /**
      * Persists the specified parameters and initializes the new instance.
      * @param context The context.
      * @param repository The connection service repository.
@@ -1077,6 +1092,10 @@
         }
     }
 
+    public void handleOverrideDisconnectMessage(@Nullable CharSequence message) {
+
+    }
+
     /**
      * Sets the call state. Although there exists the notion of appropriate state transitions
      * (see {@link CallState}), in practice those expectations break down when cellular systems
@@ -1703,6 +1722,7 @@
         PhoneAccountRegistrar phoneAccountRegistrar = mCallsManager.getPhoneAccountRegistrar();
         boolean isWorkCall = false;
         boolean isCallRecordingToneSupported = false;
+        boolean isSimCall = false;
         PhoneAccount phoneAccount =
                 phoneAccountRegistrar.getPhoneAccountUnchecked(mTargetPhoneAccountHandle);
         if (phoneAccount != null) {
@@ -1720,9 +1740,11 @@
                     PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) && phoneAccount.getExtras() != null
                     && phoneAccount.getExtras().getBoolean(
                     PhoneAccount.EXTRA_PLAY_CALL_RECORDING_TONE, false));
+            isSimCall = phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
         }
         mIsWorkCall = isWorkCall;
         mUseCallRecordingTone = isCallRecordingToneSupported;
+        mIsSimCall = isSimCall;
     }
 
     /**
@@ -1903,6 +1925,13 @@
             if (didRttChange) {
                 if ((mConnectionProperties & Connection.PROPERTY_IS_RTT) ==
                         Connection.PROPERTY_IS_RTT) {
+                    // If we already had RTT streams up, that means that either the call started
+                    // with RTT or the user previously requested to start RTT. Either way, don't
+                    // play the alert tone.
+                    if (!areRttStreamsInitialized()) {
+                        mCallsManager.playRttUpgradeToneForCall(this);
+                    }
+
                     createRttStreams();
                     // Call startRtt to pass the RTT pipes down to the connection service.
                     // They already turned on the RTT property so no request should be sent.
@@ -1944,6 +1973,16 @@
                 }
             }
 
+            boolean wasDowngradedConference =
+                    (previousProperties & Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE) != 0;
+            boolean isDowngradedConference =
+                    (connectionProperties & Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE) != 0;
+            if (wasDowngradedConference && !isDowngradedConference) {
+                Log.i(this, "DOWNGRADED_CONFERENCE property removed; setting"
+                        + " conference state to false");
+                setConferenceState(false);
+            }
+
             mAnalytics.addCallProperties(mConnectionProperties);
 
             int xorProps = previousProperties ^ mConnectionProperties;
@@ -2952,6 +2991,14 @@
                 }
                 requestHandover(phoneAccountHandle, videoState, handoverExtrasBundle, true);
             } else {
+                // Relay bluetooth call quality reports to the call diagnostic service.
+                if (BluetoothCallQualityReport.EVENT_BLUETOOTH_CALL_QUALITY_REPORT.equals(event)
+                        && extras.containsKey(
+                        BluetoothCallQualityReport.EXTRA_BLUETOOTH_CALL_QUALITY_REPORT)) {
+                    notifyBluetoothCallQualityReport(extras.getParcelable(
+                            BluetoothCallQualityReport.EXTRA_BLUETOOTH_CALL_QUALITY_REPORT
+                    ));
+                }
                 Log.addEvent(this, LogUtils.Events.CALL_EVENT, event);
                 mConnectionService.sendCallEvent(this, event, extras);
             }
@@ -2962,6 +3009,17 @@
     }
 
     /**
+     * Notifies listeners when a bluetooth quality report is received.
+     * @param report The bluetooth quality report.
+     */
+    void notifyBluetoothCallQualityReport(@NonNull BluetoothCallQualityReport report) {
+        Log.addEvent(this, LogUtils.Events.BT_QUALITY_REPORT, "choppy=" + report.isChoppyVoice());
+        for (Listener l : mListeners) {
+            l.onBluetoothCallQualityReport(this, report);
+        }
+    }
+
+    /**
      * Initiates a handover of this Call to the {@link ConnectionService} identified
      * by destAcct.
      * @param destAcct ConnectionService to which the call should be handed over.
@@ -3691,6 +3749,17 @@
             for (Listener l : mListeners) {
                 l.onCallSwitchFailed(this);
             }
+        } else if (Connection.EVENT_DEVICE_TO_DEVICE_MESSAGE.equals(event)
+                && extras != null && extras.containsKey(
+                Connection.EXTRA_DEVICE_TO_DEVICE_MESSAGE_TYPE)
+                && extras.containsKey(Connection.EXTRA_DEVICE_TO_DEVICE_MESSAGE_VALUE)) {
+            // Relay an incoming D2D message to interested listeners; most notably the
+            // CallDiagnosticService.
+            int messageType = extras.getInt(Connection.EXTRA_DEVICE_TO_DEVICE_MESSAGE_TYPE);
+            int messageValue = extras.getInt(Connection.EXTRA_DEVICE_TO_DEVICE_MESSAGE_VALUE);
+            for (Listener l : mListeners) {
+                l.onReceivedDeviceToDeviceMessage(this, messageType, messageValue);
+            }
         } else {
             for (Listener l : mListeners) {
                 l.onConnectionEvent(this, event, extras);
@@ -3892,6 +3961,44 @@
     }
 
     /**
+     * Sends a device to device message to the other part of the call.
+     * @param message the message type to send.
+     * @param value the value for the message.
+     */
+    public void sendDeviceToDeviceMessage(@DiagnosticCall.MessageType int message, int value) {
+        Log.i(this, "sendDeviceToDeviceMessage; callId=%s, msg=%d/%d", getId(), message, value);
+        Bundle extras = new Bundle();
+        extras.putInt(Connection.EXTRA_DEVICE_TO_DEVICE_MESSAGE_TYPE, message);
+        extras.putInt(Connection.EXTRA_DEVICE_TO_DEVICE_MESSAGE_VALUE, value);
+        // Send to the connection service.
+        sendCallEvent(Connection.EVENT_DEVICE_TO_DEVICE_MESSAGE, extras);
+    }
+
+    /**
+     * Signals to the Dialer app to start displaying a diagnostic message.
+     * @param messageId a unique ID for the message to display.
+     * @param message the message to display.
+     */
+    public void displayDiagnosticMessage(int messageId, @NonNull CharSequence message) {
+        Bundle extras = new Bundle();
+        extras.putInt(android.telecom.Call.EXTRA_DIAGNOSTIC_MESSAGE_ID, messageId);
+        extras.putCharSequence(android.telecom.Call.EXTRA_DIAGNOSTIC_MESSAGE, message);
+        // Send to the dialer.
+        onConnectionEvent(android.telecom.Call.EVENT_DISPLAY_DIAGNOSTIC_MESSAGE, extras);
+    }
+
+    /**
+     * Signals to the Dialer app to stop displaying a diagnostic message.
+     * @param messageId a unique ID for the message to clear.
+     */
+    public void clearDiagnosticMessage(int messageId) {
+        Bundle extras = new Bundle();
+        extras.putInt(android.telecom.Call.EXTRA_DIAGNOSTIC_MESSAGE_ID, messageId);
+        // Send to the dialer.
+        onConnectionEvent(android.telecom.Call.EVENT_CLEAR_DIAGNOSTIC_MESSAGE, extras);
+    }
+
+    /**
      * Remaps the call direction as indicated by an {@link android.telecom.Call.Details} direction
      * constant to the constants (e.g. {@link #CALL_DIRECTION_INCOMING}) used in this call class.
      * @param direction The android.telecom.Call direction.
@@ -3977,4 +4084,13 @@
             }
         }
     }
+
+    /**
+     * @return {@code true} when this call originated from a SIM-based {@link PhoneAccount}.
+     * A sim-based {@link PhoneAccount} is one with {@link PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION}
+     * set.
+     */
+    public boolean isSimCall() {
+        return mIsSimCall;
+    }
 }
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index a6509b4..6a7261e 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -264,6 +264,14 @@
         }
     }
 
+    public void playRttUpgradeTone(Call call) {
+        if (call != mForegroundCall) {
+            // We only play tones for foreground calls.
+            return;
+        }
+        mPlayerFactory.createPlayer(InCallTonePlayer.TONE_RTT_REQUEST).startTone();
+    }
+
     /**
      * Play or stop a call hold tone for a call.  Triggered via
      * {@link Connection#sendConnectionEvent(String)} when the
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index bcfdedf..7bf94ed 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -493,6 +493,8 @@
                 case SWITCH_FOCUS:
                     if (msg.arg1 == ACTIVE_FOCUS || msg.arg1 == RINGING_FOCUS) {
                         transitionTo(mActiveEarpieceRoute);
+                    } else {
+                        mCallAudioManager.notifyAudioOperationsComplete();
                     }
                     return HANDLED;
                 default:
@@ -695,6 +697,8 @@
                 case SWITCH_FOCUS:
                     if (msg.arg1 == ACTIVE_FOCUS || msg.arg1 == RINGING_FOCUS) {
                         transitionTo(mActiveHeadsetRoute);
+                    } else {
+                        mCallAudioManager.notifyAudioOperationsComplete();
                     }
                     return HANDLED;
                 default:
@@ -1051,6 +1055,8 @@
                         } else {
                             transitionTo(mRingingBluetoothRoute);
                         }
+                    } else {
+                        mCallAudioManager.notifyAudioOperationsComplete();
                     }
                     return HANDLED;
                 case BT_AUDIO_DISCONNECTED:
@@ -1274,6 +1280,8 @@
                     if (msg.arg1 == ACTIVE_FOCUS || msg.arg1 == RINGING_FOCUS) {
                         setSpeakerphoneOn(true);
                         transitionTo(mActiveSpeakerRoute);
+                    } else {
+                        mCallAudioManager.notifyAudioOperationsComplete();
                     }
                     return HANDLED;
                 default:
diff --git a/src/com/android/server/telecom/CallDiagnosticServiceAdapter.java b/src/com/android/server/telecom/CallDiagnosticServiceAdapter.java
new file mode 100644
index 0000000..79a94d3
--- /dev/null
+++ b/src/com/android/server/telecom/CallDiagnosticServiceAdapter.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package com.android.server.telecom;
+
+import android.annotation.NonNull;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.telecom.CallDiagnosticService;
+import android.telecom.DiagnosticCall;
+import android.telecom.Log;
+
+import com.android.internal.telecom.ICallDiagnosticServiceAdapter;
+import com.android.internal.telecom.IInCallAdapter;
+
+/**
+ * Adapter class used to provide a path for messages FROM a {@link CallDiagnosticService} back to
+ * the telecom stack.
+ */
+public class CallDiagnosticServiceAdapter extends ICallDiagnosticServiceAdapter.Stub {
+    public interface TelecomAdapter {
+        void displayDiagnosticMessage(String callId, int messageId, CharSequence message);
+        void clearDiagnosticMessage(String callId, int messageId);
+        void sendDeviceToDeviceMessage(String callId, @DiagnosticCall.MessageType int message,
+                int value);
+        void overrideDisconnectMessage(String callId, CharSequence message);
+    }
+
+    private final TelecomAdapter mTelecomAdapter;
+    private final String mOwnerPackageName;
+    private final String mOwnerPackageAbbreviation;
+    private final TelecomSystem.SyncRoot mLock;
+
+    CallDiagnosticServiceAdapter(@NonNull TelecomAdapter telecomAdapter,
+            @NonNull String ownerPackageName, @NonNull TelecomSystem.SyncRoot lock) {
+        mTelecomAdapter = telecomAdapter;
+        mOwnerPackageName = ownerPackageName;
+        mOwnerPackageAbbreviation = Log.getPackageAbbreviation(ownerPackageName);
+        mLock = lock;
+    }
+
+    @Override
+    public void displayDiagnosticMessage(String callId, int messageId, CharSequence message)
+            throws RemoteException {
+        try {
+            Log.startSession("CDSA.dDM", mOwnerPackageAbbreviation);
+            long token = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    Log.i(this, "displayDiagnosticMessage; callId=%s, msg=%d/%s", callId, messageId,
+                            message);
+                    mTelecomAdapter.displayDiagnosticMessage(callId, messageId, message);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        } finally {
+            Log.endSession();
+        }
+    }
+
+    @Override
+    public void clearDiagnosticMessage(String callId, int messageId) throws RemoteException {
+        try {
+            Log.startSession("CDSA.cDM", mOwnerPackageAbbreviation);
+            long token = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    Log.i(this, "clearDiagnosticMessage; callId=%s, msg=%d", callId, messageId);
+                    mTelecomAdapter.clearDiagnosticMessage(callId, messageId);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        } finally {
+            Log.endSession();
+        }
+    }
+
+    @Override
+    public void sendDeviceToDeviceMessage(String callId, @DiagnosticCall.MessageType int message,
+            int value)
+            throws RemoteException {
+        try {
+            Log.startSession("CDSA.sDTDM", mOwnerPackageAbbreviation);
+            long token = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    Log.i(this, "sendDeviceToDeviceMessage; callId=%s, msg=%d/%d", callId, message,
+                            value);
+                    mTelecomAdapter.sendDeviceToDeviceMessage(callId, message, value);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        } finally {
+            Log.endSession();
+        }
+    }
+
+    @Override
+    public void overrideDisconnectMessage(String callId, CharSequence message)
+            throws RemoteException {
+        try {
+            Log.startSession("CDSA.oDM", mOwnerPackageAbbreviation);
+            long token = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    Log.i(this, "overrideDisconnectMessage; callId=%s, msg=%s", callId, message);
+                    mTelecomAdapter.overrideDisconnectMessage(callId, message);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        } finally {
+            Log.endSession();
+        }
+    }
+}
diff --git a/src/com/android/server/telecom/CallDiagnosticServiceController.java b/src/com/android/server/telecom/CallDiagnosticServiceController.java
new file mode 100644
index 0000000..943a176
--- /dev/null
+++ b/src/com/android/server/telecom/CallDiagnosticServiceController.java
@@ -0,0 +1,654 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package com.android.server.telecom;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.UserIdInt;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.telecom.BluetoothCallQualityReport;
+import android.telecom.CallAudioState;
+import android.telecom.CallDiagnosticService;
+import android.telecom.ConnectionService;
+import android.telecom.DiagnosticCall;
+import android.telecom.InCallService;
+import android.telecom.Log;
+import android.telecom.ParcelableCall;
+import android.telephony.ims.ImsReasonInfo;
+import android.text.TextUtils;
+
+import com.android.internal.telecom.ICallDiagnosticService;
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Responsible for maintaining binding to the {@link CallDiagnosticService} defined by the
+ * {@code call_diagnostic_service_package_name} key in the
+ * {@code packages/services/Telecomm/res/values/config.xml} file.
+ */
+public class CallDiagnosticServiceController extends CallsManagerListenerBase {
+    /**
+     * Context dependencies for the {@link CallDiagnosticServiceController}.
+     */
+    public interface ContextProxy {
+        List<ResolveInfo> queryIntentServicesAsUser(@NonNull Intent intent,
+                @PackageManager.ResolveInfoFlags int flags, @UserIdInt int userId);
+        boolean bindServiceAsUser(@NonNull @RequiresPermission Intent service,
+                @NonNull ServiceConnection conn, int flags, @NonNull UserHandle user);
+        void unbindService(@NonNull ServiceConnection conn);
+        UserHandle getCurrentUserHandle();
+    }
+
+    /**
+     * Listener for {@link Call} events; used to propagate these changes to the
+     * {@link CallDiagnosticService}.
+     */
+    private final Call.Listener mCallListener = new Call.ListenerBase() {
+        @Override
+        public void onConnectionCapabilitiesChanged(Call call) {
+            updateCall(call);
+        }
+
+        @Override
+        public void onConnectionPropertiesChanged(Call call, boolean didRttChange) {
+            updateCall(call);
+        }
+
+        /**
+         * Listens for changes to extras reported by a Telecom {@link Call}.
+         *
+         * Extras changes can originate from a {@link ConnectionService} or an {@link InCallService}
+         * so we will only trigger an update of the call information if the source of the extras
+         * change was a {@link ConnectionService}.
+         *
+         * @param call The call.
+         * @param source The source of the extras change ({@link Call#SOURCE_CONNECTION_SERVICE} or
+         *               {@link Call#SOURCE_INCALL_SERVICE}).
+         * @param extras The extras.
+         */
+        @Override
+        public void onExtrasChanged(Call call, int source, Bundle extras) {
+            // Do not inform InCallServices of changes which originated there.
+            if (source == Call.SOURCE_INCALL_SERVICE) {
+                return;
+            }
+            updateCall(call);
+        }
+
+        /**
+         * Listens for changes to extras reported by a Telecom {@link Call}.
+         *
+         * Extras changes can originate from a {@link ConnectionService} or an {@link InCallService}
+         * so we will only trigger an update of the call information if the source of the extras
+         * change was a {@link ConnectionService}.
+         *  @param call The call.
+         * @param source The source of the extras change ({@link Call#SOURCE_CONNECTION_SERVICE} or
+         *               {@link Call#SOURCE_INCALL_SERVICE}).
+         * @param keys The extra key removed
+         */
+        @Override
+        public void onExtrasRemoved(Call call, int source, List<String> keys) {
+            // Do not inform InCallServices of changes which originated there.
+            if (source == Call.SOURCE_INCALL_SERVICE) {
+                return;
+            }
+            updateCall(call);
+        }
+
+        /**
+         * Handles changes to the video state of a call.
+         * @param call
+         * @param previousVideoState
+         * @param newVideoState
+         */
+        @Override
+        public void onVideoStateChanged(Call call, int previousVideoState, int newVideoState) {
+            updateCall(call);
+        }
+
+        /**
+         * Relays a bluetooth call quality report received from the Bluetooth stack to the
+         * CallDiagnosticService.
+         * @param call The call.
+         * @param report The received report.
+         */
+        @Override
+        public void onBluetoothCallQualityReport(Call call, BluetoothCallQualityReport report) {
+            handleBluetoothCallQualityReport(call, report);
+        }
+
+        /**
+         * Relays a device to device message received from Telephony to the CallDiagnosticService.
+         * @param call
+         * @param messageType
+         * @param messageValue
+         */
+        @Override
+        public void onReceivedDeviceToDeviceMessage(Call call, int messageType, int messageValue) {
+            handleReceivedDeviceToDeviceMessage(call, messageType, messageValue);
+        }
+    };
+
+    /**
+     * {@link ServiceConnection} handling changes to binding of the {@link CallDiagnosticService}.
+     */
+    private class CallDiagnosticServiceConnection implements ServiceConnection {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            Log.startSession("CDSC.oSC", Log.getPackageAbbreviation(name));
+            try {
+                synchronized (mLock) {
+                    mCallDiagnosticService = ICallDiagnosticService.Stub.asInterface(service);
+
+                    handleConnectionComplete(mCallDiagnosticService);
+                }
+                Log.i(CallDiagnosticServiceController.this, "onServiceConnected: cmp=%s", name);
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            Log.startSession("CDSC.oSD", Log.getPackageAbbreviation(name));
+            try {
+                synchronized (mLock) {
+                    mCallDiagnosticService = null;
+                    mConnection = null;
+                }
+                Log.i(CallDiagnosticServiceController.this, "onServiceDisconnected: cmp=%s", name);
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
+        public void onBindingDied(ComponentName name) {
+            Log.startSession("CDSC.oBD", Log.getPackageAbbreviation(name));
+            try {
+                synchronized (mLock) {
+                    mCallDiagnosticService = null;
+                    mConnection = null;
+                }
+                Log.w(CallDiagnosticServiceController.this, "onBindingDied: cmp=%s", name);
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
+        public void onNullBinding(ComponentName name) {
+            Log.startSession("CDSC.oNB", Log.getPackageAbbreviation(name));
+            try {
+                synchronized (mLock) {
+                    maybeUnbindCallScreeningService();
+                }
+            } finally {
+                Log.endSession();
+            }
+        }
+    }
+
+    private final String mPackageName;
+    private final ContextProxy mContextProxy;
+    private String mTestPackageName;
+    private CallDiagnosticServiceConnection mConnection;
+    private CallDiagnosticServiceAdapter mAdapter;
+    private final TelecomSystem.SyncRoot mLock;
+    private ICallDiagnosticService mCallDiagnosticService;
+    private final CallIdMapper mCallIdMapper = new CallIdMapper(Call::getId);
+
+    public CallDiagnosticServiceController(@NonNull ContextProxy contextProxy,
+            @Nullable String packageName, @NonNull TelecomSystem.SyncRoot lock) {
+        mContextProxy = contextProxy;
+        mPackageName = packageName;
+        mLock = lock;
+    }
+
+    /**
+     * Handles Telecom adding new calls.  Will bind to the call diagnostic service if needed and
+     * send the calls, or send to an already bound service.
+     * @param call The call to add.
+     */
+    @Override
+    public void onCallAdded(@NonNull Call call) {
+        if (!call.isSimCall() || call.isExternalCall()) {
+            Log.i(this, "onCallAdded: skipping call %s as non-sim or external.", call.getId());
+            return;
+        }
+        if (mCallIdMapper.getCallId(call) == null) {
+            mCallIdMapper.addCall(call);
+            call.addListener(mCallListener);
+        }
+        if (isConnected()) {
+            sendCallToBoundService(call, mCallDiagnosticService);
+        } else {
+            maybeBindCallDiagnosticService();
+        }
+    }
+
+    /**
+     * Handles Telecom removal of calls; will remove the call from the bound service and if the
+     * number of tracked calls falls to zero, unbind from the service.
+     * @param call The call to remove from the bound CDS.
+     */
+    @Override
+    public void onCallRemoved(@NonNull Call call) {
+        if (!call.isSimCall() || call.isExternalCall()) {
+            Log.i(this, "onCallRemoved: skipping call %s as non-sim or external.", call.getId());
+            return;
+        }
+        mCallIdMapper.removeCall(call);
+        call.removeListener(mCallListener);
+        removeCallFromBoundService(call, mCallDiagnosticService);
+
+        if (mCallIdMapper.getCalls().size() == 0) {
+            maybeUnbindCallScreeningService();
+        }
+    }
+
+    @Override
+    public void onCallStateChanged(Call call, int oldState, int newState) {
+        updateCall(call);
+    }
+
+    @Override
+    public void onCallAudioStateChanged(CallAudioState oldCallAudioState,
+            CallAudioState newCallAudioState) {
+        if (mCallDiagnosticService != null) {
+            try {
+                mCallDiagnosticService.updateCallAudioState(newCallAudioState);
+            } catch (RemoteException e) {
+                Log.w(this, "onCallAudioStateChanged: failed %s", e);
+            }
+        }
+    }
+
+    /**
+     * Sets the test call diagnostic service; used by the telecom command line command to override
+     * the {@link CallDiagnosticService} to bind to for CTS test purposes.
+     * @param packageName The package name to set to.
+     */
+    public void setTestCallDiagnosticService(@Nullable String packageName) {
+        if (TextUtils.isEmpty(packageName)) {
+            mTestPackageName = null;
+        } else {
+            mTestPackageName = packageName;
+        }
+
+        Log.i(this, "setTestCallDiagnosticService: packageName=%s", packageName);
+    }
+
+    /**
+     * Determines the active call diagnostic service, taking into account the test override.
+     * @return The package name of the active call diagnostic service.
+     */
+    private @Nullable String getActiveCallDiagnosticService() {
+        if (mTestPackageName != null) {
+            return mTestPackageName;
+        }
+
+        return mPackageName;
+    }
+
+    /**
+     * If we are not already bound to the {@link CallDiagnosticService}, attempts to initiate a
+     * binding tho that service.
+     * @return {@code true} if we bound, {@code false} otherwise.
+     */
+    private boolean maybeBindCallDiagnosticService() {
+        if (mConnection != null) {
+            return false;
+        }
+
+        mConnection = new CallDiagnosticServiceConnection();
+        boolean bound = bindCallDiagnosticService(mContextProxy.getCurrentUserHandle(),
+                getActiveCallDiagnosticService(), mConnection);
+        if (!bound) {
+            mConnection = null;
+        }
+        return bound;
+    }
+
+    /**
+     * Performs binding to the {@link CallDiagnosticService}.
+     * @param userHandle user name to bind via.
+     * @param packageName package name of the CDS.
+     * @param serviceConnection The service connection to be notified of bind events.
+     * @return
+     */
+    private boolean bindCallDiagnosticService(UserHandle userHandle,
+            String packageName, CallDiagnosticServiceConnection serviceConnection) {
+
+        if (TextUtils.isEmpty(packageName)) {
+            Log.i(this, "bindCallDiagnosticService: no package; skip binding.");
+            return false;
+        }
+
+        Intent intent = new Intent(CallDiagnosticService.SERVICE_INTERFACE)
+                .setPackage(packageName);
+        Log.i(this, "bindCallDiagnosticService: user %d.", userHandle.getIdentifier());
+        List<ResolveInfo> entries = mContextProxy.queryIntentServicesAsUser(intent, 0,
+                userHandle.getIdentifier());
+        if (entries.isEmpty()) {
+            Log.i(this, "bindCallDiagnosticService: %s has no service.", packageName);
+            return false;
+        }
+
+        ResolveInfo entry = entries.get(0);
+        if (entry.serviceInfo == null) {
+            Log.i(this, "bindCallDiagnosticService: %s has no service info.", packageName);
+            return false;
+        }
+
+        if (entry.serviceInfo.permission == null || !entry.serviceInfo.permission.equals(
+                Manifest.permission.BIND_CALL_DIAGNOSTIC_SERVICE)) {
+            Log.i(this, "bindCallDiagnosticService: %s doesn't require "
+                    + "BIND_CALL_DIAGNOSTIC_SERVICE.", packageName);
+            return false;
+        }
+
+        ComponentName componentName =
+                new ComponentName(entry.serviceInfo.packageName, entry.serviceInfo.name);
+        intent.setComponent(componentName);
+        if (mContextProxy.bindServiceAsUser(
+                intent,
+                serviceConnection,
+                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+                UserHandle.CURRENT)) {
+            Log.d(this, "bindCallDiagnosticService, found service, waiting for it to connect");
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * If we are bound to a {@link CallDiagnosticService}, unbind from it.
+     */
+    public void maybeUnbindCallScreeningService() {
+        if (mConnection != null) {
+            Log.i(this, "maybeUnbindCallScreeningService - unbinding from %s",
+                    getActiveCallDiagnosticService());
+            try {
+                mContextProxy.unbindService(mConnection);
+                mCallDiagnosticService = null;
+                mConnection = null;
+            } catch (IllegalArgumentException e) {
+                Log.i(this, "maybeUnbindCallScreeningService: Exception when unbind %s : %s",
+                        getActiveCallDiagnosticService(), e.getMessage());
+            }
+        } else {
+            Log.w(this, "maybeUnbindCallScreeningService - already unbound");
+        }
+    }
+
+    /**
+     * Implements the abstracted Telecom functionality the {@link CallDiagnosticServiceAdapter}
+     * depends on.
+     */
+    private CallDiagnosticServiceAdapter.TelecomAdapter mTelecomAdapter =
+            new CallDiagnosticServiceAdapter.TelecomAdapter() {
+
+        @Override
+        public void displayDiagnosticMessage(String callId, int messageId, CharSequence message) {
+            handleDisplayDiagnosticMessage(callId, messageId, message);
+        }
+
+        @Override
+        public void clearDiagnosticMessage(String callId, int messageId) {
+            handleClearDiagnosticMessage(callId, messageId);
+        }
+
+        @Override
+        public void sendDeviceToDeviceMessage(String callId,
+                        @DiagnosticCall.MessageType int message, int value) {
+            handleSendD2DMessage(callId, message, value);
+        }
+
+        @Override
+        public void overrideDisconnectMessage(String callId, CharSequence message) {
+            handleOverrideDisconnectMessage(callId, message);
+        }
+    };
+
+    /**
+     * Sends all calls to the specified {@link CallDiagnosticService}.
+     * @param callDiagnosticService the CDS to send calls to.
+     */
+    private void handleConnectionComplete(@NonNull ICallDiagnosticService callDiagnosticService) {
+        mAdapter = new CallDiagnosticServiceAdapter(mTelecomAdapter,
+                getActiveCallDiagnosticService(), mLock);
+        try {
+            // Add adapter for communication back from the call diagnostic service to Telecom.
+            callDiagnosticService.setAdapter(mAdapter);
+
+            // Loop through all the calls we've got ready to send since binding.
+            for (Call call : mCallIdMapper.getCalls()) {
+                sendCallToBoundService(call, callDiagnosticService);
+            }
+        } catch (RemoteException e) {
+            Log.w(this, "handleConnectionComplete: error=%s", e);
+        }
+    }
+
+    /**
+     * Handles a request from a {@link CallDiagnosticService} to display a diagnostic message.
+     * @param callId the ID of the call to display the message for.
+     * @param message the message.
+     */
+    private void handleDisplayDiagnosticMessage(@NonNull String callId, int messageId,
+            @Nullable CharSequence message) {
+        Call call = mCallIdMapper.getCall(callId);
+        if (call == null) {
+            Log.w(this, "handleDisplayDiagnosticMessage: callId=%s; msg=%d/%s; invalid call",
+                    callId, messageId, message);
+            return;
+        }
+        Log.i(this, "handleDisplayDiagnosticMessage: callId=%s; msg=%d/%s; invalid call",
+                callId, messageId, message);
+        call.displayDiagnosticMessage(messageId, message);
+    }
+
+    /**
+     * Handles a request from a {@link CallDiagnosticService} to clear a previously displayed
+     * diagnostic message.
+     * @param callId the ID of the call to display the message for.
+     * @param messageId the message ID which was previous posted.
+     */
+    private void handleClearDiagnosticMessage(@NonNull String callId, int messageId) {
+        Call call = mCallIdMapper.getCall(callId);
+        if (call == null) {
+            Log.w(this, "handleClearDiagnosticMessage: callId=%s; msg=%d; invalid call",
+                    callId, messageId);
+            return;
+        }
+        Log.i(this, "handleClearDiagnosticMessage: callId=%s; msg=%d; invalid call",
+                callId, messageId);
+        call.clearDiagnosticMessage(messageId);
+    }
+
+    /**
+     * Handles a request from a {@link CallDiagnosticService} to send a device to device message.
+     * @param callId The ID of the call to send the D2D message for.
+     * @param message The message type.
+     * @param value The message value.
+     */
+    private void handleSendD2DMessage(@NonNull String callId,
+            @DiagnosticCall.MessageType int message, int value) {
+        Call call = mCallIdMapper.getCall(callId);
+        if (call == null) {
+            Log.w(this, "handleSendD2DMessage: callId=%s; msg=%d/%d; invalid call", callId,
+                    message, value);
+            return;
+        }
+        Log.i(this, "handleSendD2DMessage: callId=%s; msg=%d/%d", callId, message, value);
+        call.sendDeviceToDeviceMessage(message, value);
+    }
+
+    /**
+     * Handles a request from a {@link CallDiagnosticService} to override the disconnect message
+     * for a call.  This is the response path from a previous call into the
+     * {@link CallDiagnosticService} via {@link DiagnosticCall#onCallDisconnected(ImsReasonInfo)}.
+     * @param callId The telecom call ID the disconnect override is pending for.
+     * @param message The new disconnect message, or {@code null} if no override.
+     */
+    private void handleOverrideDisconnectMessage(@NonNull String callId,
+            @Nullable CharSequence message) {
+        Call call = mCallIdMapper.getCall(callId);
+        if (call == null) {
+            Log.w(this, "handleOverrideDisconnectMessage: callId=%s; msg=%s; invalid call", callId,
+                    message);
+            return;
+        }
+        Log.i(this, "handleOverrideDisconnectMessage: callId=%s; msg=%s", callId, message);
+        call.handleOverrideDisconnectMessage(message);
+    }
+
+    /**
+     * Sends a single call to the bound {@link CallDiagnosticService}.
+     * @param call The call to send.
+     * @param callDiagnosticService The CDS to send it to.
+     */
+    private void sendCallToBoundService(@NonNull Call call,
+            @NonNull ICallDiagnosticService callDiagnosticService) {
+        try {
+            if (isConnected()) {
+                Log.w(this, "sendCallToBoundService: initializing %s", call.getId());
+                callDiagnosticService.initializeDiagnosticCall(getParceledCall(call));
+            } else {
+                Log.w(this, "sendCallToBoundService: not bound, skipping %s", call.getId());
+            }
+        } catch (RemoteException e) {
+            Log.w(this, "sendCallToBoundService: callId=%s, exception=%s", call.getId(), e);
+        }
+    }
+
+    /**
+     * Removes a call from a bound {@link CallDiagnosticService}.
+     * @param call The call to remove.
+     * @param callDiagnosticService The CDS to remove it from.
+     */
+    private void removeCallFromBoundService(@NonNull Call call,
+            @NonNull ICallDiagnosticService callDiagnosticService) {
+        try {
+            if (isConnected()) {
+                callDiagnosticService.removeDiagnosticCall(call.getId());
+            }
+        } catch (RemoteException e) {
+            Log.w(this, "removeCallFromBoundService: callId=%s, exception=%s", call.getId(), e);
+        }
+    }
+
+    /**
+     * @return {@code true} if the call diagnostic service is bound/connected.
+     */
+    private boolean isConnected() {
+        return mCallDiagnosticService != null;
+    }
+
+    /**
+     * Updates the Call diagnostic service with changes to a call.
+     * @param call The updated call.
+     */
+    private void updateCall(@NonNull Call call) {
+        try {
+            if (isConnected()) {
+                mCallDiagnosticService.updateCall(getParceledCall(call));
+            }
+        } catch (RemoteException e) {
+            Log.w(this, "updateCall: callId=%s, exception=%s", call.getId(), e);
+        }
+    }
+
+    /**
+     * Updates the call diagnostic service with a received bluetooth quality report.
+     * @param call The call.
+     * @param report The bluetooth call quality report.
+     */
+    private void handleBluetoothCallQualityReport(@NonNull Call call,
+            @NonNull BluetoothCallQualityReport report) {
+        try {
+            if (isConnected()) {
+                mCallDiagnosticService.receiveBluetoothCallQualityReport(report);
+            }
+        } catch (RemoteException e) {
+            Log.w(this, "handleBluetoothCallQualityReport: callId=%s, exception=%s", call.getId(),
+                    e);
+        }
+    }
+
+    /**
+     * Informs a CallDiagnosticService of an incoming device to device message which was received
+     * via the carrier network.
+     * @param call the call the message was received via.
+     * @param messageType The message type.
+     * @param messageValue The message value.
+     */
+    private void handleReceivedDeviceToDeviceMessage(@NonNull Call call, int messageType,
+            int messageValue) {
+        try {
+            if (isConnected()) {
+                mCallDiagnosticService.receiveDeviceToDeviceMessage(call.getId(), messageType,
+                        messageValue);
+            }
+        } catch (RemoteException e) {
+            Log.w(this, "handleReceivedDeviceToDeviceMessage: callId=%s, exception=%s",
+                    call.getId(), e);
+        }
+    }
+
+    /**
+     * Get a parcelled representation of a call for transport to the service.
+     * @param call The call.
+     * @return The parcelled call.
+     */
+    private @NonNull ParcelableCall getParceledCall(@NonNull Call call) {
+        return ParcelableCallUtils.toParcelableCall(
+                call,
+                false /* includeVideoProvider */,
+                null /* phoneAcctRegistrar */,
+                false /* supportsExternalCalls */,
+                false /* includeRttCall */,
+                false /* isForSystemDialer */
+        );
+    }
+
+    /**
+     * Dumps the state of the {@link CallDiagnosticServiceController}.
+     *
+     * @param pw The {@code IndentingPrintWriter} to write the state to.
+     */
+    public void dump(IndentingPrintWriter pw) {
+        pw.print("activeCallDiagnosticService: ");
+        pw.println(getActiveCallDiagnosticService());
+        pw.print("isConnected: ");
+        pw.println(isConnected());
+    }
+}
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 5b3c2f7..7742422 100755
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -332,6 +332,7 @@
     private final ConnectionServiceRepository mConnectionServiceRepository;
     private final DtmfLocalTonePlayer mDtmfLocalTonePlayer;
     private final InCallController mInCallController;
+    private final CallDiagnosticServiceController mCallDiagnosticServiceController;
     private final CallAudioManager mCallAudioManager;
     private final CallRecordingTonePlayer mCallRecordingTonePlayer;
     private RespondViaSmsManager mRespondViaSmsManager;
@@ -487,6 +488,7 @@
             CallAudioRouteStateMachine.Factory callAudioRouteStateMachineFactory,
             CallAudioModeStateMachine.Factory callAudioModeStateMachineFactory,
             InCallControllerFactory inCallControllerFactory,
+            CallDiagnosticServiceController callDiagnosticServiceController,
             RoleManagerAdapter roleManagerAdapter,
             ToastFactory toastFactory) {
         mContext = context;
@@ -543,6 +545,7 @@
         mInCallController = inCallControllerFactory.create(context, mLock, this,
                 systemStateHelper, defaultDialerCache, mTimeoutsAdapter,
                 emergencyCallHelper);
+        mCallDiagnosticServiceController = callDiagnosticServiceController;
         mRinger = new Ringer(playerFactory, context, systemSettingsUtil, asyncRingtonePlayer,
                 ringtoneFactory, systemVibrator,
                 new Ringer.VibrationEffectProxy(), mInCallController);
@@ -572,6 +575,7 @@
         mListeners.add(mCallLogManager);
         mListeners.add(mPhoneStateBroadcaster);
         mListeners.add(mInCallController);
+        mListeners.add(mCallDiagnosticServiceController);
         mListeners.add(mCallAudioManager);
         mListeners.add(mCallRecordingTonePlayer);
         mListeners.add(missedCallNotifier);
@@ -622,6 +626,10 @@
         return mRoleManagerAdapter;
     }
 
+    public CallDiagnosticServiceController getCallDiagnosticServiceController() {
+        return mCallDiagnosticServiceController;
+    }
+
     @Override
     public void onSuccessfulOutgoingCall(Call call, int callState) {
         Log.v(this, "onSuccessfulOutgoingCall, %s", call);
@@ -2736,6 +2744,16 @@
         updateCanAddCall();
     }
 
+    @Override
+    public void onRemoteRttRequest(Call call, int requestId) {
+        Log.i(this, "onRemoteRttRequest: call %s", call.getId());
+        playRttUpgradeToneForCall(call);
+    }
+
+    public void playRttUpgradeToneForCall(Call call) {
+        mCallAudioManager.playRttUpgradeTone(call);
+    }
+
     // Construct the list of possible PhoneAccounts that the outgoing call can use based on the
     // active calls in CallsManager. If any of the active calls are on a SIM based PhoneAccount,
     // then include only that SIM based PhoneAccount and any non-SIM PhoneAccounts, such as SIP.
@@ -3084,7 +3102,11 @@
                 Log.i(this, "Auto-unholding held foreground call (call doesn't support hold)");
                 foregroundCall.unhold();
             }
-        }, new LoggedHandlerExecutor(mHandler, "CM.mCAR", mLock));
+        }, new LoggedHandlerExecutor(mHandler, "CM.mCAR", mLock))
+                .exceptionally((throwable) -> {
+                    Log.e(TAG, throwable, "Error while executing call removal");
+                    return null;
+                });
     }
 
     /**
@@ -3631,22 +3653,8 @@
                 Trace.beginSection("onCallStateChanged");
 
                 maybeHandleHandover(call, newState);
+                notifyCallStateChanged(call, oldState, newState);
 
-                // Only broadcast state change for calls that are being tracked.
-                if (mCalls.contains(call)) {
-                    updateCanAddCall();
-                    updateHasActiveRttCall();
-                    for (CallsManagerListener listener : mListeners) {
-                        if (LogUtils.SYSTRACE_DEBUG) {
-                            Trace.beginSection(listener.getClass().toString() +
-                                    " onCallStateChanged");
-                        }
-                        listener.onCallStateChanged(call, oldState, newState);
-                        if (LogUtils.SYSTRACE_DEBUG) {
-                            Trace.endSection();
-                        }
-                    }
-                }
                 Trace.endSection();
             } else {
                 Log.i(this, "failed in setting the state to new state");
@@ -3654,6 +3662,24 @@
         }
     }
 
+    private void notifyCallStateChanged(Call call, int oldState, int newState) {
+        // Only broadcast state change for calls that are being tracked.
+        if (mCalls.contains(call)) {
+            updateCanAddCall();
+            updateHasActiveRttCall();
+            for (CallsManagerListener listener : mListeners) {
+                if (LogUtils.SYSTRACE_DEBUG) {
+                    Trace.beginSection(listener.getClass().toString() +
+                            " onCallStateChanged");
+                }
+                listener.onCallStateChanged(call, oldState, newState);
+                if (LogUtils.SYSTRACE_DEBUG) {
+                    Trace.endSection();
+                }
+            }
+        }
+    }
+
     /**
      * Identifies call state transitions for a call which trigger handover events.
      * - If this call has a handover to it which just started and this call goes active, treat
@@ -4691,6 +4717,13 @@
             pw.decreaseIndent();
         }
 
+        if (mCallDiagnosticServiceController != null) {
+            pw.println("mCallDiagnosticServiceController:");
+            pw.increaseIndent();
+            mCallDiagnosticServiceController.dump(pw);
+            pw.decreaseIndent();
+        }
+
         if (mDefaultDialerCache != null) {
             pw.println("mDefaultDialerCache:");
             pw.increaseIndent();
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index e46d377..b138eae 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -1348,7 +1348,7 @@
     /**
      * Unbinds an existing bound connection to the in-call app.
      */
-    private void unbindFromServices() {
+    public void unbindFromServices() {
         try {
             mContext.unregisterReceiver(mPackageChangedReceiver);
         } catch (IllegalArgumentException e) {
diff --git a/src/com/android/server/telecom/InCallTonePlayer.java b/src/com/android/server/telecom/InCallTonePlayer.java
index 4f0cf8d..7500436 100644
--- a/src/com/android/server/telecom/InCallTonePlayer.java
+++ b/src/com/android/server/telecom/InCallTonePlayer.java
@@ -162,6 +162,8 @@
     public static final int TONE_UNOBTAINABLE_NUMBER = 12;
     public static final int TONE_VOICE_PRIVACY = 13;
     public static final int TONE_VIDEO_UPGRADE = 14;
+    public static final int TONE_RTT_REQUEST = 15;
+    public static final int TONE_IN_CALL_QUALITY_NOTIFICATION = 16;
 
     private static final int TONE_RESOURCE_ID_UNDEFINED = -1;
 
@@ -329,12 +331,22 @@
                     // TODO: fill in.
                     throw new IllegalStateException("Voice privacy tone NYI.");
                 case TONE_VIDEO_UPGRADE:
+                case TONE_RTT_REQUEST:
                     // Similar to the call waiting tone, but does not repeat.
                     toneType = ToneGenerator.TONE_SUP_CALL_WAITING;
                     toneVolume = RELATIVE_VOLUME_HIPRI;
                     toneLengthMillis = 4000;
                     mediaResourceId = TONE_RESOURCE_ID_UNDEFINED;
                     break;
+                case TONE_IN_CALL_QUALITY_NOTIFICATION:
+                    // Don't use tone generator
+                    toneType = ToneGenerator.TONE_UNKNOWN;
+                    toneVolume = RELATIVE_VOLUME_UNDEFINED;
+                    toneLengthMillis = 0;
+
+                    // Use a tone resource file for a more rich, full-bodied tone experience.
+                    mediaResourceId = R.raw.InCallQualityNotification;
+                    break;
                 default:
                     throw new IllegalStateException("Bad toneId: " + mToneId);
             }
diff --git a/src/com/android/server/telecom/LogUtils.java b/src/com/android/server/telecom/LogUtils.java
index e4a414b..a9bf18c 100644
--- a/src/com/android/server/telecom/LogUtils.java
+++ b/src/com/android/server/telecom/LogUtils.java
@@ -196,6 +196,7 @@
         public static final String REDIRECTION_USER_CONFIRMATION = "REDIRECTION_USER_CONFIRMATION";
         public static final String REDIRECTION_USER_CONFIRMED = "REDIRECTION_USER_CONFIRMED";
         public static final String REDIRECTION_USER_CANCELLED = "REDIRECTION_USER_CANCELLED";
+        public static final String BT_QUALITY_REPORT = "BT_QUALITY_REPORT";
 
         public static class Timings {
             public static final String ACCEPT_TIMING = "accept";
diff --git a/src/com/android/server/telecom/RespondViaSmsManager.java b/src/com/android/server/telecom/RespondViaSmsManager.java
index 00d94f0..23ccc1c 100644
--- a/src/com/android/server/telecom/RespondViaSmsManager.java
+++ b/src/com/android/server/telecom/RespondViaSmsManager.java
@@ -204,7 +204,7 @@
             for (int i = 0; i < messageParts.size(); i++) {
                 Intent intent = new Intent(ACTION_MESSAGE_SENT);
                 PendingIntent pendingIntent = PendingIntent.getBroadcast(context, i, intent,
-                        PendingIntent.FLAG_ONE_SHOT);
+                        PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
                 sentIntents.add(pendingIntent);
             }
             MessageSentReceiver receiver = new MessageSentReceiver(
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 3a44287..69ffd26 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -1790,6 +1790,7 @@
                                 mCallsManager.markCallAsRemoved(call);
                             }
                         }
+                        mCallsManager.getInCallController().unbindFromServices();
                     });
                 }
             } finally {
@@ -1899,6 +1900,30 @@
                 Log.endSession();
             }
         }
+
+        @Override
+        public void setTestCallDiagnosticService(String packageName) {
+            try {
+                Log.startSession("TSI.sTCDS");
+                enforceModifyPermission();
+                enforceShellOnly(Binder.getCallingUid(), "setTestCallDiagnosticService is for "
+                        + "shell use only.");
+                synchronized (mLock) {
+                    long token = Binder.clearCallingIdentity();
+                    try {
+                        CallDiagnosticServiceController controller =
+                                mCallsManager.getCallDiagnosticServiceController();
+                        if (controller != null) {
+                            controller.setTestCallDiagnosticService(packageName);
+                        }
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+            } finally {
+                Log.endSession();
+            }
+        }
     };
 
     /**
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index 8928e76..5f6b62a 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -36,8 +36,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.ServiceConnection;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.net.Uri;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -45,8 +47,11 @@
 import android.telecom.PhoneAccountHandle;
 import android.widget.Toast;
 
+import androidx.annotation.NonNull;
+
 import java.io.FileNotFoundException;
 import java.io.InputStream;
+import java.util.List;
 
 /**
  * Top-level Application class for Telecom.
@@ -260,6 +265,39 @@
             }
         };
 
+        CallDiagnosticServiceController callDiagnosticServiceController =
+                new CallDiagnosticServiceController(
+                        new CallDiagnosticServiceController.ContextProxy() {
+                            @Override
+                            public List<ResolveInfo> queryIntentServicesAsUser(
+                                    @NonNull Intent intent, int flags, int userId) {
+                                return mContext.getPackageManager().queryIntentServicesAsUser(
+                                        intent, flags, userId);
+                            }
+
+                            @Override
+                            public boolean bindServiceAsUser(@NonNull Intent service,
+                                    @NonNull ServiceConnection conn, int flags,
+                                    @NonNull UserHandle user) {
+                                return mContext.bindServiceAsUser(service, conn, flags, user);
+                            }
+
+                            @Override
+                            public void unbindService(@NonNull ServiceConnection conn) {
+                                mContext.unbindService(conn);
+                            }
+
+                            @Override
+                            public UserHandle getCurrentUserHandle() {
+                                return mCallsManager.getCurrentUserHandle();
+                            }
+                        },
+                        mContext.getResources().getString(
+                                com.android.server.telecom.R.string
+                                        .call_diagnostic_service_package_name),
+                        mLock
+                );
+
         AudioProcessingNotification audioProcessingNotification =
                 new AudioProcessingNotification(mContext);
 
@@ -303,6 +341,7 @@
                 callAudioRouteStateMachineFactory,
                 callAudioModeStateMachineFactory,
                 inCallControllerFactory,
+                callDiagnosticServiceController,
                 roleManagerAdapter,
                 toastFactory);
 
diff --git a/src/com/android/server/telecom/ui/DisconnectedCallNotifier.java b/src/com/android/server/telecom/ui/DisconnectedCallNotifier.java
index 3f54689..66f9fe4 100644
--- a/src/com/android/server/telecom/ui/DisconnectedCallNotifier.java
+++ b/src/com/android/server/telecom/ui/DisconnectedCallNotifier.java
@@ -333,7 +333,8 @@
             UserHandle userHandle) {
         Intent intent = new Intent(action, data, mContext, TelecomBroadcastReceiver.class);
         intent.putExtra(TelecomBroadcastIntentProcessor.EXTRA_USERHANDLE, userHandle);
-        return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+        return PendingIntent.getBroadcast(mContext, 0, intent,
+                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
     }
 
     private boolean canRespondViaSms(@NonNull CallInfo call) {
@@ -354,7 +355,7 @@
         TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(mContext);
         taskStackBuilder.addNextIntent(intent);
 
-        return taskStackBuilder.getPendingIntent(0, 0, null, userHandle);
+        return taskStackBuilder.getPendingIntent(0, PendingIntent.FLAG_IMMUTABLE, null, userHandle);
     }
 
     /**
diff --git a/testapps/AndroidManifest.xml b/testapps/AndroidManifest.xml
index 891a7a7..dd8258a 100644
--- a/testapps/AndroidManifest.xml
+++ b/testapps/AndroidManifest.xml
@@ -39,6 +39,13 @@
         <uses-library android:name="android.test.runner"/>
 
         <!-- Miscellaneous telecom app-related test activities. -->
+        <service android:name="com.android.server.telecom.testapps.TestCallDiagnosticService"
+            android:permission="android.permission.BIND_CALL_DIAGNOSTIC_SERVICE"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.telecom.CallDiagnosticService"/>
+            </intent-filter>
+        </service>
 
         <service android:name="com.android.server.telecom.testapps.TestConnectionService"
              android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
diff --git a/testapps/src/com/android/server/telecom/testapps/TestCallDiagnosticService.java b/testapps/src/com/android/server/telecom/testapps/TestCallDiagnosticService.java
new file mode 100644
index 0000000..73bf438
--- /dev/null
+++ b/testapps/src/com/android/server/telecom/testapps/TestCallDiagnosticService.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package com.android.server.telecom.testapps;
+
+import android.telecom.BluetoothCallQualityReport;
+import android.telecom.Call;
+import android.telecom.CallAudioState;
+import android.telecom.CallDiagnosticService;
+import android.telecom.DiagnosticCall;
+import android.telecom.Log;
+import android.telephony.CallQuality;
+import android.telephony.ims.ImsReasonInfo;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+public class TestCallDiagnosticService extends CallDiagnosticService {
+
+    public static final class TestDiagnosticCall extends DiagnosticCall {
+        public Call.Details details;
+
+        TestDiagnosticCall(Call.Details details) {
+            this.details = details;
+        }
+
+        @Override
+        public void onCallDetailsChanged(@NonNull Call.Details details) {
+            Log.i(this, "onCallDetailsChanged; %s", details);
+        }
+
+        @Override
+        public void onReceiveDeviceToDeviceMessage(int message, int value) {
+            Log.i(this, "onReceiveDeviceToDeviceMessage; %d/%d", message, value);
+        }
+
+        @Nullable
+        @Override
+        public CharSequence onCallDisconnected(int disconnectCause, int preciseDisconnectCause) {
+            Log.i(this, "onCallDisconnected");
+            return null;
+        }
+
+        @Nullable
+        @Override
+        public CharSequence onCallDisconnected(@NonNull ImsReasonInfo disconnectReason) {
+            Log.i(this, "onCallDisconnected");
+            return null;
+        }
+
+        @Override
+        public void onCallQualityReceived(@NonNull CallQuality callQuality) {
+            Log.i(this, "onCallQualityReceived %s", callQuality);
+        }
+    }
+
+    @NonNull
+    @Override
+    public DiagnosticCall onInitializeDiagnosticCall(@NonNull Call.Details call) {
+        Log.i(this, "onInitiatlizeDiagnosticCall %s", call);
+        return new TestDiagnosticCall(call);
+    }
+
+    @Override
+    public void onRemoveDiagnosticCall(@NonNull DiagnosticCall call) {
+        Log.i(this, "onRemoveDiagnosticCall %s", call);
+    }
+
+    @Override
+    public void onCallAudioStateChanged(@NonNull CallAudioState audioState) {
+        Log.i(this, "onCallAudioStateChanged %s", audioState);
+    }
+
+    @Override
+    public void onBluetoothCallQualityReportReceived(
+            @NonNull BluetoothCallQualityReport qualityReport) {
+        Log.i(this, "onBluetoothCallQualityReportReceived %s", qualityReport);
+    }
+}
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
index 5592cf4..976a4da 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
@@ -276,6 +276,10 @@
 
         waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);
         verifyNewSystemCallAudioState(initState, expectedMidState);
+        // clear out the handler state before resetting mocks in order to avoid introducing a
+        // CallAudioState that has a null list of supported BT devices
+        waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);
+        waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);
         resetMocks();
 
         // Now, switch back to BT explicitly
diff --git a/tests/src/com/android/server/telecom/tests/CallDiagnosticServiceControllerTest.java b/tests/src/com/android/server/telecom/tests/CallDiagnosticServiceControllerTest.java
new file mode 100644
index 0000000..d420f1d
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/CallDiagnosticServiceControllerTest.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package com.android.server.telecom.tests;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.Manifest;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.telecom.ParcelableCall;
+
+import com.android.internal.telecom.ICallDiagnosticService;
+import com.android.server.telecom.Call;
+import com.android.server.telecom.CallDiagnosticServiceController;
+import com.android.server.telecom.TelecomSystem;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public class CallDiagnosticServiceControllerTest {
+    private static final String TEST_CDS_PACKAGE = "com.test.stuff";
+    private static final String TEST_PACKAGE = "com.android.telecom.calldiagnosticservice";
+    private static final String TEST_CLASS =
+            "com.android.telecom.calldiagnosticservice.TestService";
+    private static final ComponentName TEST_COMPONENT = new ComponentName(TEST_PACKAGE, TEST_CLASS);
+    private static final List<ResolveInfo> RESOLVE_INFOS = new ArrayList<>();
+    private static final ResolveInfo TEST_RESOLVE_INFO = new ResolveInfo();
+    static {
+        TEST_RESOLVE_INFO.serviceInfo = new ServiceInfo();
+        TEST_RESOLVE_INFO.serviceInfo.packageName = TEST_PACKAGE;
+        TEST_RESOLVE_INFO.serviceInfo.name = TEST_CLASS;
+        TEST_RESOLVE_INFO.serviceInfo.permission = Manifest.permission.BIND_CALL_DIAGNOSTIC_SERVICE;
+        RESOLVE_INFOS.add(TEST_RESOLVE_INFO);
+    }
+    private static final String ID_1 = "1";
+    private static final String ID_2 = "2";
+
+    @Mock
+    private CallDiagnosticServiceController.ContextProxy mContextProxy;
+    @Mock
+    private Call mCall;
+    @Mock
+    private Call mCallTwo;
+    @Mock
+    private ICallDiagnosticService mICallDiagnosticService;
+    private TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };
+
+    private CallDiagnosticServiceController mCallDiagnosticService;
+    private ServiceConnection mServiceConnection;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        when(mCall.getId()).thenReturn(ID_1);
+        when(mCall.isSimCall()).thenReturn(true);
+        when(mCall.isExternalCall()).thenReturn(false);
+
+        when(mCallTwo.getId()).thenReturn(ID_2);
+        when(mCallTwo.isSimCall()).thenReturn(true);
+        when(mCallTwo.isExternalCall()).thenReturn(false);
+        mServiceConnection = null;
+
+        // Mock out the context and other junk that we depend on.
+        when(mContextProxy.queryIntentServicesAsUser(any(Intent.class), anyInt(), anyInt()))
+                .thenReturn(RESOLVE_INFOS);
+        when(mContextProxy.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class),
+                anyInt(), any(UserHandle.class))).thenReturn(true);
+        when(mContextProxy.getCurrentUserHandle()).thenReturn(UserHandle.CURRENT);
+
+        mCallDiagnosticService = new CallDiagnosticServiceController(mContextProxy,
+                TEST_PACKAGE, mLock);
+    }
+
+    /**
+     * Verify no binding takes place for a non-sim call.
+     */
+    @Test
+    public void testNoBindOnNonSimCall() {
+        Call mockCall = Mockito.mock(Call.class);
+        when(mockCall.isSimCall()).thenReturn(false);
+
+        mCallDiagnosticService.onCallAdded(mockCall);
+
+        verify(mContextProxy, never()).bindServiceAsUser(any(Intent.class),
+                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+    }
+
+    /**
+     * Verify no binding takes place for a SIM external call.
+     */
+    @Test
+    public void testNoBindOnExternalCall() {
+        Call mockCall = Mockito.mock(Call.class);
+        when(mockCall.isSimCall()).thenReturn(true);
+        when(mockCall.isExternalCall()).thenReturn(true);
+
+        mCallDiagnosticService.onCallAdded(mockCall);
+
+        verify(mContextProxy, never()).bindServiceAsUser(any(Intent.class),
+                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+    }
+
+    /**
+     * Verify a valid SIM call causes binding to initiate.
+     */
+    @Test
+    public void testAddSimCallCausesBind() throws RemoteException {
+        mCallDiagnosticService.onCallAdded(mCall);
+
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        ArgumentCaptor<ServiceConnection> serviceConnectionCaptor = ArgumentCaptor.forClass(
+                ServiceConnection.class);
+        verify(mContextProxy).bindServiceAsUser(intentCaptor.capture(),
+                serviceConnectionCaptor.capture(), anyInt(), any(UserHandle.class));
+        assertEquals(TEST_PACKAGE, intentCaptor.getValue().getPackage());
+
+        // Now we'll pretend bind completed and we sent back the binder.
+        IBinder mockBinder = mock(IBinder.class);
+        when(mockBinder.queryLocalInterface(anyString())).thenReturn(mICallDiagnosticService);
+        serviceConnectionCaptor.getValue().onServiceConnected(TEST_COMPONENT, mockBinder);
+        mServiceConnection = serviceConnectionCaptor.getValue();
+
+        // Make sure it's sent
+        verify(mICallDiagnosticService).initializeDiagnosticCall(any(ParcelableCall.class));
+    }
+
+    /**
+     * Verify removing the active call causes it to be removed from the CallDiagnosticService and
+     * that an unbind takes place.
+     */
+    @Test
+    public void testRemoveSimCallCausesRemoveAndUnbind() throws RemoteException {
+        testAddSimCallCausesBind();
+        mCallDiagnosticService.onCallRemoved(mCall);
+
+        verify(mICallDiagnosticService).removeDiagnosticCall(eq(ID_1));
+        verify(mContextProxy).unbindService(eq(mServiceConnection));
+    }
+
+    /**
+     * Try to add and remove two and verify bind/unbind.
+     */
+    @Test
+    public void testAddTwo() throws RemoteException {
+        testAddSimCallCausesBind();
+        mCallDiagnosticService.onCallAdded(mCallTwo);
+        verify(mICallDiagnosticService, times(2)).initializeDiagnosticCall(
+                any(ParcelableCall.class));
+
+        mCallDiagnosticService.onCallRemoved(mCall);
+        // Not yet!
+        verify(mContextProxy, never()).unbindService(eq(mServiceConnection));
+
+        mCallDiagnosticService.onCallRemoved(mCallTwo);
+
+        verify(mICallDiagnosticService).removeDiagnosticCall(eq(ID_1));
+        verify(mICallDiagnosticService).removeDiagnosticCall(eq(ID_2));
+        verify(mContextProxy).unbindService(eq(mServiceConnection));
+    }
+
+    /**
+     * Verifies we can override the call diagnostic service package to a test package (used by CTS
+     * tests).
+     */
+    @Test
+    public void testTestOverride() {
+        mCallDiagnosticService.setTestCallDiagnosticService(TEST_CDS_PACKAGE);
+        mCallDiagnosticService.onCallAdded(mCall);
+
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContextProxy).bindServiceAsUser(intentCaptor.capture(),
+                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+        assertEquals(TEST_CDS_PACKAGE, intentCaptor.getValue().getPackage());
+    }
+}
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
index 8378e3b..08f3536 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -67,6 +67,7 @@
 import com.android.server.telecom.CallAudioManager;
 import com.android.server.telecom.CallAudioModeStateMachine;
 import com.android.server.telecom.CallAudioRouteStateMachine;
+import com.android.server.telecom.CallDiagnosticServiceController;
 import com.android.server.telecom.CallState;
 import com.android.server.telecom.CallerInfoLookupHelper;
 import com.android.server.telecom.CallsManager;
@@ -196,6 +197,7 @@
     @Mock private CallAudioRouteStateMachine.Factory mCallAudioRouteStateMachineFactory;
     @Mock private CallAudioModeStateMachine mCallAudioModeStateMachine;
     @Mock private CallAudioModeStateMachine.Factory mCallAudioModeStateMachineFactory;
+    @Mock private CallDiagnosticServiceController mCallDiagnosticServiceController;
     @Mock private BluetoothStateReceiver mBluetoothStateReceiver;
     @Mock private RoleManagerAdapter mRoleManagerAdapter;
     @Mock private ToastFactory mToastFactory;
@@ -253,6 +255,7 @@
                 mCallAudioRouteStateMachineFactory,
                 mCallAudioModeStateMachineFactory,
                 mInCallControllerFactory,
+                mCallDiagnosticServiceController,
                 mRoleManagerAdapter,
                 mToastFactory);