DO NOT MERGE - Skip pi-platform-release (PPRL.190505.001) in stage-aosp-master

Bug: 132622481
Change-Id: I5307c500d3948e733c02366b9950ee1fc8b82600
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..629c95c
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,77 @@
+// Build the Telecom service.
+android_app {
+    name: "Telecom",
+    libs: ["telephony-common"],
+    srcs: [
+        "src/**/*.java",
+        "proto/**/*.proto",
+    ],
+    resource_dirs: ["res"],
+    proto: {
+        type: "nano",
+        local_include_dirs: ["proto/"],
+        output_params: ["optional_field_style=accessors"],
+    },
+    platform_apis: true,
+    certificate: "platform",
+    privileged: true,
+    optimize: {
+        proguard_flags_files: ["proguard.flags"],
+    },
+    defaults: ["SettingsLibDefaults"],
+}
+
+android_test {
+    name: "TelecomUnitTests",
+    static_libs: [
+        "android-ex-camera2",
+        "guava",
+        "mockito-target-inline",
+        "androidx.test.rules",
+        "platform-test-annotations",
+        "androidx.legacy_legacy-support-core-ui",
+        "androidx.legacy_legacy-support-core-utils",
+        "androidx.core_core",
+        "androidx.fragment_fragment",
+    ],
+    srcs: [
+        "tests/src/**/*.java",
+        "src/**/*.java",
+        "proto/**/*.proto",
+    ],
+    proto: {
+        type: "nano",
+        local_include_dirs: ["proto/"],
+        output_params: ["optional_field_style=accessors"],
+    },
+    resource_dirs: [
+        "tests/res",
+        "res",
+    ],
+    libs: [
+        "android.test.mock",
+        "android.test.base",
+        "android.test.runner",
+        "telephony-common",
+    ],
+
+    jni_libs: ["libdexmakerjvmtiagent"],
+
+    aaptflags: [
+        "--auto-add-overlay",
+        "--extra-packages",
+        "com.android.server.telecom",
+    ],
+    manifest: "tests/AndroidManifest.xml",
+    optimize: {
+        enabled: false,
+    },
+    platform_apis: true,
+    certificate: "platform",
+    jacoco: {
+        include_filter: ["com.android.server.telecom.*"],
+        exclude_filter: ["com.android.server.telecom.tests.*"],
+    },
+    test_suites: ["device-tests"],
+    defaults: ["SettingsLibDefaults"],
+}
diff --git a/Android.mk b/Android.mk
deleted file mode 100644
index 4e5eeff..0000000
--- a/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# Build the Telecom service.
-include $(CLEAR_VARS)
-
-LOCAL_JAVA_LIBRARIES := telephony-common
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-proto-files-under, proto)
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_USE_AAPT2 := true
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/proto/
-LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
-
-LOCAL_PACKAGE_NAME := Telecom
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_CERTIFICATE := platform
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-include frameworks/base/packages/SettingsLib/common.mk
-
-include $(BUILD_PACKAGE)
-
-# Build the test package.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 588e5c3..bec37da 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -21,6 +21,8 @@
         android:sharedUserId="android.uid.system">
 
     <protected-broadcast android:name="android.intent.action.SHOW_MISSED_CALLS_NOTIFICATION" />
+    <protected-broadcast android:name="com.android.server.telecom.MESSAGE_SENT" />
+
 
     <!-- Prevents the activity manager from delaying any activity-start
          requests by this package, including requests immediately after
@@ -32,6 +34,7 @@
     <uses-permission android:name="android.permission.BROADCAST_CALLLOG_INFO" />
     <uses-permission android:name="android.permission.BROADCAST_PHONE_ACCOUNT_REGISTRATION" />
     <uses-permission android:name="android.permission.CALL_PRIVILEGED" />
+    <uses-permission android:name="android.permission.HANDLE_CALL_INTENT" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
     <uses-permission android:name="android.permission.MANAGE_USERS" />
@@ -41,6 +44,7 @@
     <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
     <uses-permission android:name="android.permission.READ_CALL_LOG" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.SEND_SMS" />
     <uses-permission android:name="android.permission.STOP_APP_SWITCHES" />
     <uses-permission android:name="android.permission.VIBRATE" />
     <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
@@ -69,6 +73,11 @@
             android:label="Process phone account registration"
             android:protectionLevel="signature|system"/>
 
+    <permission
+            android:name="android.permission.HANDLE_CALL_INTENT"
+            android:label="Protects handling the call intent via the TelecomManager API."
+            android:protectionLevel="signature|system"/>
+
     <application android:label="@string/telecommAppLabel"
             android:icon="@mipmap/ic_launcher_phone"
             android:allowBackup="false"
@@ -227,10 +236,12 @@
                 <action android:name="com.android.server.telecom.ACTION_REJECT_FROM_NOTIFICATION" />
                 <action android:name="com.android.server.telecom.PROCEED_WITH_CALL" />
                 <action android:name="com.android.server.telecom.CANCEL_CALL" />
+                <action android:name="com.android.server.telecom.PROCEED_WITH_REDIRECTED_CALL" />
+                <action android:name="com.android.server.telecom.CANCEL_REDIRECTED_CALL" />
             </intent-filter>
         </receiver>
 
-        <receiver android:name=".components.PhoneAccountBroadcastReceiver"
+        <receiver android:name=".components.AppUninstallBroadcastReceiver"
                 android:process="system">
             <intent-filter>
                 <action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
@@ -277,6 +288,22 @@
                 android:process=":ui">
         </activity>
 
+        <activity android:name=".ui.CallRedirectionConfirmDialogActivity"
+                  android:configChanges="orientation|screenSize|keyboardHidden"
+                  android:excludeFromRecents="true"
+                  android:launchMode="singleInstance"
+                  android:theme="@style/Theme.Telecomm.Transparent"
+                  android:process=":ui">
+        </activity>
+
+        <activity android:name=".ui.CallRedirectionTimeoutDialogActivity"
+                  android:configChanges="orientation|screenSize|keyboardHidden"
+                  android:excludeFromRecents="true"
+                  android:launchMode="singleInstance"
+                  android:theme="@style/Theme.Telecomm.Transparent"
+                  android:process=":ui">
+        </activity>
+
         <activity android:name=".components.ChangeDefaultDialerDialog"
                   android:label="@string/change_default_dialer_dialog_title"
                   android:excludeFromRecents="true"
@@ -289,11 +316,10 @@
             </intent-filter>
         </activity>
 
-        <receiver android:name=".components.PrimaryCallReceiver"
-                android:exported="true"
-                android:permission="android.permission.MODIFY_PHONE_STATE"
-                android:process="system">
-        </receiver>
+        <activity android:name=".ui.TelecomDeveloperMenu"
+                  android:label="@string/developer_title"
+                  android:exported="false"
+                  android:process=":ui" />
 
         <service android:name=".components.BluetoothPhoneService"
                 android:singleUser="true"
diff --git a/OWNERS b/OWNERS
index 2f0bcec..94409ef 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,3 +1,4 @@
 breadley@google.com
 hallliu@google.com
 tgunn@google.com
+paulye@google.com
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..9874044
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,2 @@
+[Hook Scripts]
+aosp_hook = ${REPO_ROOT}/packages/services/Telecomm/scripts/aosp_tag_preupload.py ${PREUPLOAD_COMMIT}
diff --git a/res/drawable/call_redirection_button_ripple_effect.xml b/res/drawable/call_redirection_button_ripple_effect.xml
new file mode 100644
index 0000000..b690c93
--- /dev/null
+++ b/res/drawable/call_redirection_button_ripple_effect.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 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
+  -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="?android:attr/colorControlHighlight" />
\ No newline at end of file
diff --git a/res/drawable/call_redirection_dialog_background.xml b/res/drawable/call_redirection_dialog_background.xml
new file mode 100644
index 0000000..71277fd
--- /dev/null
+++ b/res/drawable/call_redirection_dialog_background.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 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
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@android:color/white"/>
+    <corners android:radius="15dp" />
+</shape>
\ No newline at end of file
diff --git a/res/layout/call_redirection_confirm_dialog.xml b/res/layout/call_redirection_confirm_dialog.xml
new file mode 100644
index 0000000..98d78c8
--- /dev/null
+++ b/res/layout/call_redirection_confirm_dialog.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 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
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:paddingTop="0dp"
+              android:paddingBottom="0dp"
+              android:background="@drawable/call_redirection_dialog_background"
+              android:orientation="vertical">
+
+    <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="center"
+            android:paddingTop="@dimen/call_redirection_dialog_image_upper_margin"
+            android:paddingBottom="@dimen/call_redirection_dialog_image_bottom_margin"
+            android:tint="@color/call_redirection_dialog_icon_tint_color"
+            android:src="@drawable/ic_phone"/>
+
+    <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:paddingBottom="@dimen/call_redirection_dialog_title_bottom_margin"
+            android:text="@string/alert_redirect_outgoing_call_or_not"
+            android:textColor="@color/call_redirection_dialog_text_color"
+            android:textSize="@dimen/call_redirection_dialog_title_font_size"
+            android:textStyle="bold"/>
+
+    <View
+            android:layout_width="fill_parent"
+            android:layout_height="1dp"
+            android:background="@color/call_redirection_dialog_view_divider_color"/>
+
+    <Button
+            android:id="@+id/buttonFirstLine"
+            android:text="@string/alert_place_unredirect_outgoing_call"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:gravity="left"
+            android:background="@drawable/call_redirection_button_ripple_effect"
+            android:paddingTop="@dimen/call_redirection_dialog_button_text_upper_bottom_margin"
+            android:paddingBottom="@dimen/call_redirection_dialog_button_text_upper_bottom_margin"
+            android:paddingLeft="@dimen/call_redirection_dialog_button_text_left_margin"
+            android:paddingRight="@dimen/call_redirection_dialog_button_text_left_margin"
+            android:textColor="@color/call_redirection_dialog_text_color"
+            android:textSize="@dimen/call_redirection_dialog_button_font_size"
+            android:textAllCaps="false"/>
+
+    <View
+            android:layout_width="fill_parent"
+            android:layout_height="1dp"
+            android:background="@color/call_redirection_dialog_view_divider_color"/>
+
+    <Button
+            android:id="@+id/buttonSecondLine"
+            android:text="@string/alert_place_outgoing_call_with_redirection"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:gravity="left"
+            android:background="@drawable/call_redirection_button_ripple_effect"
+            android:paddingTop="@dimen/call_redirection_dialog_button_text_upper_bottom_margin"
+            android:paddingBottom="@dimen/call_redirection_dialog_button_text_upper_bottom_margin"
+            android:paddingLeft="@dimen/call_redirection_dialog_button_text_left_margin"
+            android:textColor="@color/call_redirection_dialog_text_color"
+            android:textSize="@dimen/call_redirection_dialog_button_font_size"
+            android:textAllCaps="false"/>
+
+    <View
+            android:layout_width="fill_parent"
+            android:layout_height="1dp"
+            android:background="@color/call_redirection_dialog_view_divider_color"/>
+
+    <Button
+            android:id="@+id/buttonThirdLine"
+            android:text="@string/cancel"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:gravity="left"
+            android:background="@drawable/call_redirection_button_ripple_effect"
+            android:paddingTop="@dimen/call_redirection_dialog_button_text_upper_bottom_margin"
+            android:paddingBottom="@dimen/call_redirection_dialog_button_text_upper_bottom_margin"
+            android:paddingLeft="@dimen/call_redirection_dialog_button_text_left_margin"
+            android:paddingRight="@dimen/call_redirection_dialog_button_text_left_margin"
+            android:textColor="@color/call_redirection_dialog_text_color"
+            android:textSize="@dimen/call_redirection_dialog_button_font_size"
+            android:textAllCaps="false"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/telecom_developer_menu.xml b/res/layout/telecom_developer_menu.xml
new file mode 100644
index 0000000..0df0cdd
--- /dev/null
+++ b/res/layout/telecom_developer_menu.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="fill_parent"
+              android:layout_height="fill_parent">
+
+    <Switch
+        android:id="@+id/switchEnhancedCallBlocking"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/developer_enhanced_call_blocking"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/raw/endcall.ogg b/res/raw/endcall.ogg
new file mode 100644
index 0000000..1af440b
--- /dev/null
+++ b/res/raw/endcall.ogg
Binary files differ
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 8b488c2..ccc7e28 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Oproep kan nie gemaak word nie weens \'n oproep in \'n ander program."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Inkomende oproepe"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Gemiste oproepe"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Oproepblokkering"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"As jy hierdie oproep maak, sal dit jou <xliff:g id="OTHER_APP">%1$s</xliff:g>-oproep beëindig."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Oproepblokkering"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Nommers nie in Kontakte nie"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blokkeer nommers wat nie in jou Kontakte gelys is nie"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privaat"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Blokkeer bellers wat nie hulle nommer bekendmaak nie"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Telefoonhokkies"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Blokkeer oproepe vanaf telefoonhokkies"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Onbekend"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Blokkeer oproepe vanaf onbekende bellers"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Oproepblokkering"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Oproepblokkering is gedeaktiveer"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Noodoproep gemaak"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Oproepblokkering is gedeaktiveer sodat noodeenhede jou kan kontak."</string>
 </resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 6331a39..478fce5 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"በሌላ መተግበሪያ ውስጥ ባለ ጥሪ ምክንያት ጥሪ መደረግ አይችልም።"</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"ገቢ ጥሪዎች"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"ያመለጡ ጥሪዎች"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"ጥሪን ማገድ"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"ይህን ጥሪ ማድረግ የ<xliff:g id="OTHER_APP">%1$s</xliff:g> ጥሪዎን ያቋርጣል።"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"ጥሪን ማገድ"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"ቁጥሮች በእውቂያዎች ውስጥ የሉም"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"በእውቂያዎችዎ ውስጥ ያልተዘረዘሩ ቁጥሮችን አግድ"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"የግል"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"ቁጥራቸውን የማይገልጹ ደዋዮችን አግድ"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"የክፍያ ስልክ"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"የክፍያ ስልኮች የሚመጡ ጥሪዎችን አግድ"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"ያልታወቀ"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"ካልታወቁ ደዋዮች የሚመጡ ጥሪዎችን አግድ"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"ጥሪን ማገድ"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"ጥሪ ማገድ ተሰናክሏል"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"የአደጋ ጊዜ ጥሪ ተደርጓል"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"የአደጋ ጊዜ ምላሽ ሰጪዎች እርስዎን ለማግኘት እንዲችሉ ጥሪ ማገድ ተሰናክሏል።"</string>
 </resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 234c836..9684b94 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -27,11 +27,11 @@
     <string name="notification_missedCall_call_back" msgid="2684890353590890187">"معاودة الاتصال"</string>
     <string name="notification_missedCall_message" msgid="3049928912736917988">"رسالة"</string>
     <string name="accessibility_call_muted" msgid="2776111226185342220">"تم كتم صوت المكالمة."</string>
-    <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"تم تفعيل مكبر صوت الهاتف."</string>
-    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"لا يمكنني التحدث الآن. ما الأمر؟"</string>
+    <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"تم تمكين مكبر صوت الهاتف."</string>
+    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"لا يمكنني التحدث الآن. ماذا هناك؟"</string>
     <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"سأعاود الاتصال بك."</string>
     <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"سأتصل بك لاحقًا."</string>
-    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"لا يمكنني التحدث الآن. اتصل لاحقًا."</string>
+    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"لا يمكنني التحدث الآن. اتصل بي لاحقًا."</string>
     <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"الردود السريعة"</string>
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"تعديل الردود السريعة"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
@@ -45,10 +45,10 @@
     <string name="no_vm_number" msgid="4164780423805688336">"رقم البريد الصوتي مفقود"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"‏لم يتم تخزين رقم بريد صوتي على شريحة SIM."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"إضافة رقم"</string>
-    <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"هل تريد تعيين <xliff:g id="NEW_APP">%s</xliff:g> كتطبيق الهاتف التلقائي؟"</string>
-    <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"التحديد كتطبيق تلقائي"</string>
+    <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"هل تريد تعيين <xliff:g id="NEW_APP">%s</xliff:g> باعتباره تطبيق الهاتف الافتراضي؟"</string>
+    <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"تعيين كافتراضي"</string>
     <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"إلغاء"</string>
-    <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"سيتمكن <xliff:g id="NEW_APP">%s</xliff:g> من إجراء المكالمات والتحكم في كل جوانبها. يمكن فقط تعيين التطبيقات التي تثق بها كتطبيق الهاتف التلقائي."</string>
+    <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"سيتمكن <xliff:g id="NEW_APP">%s</xliff:g> من إجراء المكالمات والتحكم في كل جوانبها. يمكن فقط تعيين التطبيقات التي تثق بها باعتبارها تطبيق الهاتف الافتراضي."</string>
     <string name="blocked_numbers" msgid="2751843139572970579">"الأرقام المحظورة"</string>
     <string name="blocked_numbers_msg" msgid="1045015186124965643">"لن تتلقى أي مكالمات أو مراسلات نصية من الأرقام المحظورة."</string>
     <string name="block_number" msgid="1101252256321306179">"إضافة رقم"</string>
@@ -61,7 +61,7 @@
     <string name="delete_icon_description" msgid="8903995728252556724">"إلغاء الحظر"</string>
     <string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"تم إيقاف الحظر مؤقتًا"</string>
     <string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"بعد الاتصال الهاتفي أو إرسال رسالة نصية إلى رقم طوارئ، يتم إيقاف تشغيل الحظر لضمان تمكن خدمات الطوارئ من الاتصال بك."</string>
-    <string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"إعادة تفعيل الآن"</string>
+    <string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"إعادة تمكين الآن"</string>
     <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> محظور"</string>
     <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"تم إلغاء حظر <xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g>"</string>
     <string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"غير قادر على حظر رقم الطوارئ."</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"يتعذر إجراء المكالمة نتيجة لوجود مكالمة في تطبيق آخر."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"المكالمات الواردة"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"المكالمات الفائتة"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"حظر المكالمات"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"يؤدي إجراء هذه المكالمة إلى إنهاء مكالمة <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"حظر المكالمات"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"الأرقام غير المسردة في \"جهات الاتصال\""</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"حظر المكالمات عير المسردة في \"جهات الاتصال\""</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"خاص"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"حظر المتصلين الذين لا يكشفون رقمهم"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"هاتف مدفوع"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"حظر المكالمات من الهواتف المدفوعة"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"غير معروف"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"حظر المكالمات من المتصلين مجهولي الهوية"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"حظر المكالمات"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"تم إيقاف حظر المكالمات"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"تم إجراء مكالمة طوارئ"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"تم إيقاف حظر المكالمات للسماح لمسؤولي استجابة الطوارئ بالاتصال بك."</string>
 </resources>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
deleted file mode 100644
index a8a1b2e..0000000
--- a/res/values-as/strings.xml
+++ /dev/null
@@ -1,100 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2013 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.
- -->
-
-<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="382363169988504520">"কল পৰিচালনা"</string>
-    <string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"ফ’ন"</string>
-    <string name="unknown" msgid="6878797917991465859">"অজ্ঞাত"</string>
-    <string name="notification_missedCallTitle" msgid="7554385905572364535">"মিছ্ড কল"</string>
-    <string name="notification_missedWorkCallTitle" msgid="6242489980390803090">"মিছ কৰা কৰ্মস্থানৰ কল"</string>
-    <string name="notification_missedCallsTitle" msgid="1361677948941502522">"মিছ্ড কল"</string>
-    <string name="notification_missedCallsMsg" msgid="4575787816055205600">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g>টা মিছ্ড কল"</string>
-    <string name="notification_missedCallTicker" msgid="504686252427747209">"<xliff:g id="MISSED_CALL_FROM">%s</xliff:g>ৰ পৰা মিছ্ড কল"</string>
-    <string name="notification_missedCall_call_back" msgid="2684890353590890187">"কলবেক কৰক"</string>
-    <string name="notification_missedCall_message" msgid="3049928912736917988">"বাৰ্তা"</string>
-    <string name="accessibility_call_muted" msgid="2776111226185342220">"কল মিউট কৰা হৈছে।"</string>
-    <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"স্পীকাৰফ\'ন সক্ষম কৰা হৈছে।"</string>
-    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"এতিয়া কথা পাতিব নোৱাৰোঁ। কি খবৰ?"</string>
-    <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"মই আপোনাক লগে লগে কলবেক কৰি আছোঁ।"</string>
-    <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"মই আপোনাক পিছত কল কৰিম।"</string>
-    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"এতিয়া কথা পাতিব নোৱাৰোঁ। মোক পিছত কল কৰিবনে?"</string>
-    <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"ক্ষীপ্ৰ উত্তৰসমূহ"</string>
-    <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"ক্ষীপ্ৰ উত্তৰসমূহ সম্পাদনা কৰক"</string>
-    <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
-    <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"তাৎক্ষণিক উত্তৰ"</string>
-    <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g>লৈ বাৰ্তা পঠিওৱা হ’ল।"</string>
-    <string name="enable_account_preference_title" msgid="2021848090086481720">"কলিং একাউণ্ট"</string>
-    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"কেৱল জৰুৰীকালীন কল কৰাৰ হে অনুমতি আছে।"</string>
-    <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"ফ\'ন অনুমতিটোৰ অবিহনে এই এপ্লিকেশ্বনটোৱে কোনো বহিৰ্গামী কল কৰিব নোৱাৰে।"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"কল কৰিবৰ কাৰণে এটা মান্য নম্বৰ দিয়ক।"</string>
-    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"এই মুহূৰ্তত কল যোগ কৰিব নোৱাৰি।"</string>
-    <string name="no_vm_number" msgid="4164780423805688336">"ভইচমেইল নম্বৰ নাই"</string>
-    <string name="no_vm_number_msg" msgid="1300729501030053828">"ছিম কাৰ্ডত কোনো ভইচমেইল নম্বৰ সঞ্চিত কৰি থোৱা হোৱা নাই।"</string>
-    <string name="add_vm_number_str" msgid="4676479471644687453">"নম্বৰ যোগ কৰক"</string>
-    <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g>ক আপোনাৰ ডিফ\'ল্ট ফ\'ন এপ্ হিচাপে চিহ্নিত কৰেনে?"</string>
-    <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"ডিফ\'ল্ট ছেট কৰক"</string>
-    <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"বাতিল কৰক"</string>
-    <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g>এ কল কৰা লগতে কলৰ সকলো দিশ নিয়ন্ত্ৰণ কৰিবলৈ সক্ষম হ\'ব। কেৱল আপুনি সম্পূৰ্ণৰূপে বিশ্বাস কৰা এপক হে আপোনাৰ ডিফ\'ল্ট ফ\'ন এপ্ হিচাপে চিহ্নিত কৰা উচিত।"</string>
-    <string name="blocked_numbers" msgid="2751843139572970579">"অৱৰোধ কৰা নম্বৰসমূহ"</string>
-    <string name="blocked_numbers_msg" msgid="1045015186124965643">"আপুনি অৱৰোধ কৰা নম্বৰসমূহৰ পৰা আৰু কল বা বাৰ্তা লাভ নকৰে।"</string>
-    <string name="block_number" msgid="1101252256321306179">"নম্বৰ যোগ কৰক"</string>
-    <string name="unblock_dialog_body" msgid="1614238499771862793">"<xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>ক অৱৰোধৰ পৰা আঁতৰাইনে?"</string>
-    <string name="unblock_button" msgid="3078048901972674170">"অৱৰোধৰ পৰা আঁতৰাওক"</string>
-    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"এই নম্বৰৰ পৰা কল আৰু পাঠ বাৰ্তা অৱৰোধ কৰক"</string>
-    <string name="add_blocked_number_hint" msgid="6847675097085433553">"ফ\'ন নম্বৰ"</string>
-    <string name="block_button" msgid="8822290682524373357">"অৱৰোধ কৰক"</string>
-    <string name="non_primary_user" msgid="5180129233352533459">"কেৱল ডিভাইচটোৰ গৰাকীয়েহে অৱৰোধ কৰা নম্বৰসমূহ চাব আৰু পৰিচালনা কৰিব পাৰে।"</string>
-    <string name="delete_icon_description" msgid="8903995728252556724">"অৱৰোধৰ পৰা আঁতৰাওক"</string>
-    <string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"সাময়িকভাৱে অৱৰোধৰ সুবিধা বন্ধ কৰি থোৱা হৈছে"</string>
-    <string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"আপুনি জৰুৰীকালীন নম্বৰ এটা ডায়েল কৰাৰ পিছত বা সেই নম্বৰটোলৈ পাঠ বাৰ্তা পঠিওৱাৰ পিছত নম্বৰটো অৱৰোধৰ পৰা আঁতৰোৱা হয় যাতে জৰুৰীকালীন সেৱাসমূহে আপোনাৰ সৈতে যোগাযোগ কৰিব পাৰে।"</string>
-    <string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"এতিয়াই পুনঃসক্ষম কৰক"</string>
-    <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> অৱৰোধ কৰা হৈছে"</string>
-    <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> অৱৰোধৰ পৰা আঁতৰ কৰা হৈছে"</string>
-    <string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"জৰুৰীকালীন নম্বৰ অৱৰোধ কৰিব পৰা নাই।"</string>
-    <string name="blocked_numbers_number_already_blocked_message" msgid="4392247814500811798">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g>ক ইতিমধ্যে অৱৰোধ কৰা হৈছে।"</string>
-    <string name="toast_personal_call_msg" msgid="5115361633476779723">"কলটো কৰিবলৈ ব্যক্তিগত ডায়েলাৰৰ ব্যৱহাৰ কৰা হৈছে"</string>
-    <string name="notification_incoming_call" msgid="7713197997773986670">"<xliff:g id="CALL_VIA">%1$s</xliff:g> <xliff:g id="CALL_FROM">%2$s</xliff:g>ৰ পৰা অহা কল"</string>
-    <string name="notification_incoming_video_call" msgid="6638486071698373893">"<xliff:g id="CALL_VIA">%1$s</xliff:g> <xliff:g id="CALL_FROM">%2$s</xliff:g>ৰ পৰা অহা ভিডিঅ\' কল"</string>
-    <string name="answering_ends_other_call" msgid="8282145910153766401">"উত্তৰ দিলে <xliff:g id="CALL_VIA">%1$s</xliff:g> কলটোৰ অন্ত পৰিব"</string>
-    <string name="answering_ends_other_calls" msgid="1198589551399049197">"উত্তৰ দিলে <xliff:g id="CALL_VIA">%1$s</xliff:g> কলকেইটাৰ অন্ত পৰিব"</string>
-    <string name="answering_ends_other_video_call" msgid="8510410917384186360">"উত্তৰ দিলে আপোনাৰ বৰ্তমান চলি থকা <xliff:g id="CALL_VIA">%1$s</xliff:g> ভিডিঅ\' কলটোৰ অন্ত পৰিব"</string>
-    <string name="answering_ends_other_managed_call" msgid="5186137550267947785">"উত্তৰ দিলে আপোনাৰ বৰ্তমান চলি থকা কলটোৰ অন্ত পৰিব"</string>
-    <string name="answering_ends_other_managed_calls" msgid="6429838309560397988">"উত্তৰ দিলে আপোনাৰ বৰ্তমান চলি থকা কলসমূহৰ অন্ত পৰিব"</string>
-    <string name="answering_ends_other_managed_video_call" msgid="1585423762458248435">"উত্তৰ দিলে আপোনাৰ বৰ্তমান চলি থকা ভিডিঅ\' কলটোৰ অন্ত পৰিব"</string>
-    <string name="answer_incoming_call" msgid="4140530013111794587">"উত্তৰ"</string>
-    <string name="decline_incoming_call" msgid="806026168661598368">"প্ৰত্যাখ্যান কৰক"</string>
-    <string name="cant_call_due_to_ongoing_call" msgid="4952615196237854748">"আপোনাৰ <xliff:g id="OTHER_CALL">%1$s</xliff:g> কল চলি থকাৰ কাৰণে বেলেগ কল কৰিব নোৱাৰি।"</string>
-    <string name="cant_call_due_to_ongoing_calls" msgid="1380804892363503856">"আপোনাৰ <xliff:g id="OTHER_CALL">%1$s</xliff:g> কলকেইটা চলি থকাৰ কাৰণে বেলেগ কল কৰিব নোৱাৰি।"</string>
-    <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"অইন এটা এপত কল চলি থকাৰ কাৰণে বেলেগ কল কৰিব নোৱাৰি।"</string>
-    <string name="notification_channel_incoming_call" msgid="3513761697082968084">"অন্তৰ্গামী কল"</string>
-    <string name="notification_channel_missed_call" msgid="8727062678632713146">"মিছ্ড কল"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"কল অৱৰোধ"</string>
-    <string name="alert_outgoing_call" msgid="982908156825958001">"এই কলটো কৰিলে আপোনাৰ <xliff:g id="OTHER_APP">%1$s</xliff:g> কলটোৰ অন্ত পৰিব।"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"কল অৱৰোধ"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"আপোনাৰ সর্ম্পকসূচীত নথকা"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"আপোনাৰ সর্ম্পকসূচীত নথকা নম্বৰ অৱৰোধ কৰক"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"ব্য়ক্তিগত"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"যিসকল কল কৰোঁতাই তেওঁলোকৰ নম্বৰ প্ৰকাশ নকৰে তেওঁলোকক অৱৰোধ কৰক"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"পে\'ফ\'ন"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"পে\'ফ\'নৰ পৰা অহা কল অৱৰোধ কৰক"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"অজ্ঞাত"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"অচিনাক্ত কল কৰোঁতাৰ পৰা অহা কল অৱৰোধ কৰক"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"কল অৱৰোধ"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"কল অৱৰোধ সুবিধাটো অক্ষম কৰি থোৱা আছে"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"জৰুৰীকালীন কল ম\'ড"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"আপোনাক যাতে জৰুৰীকালীন সেৱা প্ৰদানকাৰীসকলে যোগাযোগ কৰিব পাৰে তাৰ বাবে কল অৱৰোধ সুবিধাটো অক্ষম কৰি থোৱা হৈছে।"</string>
-</resources>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index fd42626..ac3bf76 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -31,9 +31,9 @@
     <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"İndi danışmaq olmur. Nə olub?"</string>
     <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"Özüm zəng edəcəm."</string>
     <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"Özüm sonra zəng edəcəm."</string>
-    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"Danışa bilmirəm. Sonra zəngləşərik."</string>
+    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"İndi danışa bilmirəm. Sonra zəng edin."</string>
     <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"Tez cavablar"</string>
-    <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Hazır cavablara düzəliş edin"</string>
+    <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Tez cavablara düzəliş edin"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Tez cavab"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mesaj <xliff:g id="PHONE_NUMBER">%s</xliff:g> nömrəsinə göndərildi."</string>
@@ -54,7 +54,7 @@
     <string name="block_number" msgid="1101252256321306179">"Nömrə əlavə edin"</string>
     <string name="unblock_dialog_body" msgid="1614238499771862793">"<xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g> nömrəsi blokdan çıxarılsın?"</string>
     <string name="unblock_button" msgid="3078048901972674170">"Blokdan çıxar"</string>
-    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"Bu nömrədən olan zəngləri və mətnləri bloklayın"</string>
+    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"Zəngləri və mətnləri buradan blok edin"</string>
     <string name="add_blocked_number_hint" msgid="6847675097085433553">"Telefon nömrəsi"</string>
     <string name="block_button" msgid="8822290682524373357">"Blok edin"</string>
     <string name="non_primary_user" msgid="5180129233352533459">"Yalnız cihaz sahibi blok edilmiş nömrələrə baxa və idarə edə bilər."</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Başqa bir tətbiqdəki zəng səbəbilə çağrı edilə bilməz."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Gələn zənglər"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Buraxılmış zənglər"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Zəngi Bloklama"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Bu zəngin yerləşdirilməsi <xliff:g id="OTHER_APP">%1$s</xliff:g> zəngini sonlandıracaq."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Zəngi Bloklama"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Kontaktda olmayan nömrələr"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Kontaktda göstərilməyən nömrələri blok edin"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Şəxsi"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Nömrələrini bildirməyən şəxslərin zənglərini blok edin"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Telefon ödənişi"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Ödənişli telefon zənglərini blok edin"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Naməlum"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"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="628536625775266096">"Zəngi Bloklama"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Zəngi Bloklama deaktivdir"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Təcili zəng edildi"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Təcili zənglərə cavab verənlərin Sizinlə əlaqə saxlamalarına icazə vermək üçün Zəngi Bloklama deaktiv edilib."</string>
 </resources>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index b74041b..ef4025b 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Ne možete da uputite poziv zbog poziva u drugoj aplikaciji."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Dolazni pozivi"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Propušteni pozivi"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Blokiranje poziva"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Ako uputite ovaj poziv, završićete <xliff:g id="OTHER_APP">%1$s</xliff:g> poziv."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Blokiranje poziva"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Brojevi koji nisu u kontaktima"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blokirajte brojeve koji vam nisu u kontaktima"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Skriveni brojevi"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Blokirajte pozivaoce koji skrivaju broj"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Telefonska govornica"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Blokirajte pozive sa telefonskih govornica"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Nepoznati brojevi"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Blokirajte pozive neidentifikovanih pozivalaca"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Blokiranje poziva"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Blokiranje poziva je onemogućeno"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Upućen je hitni poziv"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Blokiranje poziva je onemogućeno da bi hitne službe mogle da vas kontaktiraju."</string>
 </resources>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 0cfa989..9950e14 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Выклік немагчыма выканаць, бо ідзе выклік у іншай праграме."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Уваходныя выклікі"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Прапушчаныя выклікі"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Блакіраванне выклікаў"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Калі зрабіць гэты выклік, ваш выклік праз праграму <xliff:g id="OTHER_APP">%1$s</xliff:g> скончыцца."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Блакіраванне выклікаў"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Нумары не ў спісе кантактаў"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Блакіраваць нумары, якіх няма ў спісе вашых кантактаў"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Схаваныя нумары"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Блакіраваць абанентаў, якія не раскрываюць свой нумар"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Таксафон"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Блакіраваць выклікі з таксафонаў"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Невядомыя нумары"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Блакіраваць выклікі ад неапазнаных абанентаў"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Блакіраванне выклікаў"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Блакіраванне выклікаў адключана"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Зроблены экстранны выклік"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Блакіраванне выклікаў было адключана, каб дазволіць аварыйнай брыгадзе звязацца з вамі."</string>
 </resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 102fb6f..babb59c 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Не можете да се обадите заради обаждане в друго приложение."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Входящи обаждания"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Пропуснати обаждания"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Блокиране на обажданията"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Ако извършите това обаждане, обаждането ви през <xliff:g id="OTHER_APP">%1$s</xliff:g> ще прекъсне."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Блокиране на обажданията"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Номера, които не са в контактите"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Блокиране на номерата, които не са в контактите ви"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Скрити"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Блокиране на обаждащите се, които крият номера си"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Импулсни телефони"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Блокиране на обаждания от импулсни телефони"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Неизвестни"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Блокиране на обажданията от неидентифицирани обаждащи се"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Блокиране на обажданията"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Блокирането на обажданията е деактивирано"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Извършено бе спешно обаждане"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Блокирането на обажданията е деактивирано, за да могат службите за спешни случаи да се свържат с вас."</string>
 </resources>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 8b1e5f9..00c5312 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -25,8 +25,8 @@
     <string name="notification_missedCallsMsg" msgid="4575787816055205600">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g>টি মিসড কল"</string>
     <string name="notification_missedCallTicker" msgid="504686252427747209">"<xliff:g id="MISSED_CALL_FROM">%s</xliff:g> এর থেকে মিসড কল"</string>
     <string name="notification_missedCall_call_back" msgid="2684890353590890187">"কল ব্যাক করুন"</string>
-    <string name="notification_missedCall_message" msgid="3049928912736917988">"মেসেজ"</string>
-    <string name="accessibility_call_muted" msgid="2776111226185342220">"কল মিউট করা আছে৷"</string>
+    <string name="notification_missedCall_message" msgid="3049928912736917988">"বার্তা"</string>
+    <string name="accessibility_call_muted" msgid="2776111226185342220">"কল নিঃশব্দ করা আছে৷"</string>
     <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"স্পীকারফোন সক্ষম করা আছে৷"</string>
     <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"এখন কথা বলতে পারছি না৷ কি খবর?"</string>
     <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"আমি আপনাকে কিছুক্ষণ পরেই কল করছি৷"</string>
@@ -49,12 +49,12 @@
     <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"ডিফল্ট হিসাবে সেট করুন"</string>
     <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"বাতিল করুন"</string>
     <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> কল করতে এবং কলের সমগ্র বৈশিষ্ট্য নিয়ন্ত্রণ করতে সক্ষম হবে৷ শুধুমাত্র আপনি যে অ্যাপ্সকে বিশ্বাস করেন সেগুলিকেই ডিফল্ট ফোন অ্যাপ হিসাবে সেট করা উচিৎ৷"</string>
-    <string name="blocked_numbers" msgid="2751843139572970579">"ব্লক করা নম্বরগুলি"</string>
-    <string name="blocked_numbers_msg" msgid="1045015186124965643">"ব্লক করা নম্বরগুলি থেকে আপনি কল বা এসএমএস পাবেন না।"</string>
+    <string name="blocked_numbers" msgid="2751843139572970579">"অবরুদ্ধ নম্বরগুলি"</string>
+    <string name="blocked_numbers_msg" msgid="1045015186124965643">"অবরুদ্ধ নম্বরগুলি থেকে আপনি কল বা এসএমএস পাবেন না।"</string>
     <string name="block_number" msgid="1101252256321306179">"একটি নম্বর যোগ করুন"</string>
     <string name="unblock_dialog_body" msgid="1614238499771862793">"<xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g> অবরোধ মুক্ত করবেন?"</string>
     <string name="unblock_button" msgid="3078048901972674170">"অবরোধ মুক্ত করুন"</string>
-    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"এর থেকে কল এবং এসএমএস ব্লক করুন"</string>
+    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"এর থেকে কল এবং এসএমএস অবরোধ করুন"</string>
     <string name="add_blocked_number_hint" msgid="6847675097085433553">"ফোন নম্বর"</string>
     <string name="block_button" msgid="8822290682524373357">"অবরোধ করুন"</string>
     <string name="non_primary_user" msgid="5180129233352533459">"শুধুমাত্র ডিভাইসের মালিক এই অবরুদ্ধ নম্বরগুলিকে দেখতে এবং পরিচালনা করতে পারেন৷"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"অন্য একটি অ্যাপের কলের কারণে কলটি করা যাবে না।"</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"ইনকামিং কল"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"মিস করা কল"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"কল ব্লক করা"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"এই কলটির উত্তর দেওয়া হলে তা আপনার <xliff:g id="OTHER_APP">%1$s</xliff:g> কলটি কেটে যাবে৷"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"কল ব্লক করা"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"পরিচিতিতে নেই এমন নম্বর"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"আপনার পরিচিতিতে নেই এমন নম্বর ব্লক করুন"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"ব্যক্তিগত"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"কলার আইডিতে নম্বর দেখা যায়না এমন কল ব্লক করুন"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"পাবলিক ফোন"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"পাবলিক ফোন থেকে করা কল ব্লক করুন"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"অজানা"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"অচেনা নম্বর থেকে করা কল ব্লক করুন"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"কল ব্লক করা"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"কল ব্লক করার বৈশিষ্ট্য বন্ধ করা হয়েছে"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"জরুরি অবস্থার কল করা হয়েছে"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"কল ব্লক করার বৈশিষ্ট্য বন্ধ করা হয়েছে যাতে জরুরি অবস্থার সাহায্যকারী ব্যক্তি আপনার সাথে যোগাযোগ করতে পারেন।"</string>
 </resources>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index f8ad518..569e738 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -31,7 +31,7 @@
     <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"Ne mogu sada pričati. O čemu se radi?"</string>
     <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"Nazvat ću te uskoro."</string>
     <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"Nazvat ću te kasnije."</string>
-    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"Ne mogu sada pričati. Nazovi me kasnije."</string>
+    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"Ne mogu pričati. Nazovi me kasnije."</string>
     <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"Brzi odgovori"</string>
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Uredi brze odgovore"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
@@ -60,7 +60,7 @@
     <string name="non_primary_user" msgid="5180129233352533459">"Samo vlasnik uređaja može pregledati i upravljati blokiranim brojevima."</string>
     <string name="delete_icon_description" msgid="8903995728252556724">"Deblokiraj"</string>
     <string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"Blokiranje je privremeno isključeno"</string>
-    <string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"Nakon što pozovete ili pošaljete poruku na broj za hitne slučajeve, blokiranje se isključuje da bi vas hitne službe mogle kontaktirati."</string>
+    <string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"Nakon što pozovete ili pošaljete poruku na broj za hitne slučajeve, blokiranje se isključuje da bi vas hitna služba mogla kontaktirati."</string>
     <string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"Ponovo omogući sada"</string>
     <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> je blokiran"</string>
     <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> je deblokiran"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Pozivanje nije moguće zbog poziva u drugoj aplikaciji."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Dolazni pozivi"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Propušteni pozivi"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Blokiranje poziva"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Upućivanje ovog poziva će prekinuti poziv: <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Blokiranje poziva"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Brojevi koji nisu u Kontaktima"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blokirajte brojeve koji se ne nalaze u vašim Kontaktima"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privatan"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Blokirajte pozivaoce koji ne otkrivaju svoj broj"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Telefonska govornica"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Blokirajte pozive s telefonskih govornica"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Nepoznat"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Blokirajte pozive neidentificiranih pozivalaca"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Blokiranje poziva"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Blokiranje poziva je onemogućeno"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Upućen je hitni poziv"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Blokiranje poziva je onemogućeno kako bi se omogućilo osobama koje reagiraju u hitnim slučajevima da vas kontaktiraju."</string>
 </resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 9d6adce..3776db9 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -31,7 +31,7 @@
     <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"Ara no puc parlar. Què passa?"</string>
     <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"Et truco de seguida."</string>
     <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"Et truco més tard."</string>
-    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"No puc parlar. Em truques després?"</string>
+    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"Ara no puc parlar. Truques després?"</string>
     <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"Respostes ràpides"</string>
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Edita les respostes ràpides"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"No es pot trucar perquè ja hi ha una trucada en curs en una altra aplicació."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Trucades entrants"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Trucades perdudes"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Bloqueig de trucades"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"En fer aquesta trucada, finalitzarà la de l\'aplicació <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Bloqueig de trucades"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Números que no surten a Contactes"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Bloqueja els números que no surten a Contactes"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privades"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Bloqueja les trucades que tinguin el número ocult"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Telèfons públics"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Bloqueja les trucades de telèfons públics"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Desconegudes"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Bloqueja les trucades de números desconeguts"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Bloqueig de trucades"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"El bloqueig de trucades s\'ha desactivat"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"S\'ha fet una trucada d\'emergència"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"El bloqueig de trucades s\'ha desactivat perquè els serveis d\'emergència puguin contactar amb tu."</string>
 </resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 76c40e6..2a9ac60 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Hovor není možné provést kvůli hovoru v jiné aplikaci."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Příchozí hovory"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Zmeškané hovory"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Blokování hovorů"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Uskutečněním tohoto hovoru ukončíte hovor <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Blokování hovorů"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Čísla, která nejsou v kontaktech"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blokovat čísla, která nemáte v kontaktech"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Ze skrytých čísel"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Blokovat volající, kteří skrývají své číslo"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Z veřejných telefonů"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Blokovat hovory z veřejných telefonů"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Z nerozpoznaných čísel"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Blokovat hovory od nerozpoznaných volajících"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Blokování hovorů"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Blokování hovorů bylo vypnuto"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Uskutečněno tísňové volání"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Blokování hovorů bylo vypnuto, aby vás mohli kontaktovat pracovníci tísňových služeb."</string>
 </resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 1ba9a08..2e0ed39 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -36,11 +36,11 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Rediger hurtige svar"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Hurtigt svar"</string>
-    <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Beskeden er sendt til <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
+    <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Meddelelsen er sendt til <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Opkaldskonti"</string>
     <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Kun nødopkald er tilladt."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Denne app kan ikke foretage udgående opkald uden opkaldstilladelse."</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Angiv et gyldigt nummer for at foretage et opkald."</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Indtast et gyldigt nummer for at foretage et opkald."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Opkaldet kan ikke tilføjes på nuværende tidspunkt."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Telefonsvarernummer mangler"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Der er ikke gemt noget telefonsvarernummer på SIM-kortet."</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Opkaldet kan ikke foretages på grund et opkald i en anden app."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Indgående opkald"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Ubesvarede opkald"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Opkaldsblokering"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Hvis du foretager dette opkald, afsluttes dit opkald i <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Opkaldsblokering"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Numre er ikke i Kontakter"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Bloker numre, som ikke er i dine kontakter"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privat"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Bloker opkald fra personer, der ringer fra hemmeligt nummer"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Mønttelefon"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Bloker opkald fra mønttelefoner"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Ukendt"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Bloker opkald fra numre uden opkalds-id"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Opkaldsblokering"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Opkaldsblokering er deaktiveret"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Foretagne nødopkald"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Opkaldsblokering er blevet deaktiveret for at give nødnumre mulighed for at kontakte dig."</string>
 </resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 13f7e04..f0a4b75 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Dieser Anruf kann aufgrund eines Anrufs in einer anderen App nicht getätigt werden."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Eingehende Anrufe"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Entgangene Anrufe"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Anrufblockierung"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Durch diesen Anruf wird der Anruf in <xliff:g id="OTHER_APP">%1$s</xliff:g> beendet."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Anrufblockierung"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Nicht in den Kontakten gespeicherte Telefonnummern"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Telefonnummern, die nicht in den Kontakten gespeichert sind, werden blockiert"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privat"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Anrufer mit unterdrückter Nummer werden blockiert"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Öffentliche Telefone"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Anrufe von öffentlichen Telefonen werden blockiert"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Unbekannt"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Anrufe von nicht identifizierten Anrufern werden blockiert"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Anrufblockierung"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Anrufblockierung deaktiviert"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Notruf abgesetzt"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Die Anrufblockierung wurde deaktiviert, damit Ersthelfer und Rettungskräfte dich kontaktieren können."</string>
 </resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index cb21b12..5dd11d5 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Δεν είναι δυνατή η πραγματοποίηση της κλήσης, λόγω κάποιας κλήσης μέσω άλλης εφαρμογής."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Εισερχόμενες κλήσεις"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Αναπάντητες κλήσεις"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Φραγή κλήσεων"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Εάν πραγματοποιήσετε αυτήν την κλήση, η κλήση σας μέσω <xliff:g id="OTHER_APP">%1$s</xliff:g> θα τερματιστεί."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Φραγή κλήσεων"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Αριθμοί που δεν βρίσκονται στις Επαφές"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Αποκλεισμός αριθμών που δεν περιλαμβάνονται στις επαφές σας"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Με απόκρυψη"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Αποκλεισμός καλούντων που δεν αποκαλύπτουν τον αριθμό τους"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Καρτοτηλέφωνο"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Αποκλεισμός κλήσεων από καρτοτηλέφωνα"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Άγνωστος"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Αποκλεισμός κλήσεων από αγνώστους"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Φραγή κλήσεων"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Φραγή κλήσεων απενεργοποιημένη"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Πραγματοποιήθηκε κλήση έκτακτης ανάγκης"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Η φραγή κλήσεων έχει απενεργοποιηθεί, ώστε να επιτρέπεται σε άτομα που ανταποκρίνονται σε έκτακτες ανάγκες να επικοινωνούν μαζί σας."</string>
 </resources>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index d62ac55..7d344f1 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Call cannot be placed due to a call in another app."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Incoming calls"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Missed calls"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Call Blocking"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Placing this call will end your <xliff:g id="OTHER_APP">%1$s</xliff:g> call."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Call Blocking"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Numbers not in Contacts"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Block numbers that are not listed in your Contacts"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Private"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Block callers who do not disclose their number"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Phonebox"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Block calls from pay phones"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Unknown"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Block calls from unidentified callers"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Call Blocking"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Call Blocking disabled"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Emergency call made"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Call Blocking has been disabled to allow emergency responders to contact you."</string>
 </resources>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index d62ac55..7d344f1 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Call cannot be placed due to a call in another app."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Incoming calls"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Missed calls"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Call Blocking"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Placing this call will end your <xliff:g id="OTHER_APP">%1$s</xliff:g> call."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Call Blocking"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Numbers not in Contacts"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Block numbers that are not listed in your Contacts"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Private"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Block callers who do not disclose their number"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Phonebox"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Block calls from pay phones"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Unknown"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Block calls from unidentified callers"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Call Blocking"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Call Blocking disabled"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Emergency call made"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Call Blocking has been disabled to allow emergency responders to contact you."</string>
 </resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index d62ac55..7d344f1 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Call cannot be placed due to a call in another app."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Incoming calls"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Missed calls"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Call Blocking"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Placing this call will end your <xliff:g id="OTHER_APP">%1$s</xliff:g> call."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Call Blocking"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Numbers not in Contacts"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Block numbers that are not listed in your Contacts"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Private"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Block callers who do not disclose their number"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Phonebox"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Block calls from pay phones"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Unknown"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Block calls from unidentified callers"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Call Blocking"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Call Blocking disabled"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Emergency call made"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Call Blocking has been disabled to allow emergency responders to contact you."</string>
 </resources>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index d62ac55..7d344f1 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Call cannot be placed due to a call in another app."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Incoming calls"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Missed calls"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Call Blocking"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Placing this call will end your <xliff:g id="OTHER_APP">%1$s</xliff:g> call."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Call Blocking"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Numbers not in Contacts"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Block numbers that are not listed in your Contacts"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Private"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Block callers who do not disclose their number"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Phonebox"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Block calls from pay phones"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Unknown"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Block calls from unidentified callers"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Call Blocking"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Call Blocking disabled"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Emergency call made"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Call Blocking has been disabled to allow emergency responders to contact you."</string>
 </resources>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index 7a44902..26daa02 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -16,85 +16,71 @@
 
 <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="382363169988504520">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‎‎‎‏‏‎‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‎‏‎‎‎‎Call Management‎‏‎‎‏‎"</string>
-    <string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‎Phone‎‏‎‎‏‎"</string>
-    <string name="unknown" msgid="6878797917991465859">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‎‎‎‏‎‏‏‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‎Unknown‎‏‎‎‏‎"</string>
-    <string name="notification_missedCallTitle" msgid="7554385905572364535">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‎‏‏‎‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‏‏‏‎Missed call‎‏‎‎‏‎"</string>
-    <string name="notification_missedWorkCallTitle" msgid="6242489980390803090">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‎‎‏‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‎‎‎‏‎‎‎‏‏‎‎‏‎‎‎‎‏‎‎‎‎‎‏‏‎‏‎‎‏‎‎‏‎‎Missed work call‎‏‎‎‏‎"</string>
-    <string name="notification_missedCallsTitle" msgid="1361677948941502522">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‏‎‏‏‏‎‎‏‎‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‎‏‎‏‎‎‏‏‎‏‎‎‏‎‎‏‎‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎Missed calls‎‏‎‎‏‎"</string>
-    <string name="notification_missedCallsMsg" msgid="4575787816055205600">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‏‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g>‎‏‎‎‏‏‏‎ missed calls‎‏‎‎‏‎"</string>
-    <string name="notification_missedCallTicker" msgid="504686252427747209">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‎‎‎‎‎‏‎‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‎‎‏‎Missed call from ‎‏‎‎‏‏‎<xliff:g id="MISSED_CALL_FROM">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="notification_missedCall_call_back" msgid="2684890353590890187">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‎‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‎‏‏‏‎‏‏‎‎‏‎‏‏‎Call back‎‏‎‎‏‎"</string>
-    <string name="notification_missedCall_message" msgid="3049928912736917988">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‏‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎Message‎‏‎‎‏‎"</string>
-    <string name="accessibility_call_muted" msgid="2776111226185342220">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‏‏‎‏‎‎‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‎‏‏‎‎‎Call muted.‎‏‎‎‏‎"</string>
-    <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‏‎‏‎‎‏‎‏‎‏‎‎‏‎‎‏‎‎‎‏‏‏‎‎‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎‏‏‏‎Speakerphone enabled.‎‏‎‎‏‎"</string>
-    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‎‏‎‎‏‎‏‏‎‎‎‏‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‏‏‎‎‎‏‏‎‏‏‏‎Can\'t talk now. What\'s up?‎‏‎‎‏‎"</string>
-    <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‏‎‏‏‎‏‎‏‏‎‏‏‎‎‎‏‎‏‎‎‏‎‎‎‎‎‏‎‎‏‏‏‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎I\'ll call you right back.‎‏‎‎‏‎"</string>
-    <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‎‏‎‎‏‎‎‏‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎I\'ll call you later.‎‏‎‎‏‎"</string>
-    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‏‏‏‎‎‏‎‏‎‎‎‎‎‎‎‏‎‏‏‎‏‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‏‏‎‏‏‏‎‎Can\'t talk now. Call me later?‎‏‎‎‏‎"</string>
-    <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‏‎‎‎‏‏‏‎‎‎‏‏‎‏‏‏‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‏‏‎Quick responses‎‏‎‎‏‎"</string>
-    <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‎‎‎‎‎‏‎‎‏‎‎Edit quick responses‎‏‎‎‏‎"</string>
+    <string name="telecommAppLabel" product="default" msgid="382363169988504520">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‎‎‎‏‏‎‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‎‏‎‎‎‎Call Management‎‏‎‎‏‎"</string>
+    <string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‎Phone‎‏‎‎‏‎"</string>
+    <string name="unknown" msgid="6878797917991465859">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‎‎‎‏‎‏‏‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‎Unknown‎‏‎‎‏‎"</string>
+    <string name="notification_missedCallTitle" msgid="7554385905572364535">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‎‏‏‎‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‏‏‏‎Missed call‎‏‎‎‏‎"</string>
+    <string name="notification_missedWorkCallTitle" msgid="6242489980390803090">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‎‎‏‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‎‎‎‏‎‎‎‏‏‎‎‏‎‎‎‎‏‎‎‎‎‎‏‏‎‏‎‎‏‎‎‏‎‎Missed work call‎‏‎‎‏‎"</string>
+    <string name="notification_missedCallsTitle" msgid="1361677948941502522">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‏‎‏‏‏‎‎‏‎‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‎‏‎‏‎‎‏‏‎‏‎‎‏‎‎‏‎‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎Missed calls‎‏‎‎‏‎"</string>
+    <string name="notification_missedCallsMsg" msgid="4575787816055205600">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‏‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g>‎‏‎‎‏‏‏‎ missed calls‎‏‎‎‏‎"</string>
+    <string name="notification_missedCallTicker" msgid="504686252427747209">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‎‎‎‎‎‏‎‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‎‎‏‎Missed call from ‎‏‎‎‏‏‎<xliff:g id="MISSED_CALL_FROM">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="notification_missedCall_call_back" msgid="2684890353590890187">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‎‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‎‏‏‏‎‏‏‎‎‏‎‏‏‎Call back‎‏‎‎‏‎"</string>
+    <string name="notification_missedCall_message" msgid="3049928912736917988">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‏‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎Message‎‏‎‎‏‎"</string>
+    <string name="accessibility_call_muted" msgid="2776111226185342220">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‏‏‎‏‎‎‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‎‏‏‎‎‎Call muted.‎‏‎‎‏‎"</string>
+    <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‏‎‏‎‎‏‎‏‎‏‎‎‏‎‎‏‎‎‎‏‏‏‎‎‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎‏‏‏‎Speakerphone enabled.‎‏‎‎‏‎"</string>
+    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‎‏‎‎‏‎‏‏‎‎‎‏‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‏‏‎‎‎‏‏‎‏‏‏‎Can\'t talk now. What\'s up?‎‏‎‎‏‎"</string>
+    <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‏‎‏‏‎‏‎‏‏‎‏‏‎‎‎‏‎‏‎‎‏‎‎‎‎‎‏‎‎‏‏‏‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎I\'ll call you right back.‎‏‎‎‏‎"</string>
+    <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‎‏‎‎‏‎‎‏‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎I\'ll call you later.‎‏‎‎‏‎"</string>
+    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‏‏‏‎‎‏‎‏‎‎‎‎‎‎‎‏‎‏‏‎‏‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‏‏‎‏‏‏‎‎Can\'t talk now. Call me later?‎‏‎‎‏‎"</string>
+    <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‏‎‎‎‏‏‏‎‎‎‏‏‎‏‏‏‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‏‏‎Quick responses‎‏‎‎‏‎"</string>
+    <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‎‎‎‎‎‏‎‎‏‎‎Edit quick responses‎‏‎‎‏‎"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
-    <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‎‎‎‎‏‏‏‏‎‎‎‏‏‎‎‎‏‏‎‎‎‏‏‏‎‎‏‎‎Quick response‎‏‎‎‏‎"</string>
-    <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‎‏‏‏‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‎‏‎Message sent to ‎‏‎‎‏‏‎<xliff:g id="PHONE_NUMBER">%s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
-    <string name="enable_account_preference_title" msgid="2021848090086481720">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‏‏‎‎‎‎‏‎‎‎‎‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎Calling accounts‎‏‎‎‏‎"</string>
-    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‏‎‏‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‎Only emergency calls are allowed.‎‏‎‎‏‎"</string>
-    <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‏‎‏‏‎‏‎‏‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‏‏‏‎‏‏‏‏‏‎‎‎This application cannot make outgoing calls without the Phone permission.‎‏‎‎‏‎"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‏‏‎‎‏‎‏‏‎‏‎‏‏‎‎‏‎‏‏‏‎‎‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎To place a call, enter a valid number.‎‏‎‎‏‎"</string>
-    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‎‏‎‏‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‎‏‎‎Call cannot be added at this time.‎‏‎‎‏‎"</string>
-    <string name="no_vm_number" msgid="4164780423805688336">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‏‏‎‎‎‏‎‎‎‏‎‏‏‎‏‏‏‎‏‎‏‏‎‎‎‎‎‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‏‎‎‎‎‏‎‎‎‎‎Missing voicemail number‎‏‎‎‏‎"</string>
-    <string name="no_vm_number_msg" msgid="1300729501030053828">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‎‎‎‏‏‏‏‎‏‎‎‏‎‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‎‏‎‎‎‏‏‏‎‏‏‏‏‏‎‎‎‏‎‎‎No voicemail number is stored on the SIM card.‎‏‎‎‏‎"</string>
-    <string name="add_vm_number_str" msgid="4676479471644687453">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‎‏‏‎‎‎‏‏‎‎‎‏‎‏‎‎‏‏‎‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‎‎‏‎‏‏‏‎‏‎Add number‎‏‎‎‏‎"</string>
-    <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‎‏‎‏‏‏‎‏‏‎‏‏‎Make ‎‏‎‎‏‏‎<xliff:g id="NEW_APP">%s</xliff:g>‎‏‎‎‏‏‏‎ your default Phone app?‎‏‎‎‏‎"</string>
-    <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‏‎‎‏‏‎‎‎‏‎‎‏‎‏‏‏‎‏‎‎‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎‏‎‎‎‏‏‎‎‎‏‎‎‎Set Default‎‏‎‎‏‎"</string>
-    <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‎‎‎‏‏‎‏‏‏‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‎‎‏‎‏‎‏‎Cancel‎‏‎‎‏‎"</string>
-    <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‏‎‎‏‎‏‎‎‏‎‏‎‏‏‏‎‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎‎‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="NEW_APP">%s</xliff:g>‎‏‎‎‏‏‏‎ will be able to place and control all aspects of calls. Only apps you trust should be set as the default Phone app.‎‏‎‎‏‎"</string>
-    <string name="blocked_numbers" msgid="2751843139572970579">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‏‎‎‎‎‏‎‎‎‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‎‎‏‏‎Blocked numbers‎‏‎‎‏‎"</string>
-    <string name="blocked_numbers_msg" msgid="1045015186124965643">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‎‎‎‏‏‏‏‎‎‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‏‏‏‏‎‎‎‎‎‎‏‏‏‎‎‎‎‏‎‏‏‎You won\'t receive calls or texts from blocked numbers.‎‏‎‎‏‎"</string>
-    <string name="block_number" msgid="1101252256321306179">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‎‎‎‏‏‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‏‎‏‎‏‎‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‎Add a number‎‏‎‎‏‎"</string>
-    <string name="unblock_dialog_body" msgid="1614238499771862793">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‏‎‎‏‏‎‎‏‏‎‏‏‏‎‏‏‎‏‎‏‎‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‏‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‎‎‏‎‎‏‎Unblock ‎‏‎‎‏‏‎<xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
-    <string name="unblock_button" msgid="3078048901972674170">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‎‏‏‏‎‏‏‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‏‏‎‏‎‎Unblock‎‏‎‎‏‎"</string>
-    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‏‏‎‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‎Block calls and texts from‎‏‎‎‏‎"</string>
-    <string name="add_blocked_number_hint" msgid="6847675097085433553">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‎‎‏‎‎‎‎‏‏‎‏‎‏‏‎‏‏‎‏‎‎‎‏‎Phone number‎‏‎‎‏‎"</string>
-    <string name="block_button" msgid="8822290682524373357">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‏‎‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‎‎‎‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎‏‎Block‎‏‎‎‏‎"</string>
-    <string name="non_primary_user" msgid="5180129233352533459">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‎‏‎‏‏‏‎‏‎‎‏‏‎Only the device owner can view and manage blocked numbers.‎‏‎‎‏‎"</string>
-    <string name="delete_icon_description" msgid="8903995728252556724">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‎‎‎‎‏‎‎‎‎‎‎‎‎‎‎‏‎‏‏‎‏‏‎‏‎‏‎‏‏‎‏‏‎‏‎‎‎Unblock‎‏‎‎‏‎"</string>
-    <string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‎‎‎‎‏‎‏‎‎‏‎‏‏‎‎‏‎‎‎‎‏‎‏‎‎‏‏‎‏‏‏‎‏‎‎‎‎‎‎‏‎‎‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‎Blocking temporarily off‎‏‎‎‏‎"</string>
-    <string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‎‎‏‏‎‏‎‎‎‏‎‏‎‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎After you dial or text an emergency number, blocking is turned off to ensure that emergency services can contact you.‎‏‎‎‏‎"</string>
-    <string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‎‎‎‏‏‏‎‏‎‎‎‏‎‎‎‎‏‎‎‏‎‎‎‎Re-enable now‎‏‎‎‏‎"</string>
-    <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g>‎‏‎‎‏‏‏‎ blocked‎‏‎‎‏‎"</string>
-    <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‎‎‎‎‎‎‎‎‎‎‏‎‏‏‎‎‎‎‎‎‏‏‎‏‎‎‎‏‎‎‎‎‏‏‎‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g>‎‏‎‎‏‏‏‎ unblocked‎‏‎‎‏‎"</string>
-    <string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‏‏‎‏‎‏‏‎‏‎‏‏‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‏‎Unable to block emergency number.‎‏‎‎‏‎"</string>
-    <string name="blocked_numbers_number_already_blocked_message" msgid="4392247814500811798">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‎‏‏‏‎‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‎‎‏‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is already blocked.‎‏‎‎‏‎"</string>
-    <string name="toast_personal_call_msg" msgid="5115361633476779723">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‎‏‎‏‏‎Using the personal dialer to make the call‎‏‎‎‏‎"</string>
-    <string name="notification_incoming_call" msgid="7713197997773986670">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‏‎‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎‎‏‏‏‎‎‏‏‏‎‎‏‎‎‏‎‏‎‎‏‏‎‏‏‎‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="CALL_VIA">%1$s</xliff:g>‎‏‎‎‏‏‏‎ call from ‎‏‎‎‏‏‎<xliff:g id="CALL_FROM">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="notification_incoming_video_call" msgid="6638486071698373893">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‏‏‏‏‎‏‎‏‏‎‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="CALL_VIA">%1$s</xliff:g>‎‏‎‎‏‏‏‎ video call from ‎‏‎‎‏‏‎<xliff:g id="CALL_FROM">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="answering_ends_other_call" msgid="8282145910153766401">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‎‎‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‏‎‎‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‏‎‎‎‎‎‎‎‎‏‎Answering will end your ‎‏‎‎‏‏‎<xliff:g id="CALL_VIA">%1$s</xliff:g>‎‏‎‎‏‏‏‎ call‎‏‎‎‏‎"</string>
-    <string name="answering_ends_other_calls" msgid="1198589551399049197">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‎‏‎Answering will end your ‎‏‎‎‏‏‎<xliff:g id="CALL_VIA">%1$s</xliff:g>‎‏‎‎‏‏‏‎ calls‎‏‎‎‏‎"</string>
-    <string name="answering_ends_other_video_call" msgid="8510410917384186360">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‏‎‎‎‏‏‏‎‏‎‎‏‏‏‎‏‎‎‏‎‏‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎‎‎Answering will end your ‎‏‎‎‏‏‎<xliff:g id="CALL_VIA">%1$s</xliff:g>‎‏‎‎‏‏‏‎ video call‎‏‎‎‏‎"</string>
-    <string name="answering_ends_other_managed_call" msgid="5186137550267947785">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‎‏‏‎‏‏‎‎‎‎‏‎‎‏‎Answering will end your ongoing call‎‏‎‎‏‎"</string>
-    <string name="answering_ends_other_managed_calls" msgid="6429838309560397988">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‎‏‎‏‎‎‏‎‎‎Answering will end your ongoing calls‎‏‎‎‏‎"</string>
-    <string name="answering_ends_other_managed_video_call" msgid="1585423762458248435">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‎‎‏‏‏‎‏‎‎‎‎‎‏‏‎‎‎‏‎‎‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‎‏‏‎Answering will end your ongoing video call‎‏‎‎‏‎"</string>
-    <string name="answer_incoming_call" msgid="4140530013111794587">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‎‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎Answer‎‏‎‎‏‎"</string>
-    <string name="decline_incoming_call" msgid="806026168661598368">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‎‏‎‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‎Decline‎‏‎‎‏‎"</string>
-    <string name="cant_call_due_to_ongoing_call" msgid="4952615196237854748">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‏‏‏‎‏‏‎‎‏‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‎‎‎‏‏‏‎‎‎Call cannot be placed due to your ‎‏‎‎‏‏‎<xliff:g id="OTHER_CALL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ call.‎‏‎‎‏‎"</string>
-    <string name="cant_call_due_to_ongoing_calls" msgid="1380804892363503856">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‏‏‎‎‏‎‏‎‎‏‏‎‎‏‏‎‏‎‏‎‏‏‏‎‏‏‏‏‎‏‏‎‎‏‎‏‏‏‎‎‏‎‏‎‏‏‏‎‎‎‏‏‏‏‎‎‎‎‎Call cannot be placed due to your ‎‏‎‎‏‏‎<xliff:g id="OTHER_CALL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ calls.‎‏‎‎‏‎"</string>
-    <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‏‏‏‎‏‎‎‎‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‎‎‎‎‏‏‎Call cannot be placed due to a call in another app.‎‏‎‎‏‎"</string>
-    <string name="notification_channel_incoming_call" msgid="3513761697082968084">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‎‎‏‏‎‏‏‎‎‎‏‏‏‎‏‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‎‎‎‏‎‏‎‎‎Incoming calls‎‏‎‎‏‎"</string>
-    <string name="notification_channel_missed_call" msgid="8727062678632713146">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‎‎‏‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‎‎‎‏‏‎‎‏‎‏‏‏‎‏‏‏‎‏‎‎Missed calls‎‏‎‎‏‎"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‏‎‎‎‏‏‏‎‏‎‎‏‎‎‏‏‎‏‏‏‎‎‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‎‎Call Blocking‎‏‎‎‏‎"</string>
-    <string name="alert_outgoing_call" msgid="982908156825958001">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‏‎‎‏‏‏‎‎‏‏‏‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‎Placing this call will end your ‎‏‎‎‏‏‎<xliff:g id="OTHER_APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎ call.‎‏‎‎‏‎"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‎‎‏‏‎‎‏‎‎‏‏‎‏‎Call Blocking‎‏‎‎‏‎"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‎‎‏‎‎‏‎‏‏‏‎‏‎‏‏‎‎‏‎‏‎‏‏‏‎‎‎‏‏‏‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‎‎Numbers not in Contacts‎‏‎‎‏‎"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‎‎‏‏‎‎‎‎‎‏‏‏‏‎Block numbers that are not listed in your Contacts‎‏‎‎‏‎"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‎‏‏‏‏‏‎‎‎‏‏‎‏‏‎‎Private‎‏‎‎‏‎"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‏‏‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎‎‏‎‏‏‏‏‎Block callers that do not disclose their number‎‏‎‎‏‎"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‎‎‎‏‎‏‏‏‎‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‎‎‏‏‎‏‎‎‎‏‏‎‎Pay phone‎‏‎‎‏‎"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‏‏‎‎‏‏‏‎‎‏‎‎‎‏‏‏‏‎‎‎‎‏‏‏‎‏‏‎‏‎‏‏‏‏‎‏‏‎‏‏‎‎‏‏‏‏‏‏‏‎‏‎Block calls from pay phones‎‏‎‎‏‎"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‏‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎Unknown‎‏‎‎‏‎"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‎‏‏‎‎‎‎‏‎‏‎‎‎‎‎‏‏‏‎‎‎‏‎‎‏‎‎‎‏‎Block calls from unidentified callers‎‏‎‎‏‎"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‎‎‎‏‎‏‏‏‎‎‏‎‎‎‎‎‎‏‎‏‎‏‏‏‎‏‏‎‎‏‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‎‎‎‎‎Call Blocking‎‏‎‎‏‎"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‎‏‏‏‏‎‎‎‎‎‏‎‎‎‎‎‎‏‎‏‎‎‏‎‎‏‎‏‎‏‏‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‏‏‎‏‎‏‎Call Blocking disabled‎‏‎‎‏‎"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‎‎‎Emergency call made‎‏‎‎‏‎"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‏‎‏‎‏‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‎‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‏‏‏‎‎‏‎‏‎‏‏‏‎‎‎Call Blocking has been disabled to allow emergency responders to contact you.‎‏‎‎‏‎"</string>
+    <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‎‎‎‎‏‏‏‏‎‎‎‏‏‎‎‎‏‏‎‎‎‏‏‏‎‎‏‎‎Quick response‎‏‎‎‏‎"</string>
+    <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‎‏‏‏‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‎‏‎Message sent to ‎‏‎‎‏‏‎<xliff:g id="PHONE_NUMBER">%s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
+    <string name="enable_account_preference_title" msgid="2021848090086481720">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‏‏‎‎‎‎‏‎‎‎‎‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎Calling accounts‎‏‎‎‏‎"</string>
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‏‎‏‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‎Only emergency calls are allowed.‎‏‎‎‏‎"</string>
+    <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‏‎‏‏‎‏‎‏‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‏‏‏‎‏‏‏‏‏‎‎‎This application cannot make outgoing calls without the Phone permission.‎‏‎‎‏‎"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‏‏‎‎‏‎‏‏‎‏‎‏‏‎‎‏‎‏‏‏‎‎‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎To place a call, enter a valid number.‎‏‎‎‏‎"</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‎‏‎‏‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‎‏‎‎Call cannot be added at this time.‎‏‎‎‏‎"</string>
+    <string name="no_vm_number" msgid="4164780423805688336">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‏‏‎‎‎‏‎‎‎‏‎‏‏‎‏‏‏‎‏‎‏‏‎‎‎‎‎‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‏‎‎‎‎‏‎‎‎‎‎Missing voicemail number‎‏‎‎‏‎"</string>
+    <string name="no_vm_number_msg" msgid="1300729501030053828">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‎‎‎‏‏‏‏‎‏‎‎‏‎‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‎‏‎‎‎‏‏‏‎‏‏‏‏‏‎‎‎‏‎‎‎No voicemail number is stored on the SIM card.‎‏‎‎‏‎"</string>
+    <string name="add_vm_number_str" msgid="4676479471644687453">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‎‏‏‎‎‎‏‏‎‎‎‏‎‏‎‎‏‏‎‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‎‎‏‎‏‏‏‎‏‎Add number‎‏‎‎‏‎"</string>
+    <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‎‏‎‏‏‏‎‏‏‎‏‏‎Make ‎‏‎‎‏‏‎<xliff:g id="NEW_APP">%s</xliff:g>‎‏‎‎‏‏‏‎ your default Phone app?‎‏‎‎‏‎"</string>
+    <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‏‎‎‏‏‎‎‎‏‎‎‏‎‏‏‏‎‏‎‎‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎‏‎‎‎‏‏‎‎‎‏‎‎‎Set Default‎‏‎‎‏‎"</string>
+    <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‎‎‎‏‏‎‏‏‏‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‎‎‏‎‏‎‏‎Cancel‎‏‎‎‏‎"</string>
+    <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‏‎‎‏‎‏‎‎‏‎‏‎‏‏‏‎‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎‎‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="NEW_APP">%s</xliff:g>‎‏‎‎‏‏‏‎ will be able to place and control all aspects of calls. Only apps you trust should be set as the default Phone app.‎‏‎‎‏‎"</string>
+    <string name="blocked_numbers" msgid="2751843139572970579">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‏‎‎‎‎‏‎‎‎‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‎‎‏‏‎Blocked numbers‎‏‎‎‏‎"</string>
+    <string name="blocked_numbers_msg" msgid="1045015186124965643">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‎‎‎‏‏‏‏‎‎‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‏‏‏‏‎‎‎‎‎‎‏‏‏‎‎‎‎‏‎‏‏‎You won\'t receive calls or texts from blocked numbers.‎‏‎‎‏‎"</string>
+    <string name="block_number" msgid="1101252256321306179">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‎‎‎‏‏‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‏‎‏‎‏‎‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‎Add a number‎‏‎‎‏‎"</string>
+    <string name="unblock_dialog_body" msgid="1614238499771862793">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‏‎‎‏‏‎‎‏‏‎‏‏‏‎‏‏‎‏‎‏‎‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‏‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‎‎‏‎‎‏‎Unblock ‎‏‎‎‏‏‎<xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <string name="unblock_button" msgid="3078048901972674170">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‎‏‏‏‎‏‏‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‏‏‎‏‎‎Unblock‎‏‎‎‏‎"</string>
+    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‏‏‎‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‎Block calls and texts from‎‏‎‎‏‎"</string>
+    <string name="add_blocked_number_hint" msgid="6847675097085433553">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‎‎‏‎‎‎‎‏‏‎‏‎‏‏‎‏‏‎‏‎‎‎‏‎Phone number‎‏‎‎‏‎"</string>
+    <string name="block_button" msgid="8822290682524373357">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‏‎‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‎‎‎‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎‏‎Block‎‏‎‎‏‎"</string>
+    <string name="non_primary_user" msgid="5180129233352533459">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‎‏‎‏‏‏‎‏‎‎‏‏‎Only the device owner can view and manage blocked numbers.‎‏‎‎‏‎"</string>
+    <string name="delete_icon_description" msgid="8903995728252556724">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‎‎‎‎‏‎‎‎‎‎‎‎‎‎‎‏‎‏‏‎‏‏‎‏‎‏‎‏‏‎‏‏‎‏‎‎‎Unblock‎‏‎‎‏‎"</string>
+    <string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‎‎‎‎‏‎‏‎‎‏‎‏‏‎‎‏‎‎‎‎‏‎‏‎‎‏‏‎‏‏‏‎‏‎‎‎‎‎‎‏‎‎‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‎Blocking temporarily off‎‏‎‎‏‎"</string>
+    <string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‎‎‏‏‎‏‎‎‎‏‎‏‎‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎After you dial or text an emergency number, blocking is turned off to ensure that emergency services can contact you.‎‏‎‎‏‎"</string>
+    <string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‎‎‎‏‏‏‎‏‎‎‎‏‎‎‎‎‏‎‎‏‎‎‎‎Re-enable now‎‏‎‎‏‎"</string>
+    <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g>‎‏‎‎‏‏‏‎ blocked‎‏‎‎‏‎"</string>
+    <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‎‎‎‎‎‎‎‎‎‎‏‎‏‏‎‎‎‎‎‎‏‏‎‏‎‎‎‏‎‎‎‎‏‏‎‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g>‎‏‎‎‏‏‏‎ unblocked‎‏‎‎‏‎"</string>
+    <string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‏‏‎‏‎‏‏‎‏‎‏‏‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‏‎Unable to block emergency number.‎‏‎‎‏‎"</string>
+    <string name="blocked_numbers_number_already_blocked_message" msgid="4392247814500811798">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‎‏‏‏‎‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‎‎‏‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is already blocked.‎‏‎‎‏‎"</string>
+    <string name="toast_personal_call_msg" msgid="5115361633476779723">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‎‏‎‏‏‎Using the personal dialer to make the call‎‏‎‎‏‎"</string>
+    <string name="notification_incoming_call" msgid="7713197997773986670">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‏‎‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎‎‏‏‏‎‎‏‏‏‎‎‏‎‎‏‎‏‎‎‏‏‎‏‏‎‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="CALL_VIA">%1$s</xliff:g>‎‏‎‎‏‏‏‎ call from ‎‏‎‎‏‏‎<xliff:g id="CALL_FROM">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="notification_incoming_video_call" msgid="6638486071698373893">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‏‏‏‏‎‏‎‏‏‎‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="CALL_VIA">%1$s</xliff:g>‎‏‎‎‏‏‏‎ video call from ‎‏‎‎‏‏‎<xliff:g id="CALL_FROM">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="answering_ends_other_call" msgid="8282145910153766401">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‎‎‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‏‎‎‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‏‎‎‎‎‎‎‎‎‏‎Answering will end your ‎‏‎‎‏‏‎<xliff:g id="CALL_VIA">%1$s</xliff:g>‎‏‎‎‏‏‏‎ call‎‏‎‎‏‎"</string>
+    <string name="answering_ends_other_calls" msgid="1198589551399049197">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‎‏‎Answering will end your ‎‏‎‎‏‏‎<xliff:g id="CALL_VIA">%1$s</xliff:g>‎‏‎‎‏‏‏‎ calls‎‏‎‎‏‎"</string>
+    <string name="answering_ends_other_video_call" msgid="8510410917384186360">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‏‎‎‎‏‏‏‎‏‎‎‏‏‏‎‏‎‎‏‎‏‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎‎‎Answering will end your ‎‏‎‎‏‏‎<xliff:g id="CALL_VIA">%1$s</xliff:g>‎‏‎‎‏‏‏‎ video call‎‏‎‎‏‎"</string>
+    <string name="answering_ends_other_managed_call" msgid="5186137550267947785">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‎‏‏‎‏‏‎‎‎‎‏‎‎‏‎Answering will end your ongoing call‎‏‎‎‏‎"</string>
+    <string name="answering_ends_other_managed_calls" msgid="6429838309560397988">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‎‏‎‏‎‎‏‎‎‎Answering will end your ongoing calls‎‏‎‎‏‎"</string>
+    <string name="answering_ends_other_managed_video_call" msgid="1585423762458248435">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‎‎‏‏‏‎‏‎‎‎‎‎‏‏‎‎‎‏‎‎‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‎‏‏‎Answering will end your ongoing video call‎‏‎‎‏‎"</string>
+    <string name="answer_incoming_call" msgid="4140530013111794587">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‎‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎Answer‎‏‎‎‏‎"</string>
+    <string name="decline_incoming_call" msgid="806026168661598368">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‎‏‎‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‎Decline‎‏‎‎‏‎"</string>
+    <string name="cant_call_due_to_ongoing_call" msgid="4952615196237854748">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‏‏‏‎‏‏‎‎‏‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‎‎‎‏‏‏‎‎‎Call cannot be placed due to your ‎‏‎‎‏‏‎<xliff:g id="OTHER_CALL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ call.‎‏‎‎‏‎"</string>
+    <string name="cant_call_due_to_ongoing_calls" msgid="1380804892363503856">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‏‏‎‎‏‎‏‎‎‏‏‎‎‏‏‎‏‎‏‎‏‏‏‎‏‏‏‏‎‏‏‎‎‏‎‏‏‏‎‎‏‎‏‎‏‏‏‎‎‎‏‏‏‏‎‎‎‎‎Call cannot be placed due to your ‎‏‎‎‏‏‎<xliff:g id="OTHER_CALL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ calls.‎‏‎‎‏‎"</string>
+    <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‏‏‏‎‏‎‎‎‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‎‎‎‎‏‏‎Call cannot be placed due to a call in another app.‎‏‎‎‏‎"</string>
+    <string name="notification_channel_incoming_call" msgid="3513761697082968084">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‎‎‏‏‎‏‏‎‎‎‏‏‏‎‏‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‎‎‎‏‎‏‎‎‎Incoming calls‎‏‎‎‏‎"</string>
+    <string name="notification_channel_missed_call" msgid="8727062678632713146">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‎‎‏‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‎‎‎‏‏‎‎‏‎‏‏‏‎‏‏‏‎‏‎‎Missed calls‎‏‎‎‏‎"</string>
+    <string name="alert_outgoing_call" msgid="982908156825958001">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‏‎‎‏‏‏‎‎‏‏‏‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‎Placing this call will end your ‎‏‎‎‏‏‎<xliff:g id="OTHER_APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎ call.‎‏‎‎‏‎"</string>
 </resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 35f2cd7..fc35dcf 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"No se puede realizar la llamada porque hay una llamada en curso en otra app."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Llamadas entrantes"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Llamadas perdidas"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Bloqueo de llamadas"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Si realizas esta llamada, finalizará la de <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Bloqueo de llamadas"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Números que no están en Contactos"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Bloquear números que no estén en tus Contactos"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privado"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Bloquear llamadas de emisores con números ocultos"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Teléfono público"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Bloquear llamadas provenientes de teléfonos públicos"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Desconocido"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Bloquear llamadas de emisores desconocidos"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Bloqueo de llamadas"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Se inhabilitó el bloqueo de llamadas"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Se realizó una llamada de emergencia"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Se inhabilitó el bloqueo de llamadas para permitir que los servicios de emergencia se comuniquen contigo."</string>
 </resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 43fbb9f..3c08971 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -54,7 +54,7 @@
     <string name="block_number" msgid="1101252256321306179">"Añadir un número"</string>
     <string name="unblock_dialog_body" msgid="1614238499771862793">"¿Desbloquear el número <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>?"</string>
     <string name="unblock_button" msgid="3078048901972674170">"Desbloquear"</string>
-    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"Bloquear llamadas y mensajes de texto del"</string>
+    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"Bloquear llamadas y mensajes de texto del número"</string>
     <string name="add_blocked_number_hint" msgid="6847675097085433553">"Número de teléfono"</string>
     <string name="block_button" msgid="8822290682524373357">"Bloquear"</string>
     <string name="non_primary_user" msgid="5180129233352533459">"Solo el propietario del dispositivo puede ver y administrar los números bloqueados."</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"No puedes llamar porque tienes una llamada en curso en otra aplicación."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Llamadas entrantes"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Llamadas perdidas"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Bloqueo de llamadas"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Si haces esta llamada, se finalizará la de <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Bloqueo de llamadas"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Números que no están en Contactos"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Bloquea los números que no estén en Contactos"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privada"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Bloquea las llamadas que tengan el número oculto"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Teléfono público"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Bloquea las llamadas de teléfonos públicos"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Desconocida"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Bloquea las llamadas de números desconocidos"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Bloqueo de llamadas"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Se ha inhabilitado el bloqueo de llamadas"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Se ha hecho una llamada de emergencia"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Se ha inhabilitado el bloqueo de llamadas para que los servicios de emergencia puedan ponerse en contacto contigo."</string>
 </resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 53443ca..70a4cf4 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Kõnet ei saa teise rakenduse kõne tõttu teha."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Sissetulevad kõned"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Vastamata kõned"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Kõnede blokeerimine"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Selle kõne tegemisel lõpetatakse pooleliolev kõne rakenduses <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Kõnede blokeerimine"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Numbrid, mis ei ole kontaktide hulgas"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blokeeritud numbreid ei lisata teie kontaktide hulka"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privaatne"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Nende helistajate blokeerimine, kes ei avalda oma numbrit"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Telefoniautomaat"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Kõnede blokeerimine telefoniautomaatidest"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Tundmatu"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Kõnede blokeerimine tuvastamata helistajatelt"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Kõnede blokeerimine"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Kõnede blokeerimine on keelatud"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Tehti hädaabikõne"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Kõnede blokeerimine on keelatud, et lubada hädaabiteenustel teiega ühendust võtta."</string>
 </resources>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 094e813..529c845 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -52,7 +52,7 @@
     <string name="blocked_numbers" msgid="2751843139572970579">"Blokeatutako zenbakiak"</string>
     <string name="blocked_numbers_msg" msgid="1045015186124965643">"Ez duzu jasoko deirik edo testu-mezurik blokeatutako zenbakietatik."</string>
     <string name="block_number" msgid="1101252256321306179">"Gehitu zenbakia"</string>
-    <string name="unblock_dialog_body" msgid="1614238499771862793">"<xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g> desblokeatu nahi duzu?"</string>
+    <string name="unblock_dialog_body" msgid="1614238499771862793">"<xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g> desblokeatu?"</string>
     <string name="unblock_button" msgid="3078048901972674170">"Desblokeatu"</string>
     <string name="add_blocked_dialog_body" msgid="9030243212265516828">"Blokeatu zenbaki honetatik jasotzen diren deiak eta testu-mezuak:"</string>
     <string name="add_blocked_number_hint" msgid="6847675097085433553">"Telefono-zenbakia"</string>
@@ -64,7 +64,7 @@
     <string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"Gaitu berriro"</string>
     <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"Blokeatu da <xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g>"</string>
     <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"Desblokeatu da <xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g>"</string>
-    <string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"Ezin da blokeatu larrialdietarako zenbakia."</string>
+    <string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"Ezin da blokeatu larrialdi-zenbakia."</string>
     <string name="blocked_numbers_number_already_blocked_message" msgid="4392247814500811798">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> blokeatuta dago dagoeneko."</string>
     <string name="toast_personal_call_msg" msgid="5115361633476779723">"Telefono pertsonala erabiltzen ari zara deia egiteko"</string>
     <string name="notification_incoming_call" msgid="7713197997773986670">"<xliff:g id="CALL_VIA">%1$s</xliff:g> deia (deitzailea: <xliff:g id="CALL_FROM">%2$s</xliff:g>)"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Ezin da egin deia, beste dei bat abian delako beste aplikazio batean."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Jasotako deiak"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Dei galduak"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Deiak blokeatzeko aukera"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Dei hau egiten baduzu, amaitu egingo da <xliff:g id="OTHER_APP">%1$s</xliff:g> aplikazioko deia."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Deiak blokeatzeko aukera"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Kontaktuak zerbitzuan ez dauden zenbakiak"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blokeatu Kontaktuak zerbitzuan zerrendatuta ez dauden zenbakiak"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Pribatua"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Blokeatu zenbakia erakusten ez duten deitzaileak"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Telefono publikoa"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Blokeatu telefono publikoen deiak"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Ezezaguna"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Blokeatu identifikatu gabeko deitzaileen deiak"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Deiak blokeatzeko aukera"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Desgaitu da deiak blokeatzeko aukera"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Larrialdi-deia egin da"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Desgaitu da deiak blokeatzeko aukera, larrialdietako zerbitzuak zurekin harremanetan jarri ahal daitezen."</string>
 </resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index b3f8d1e..80754b8 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"به دلیل تماسی در برنامه دیگر، نمی‌توان تماسی برقرار کرد."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"تماس‌های ورودی"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"تماس‌های بی‌پاسخ"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"مسدود کردن تماس"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"اگر این تماس را برقرار کنید، تماس <xliff:g id="OTHER_APP">%1$s</xliff:g> شما قطع می‌شود."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"مسدود کردن تماس"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"شماره‌هایی که در «مخاطبین» نیستند"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"مسدود کردن شماره‌هایی که در «مخاطبین» شما نیستند"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"خصوصی"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"مسدود کردن تماس‌گیرندگانی که شماره‌شان را افشا نمی‌کنند"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"تلفن عمومی"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"مسدود کردن تماس‌ها از تلفن‌های عمومی"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"ناشناس"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"مسدودن تماس‌های تماس‌گیرندگان ناشناس"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"مسدود کردن تماس"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"مسدود کردن تماس غیرفعال شد"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"تماس اضطراری برقرار شد"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"مسدود کردن تماس غیرفعال شده است تا پاسخ‌دهندگان اضطراری بتوانند با شما تماس بگیرند."</string>
 </resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 73cb390..d65e584 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Puhelua ei voi soittaa, koska toisessa sovelluksessa on puhelu käynnissä."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Saapuvat puhelut"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Vastaamattomat puhelut"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Puhelujen esto"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Tämän puhelun soittaminen päättää puhelun sovelluksessa <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Puhelujen esto"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Numerot eivät ole yhteystiedoissa"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Toiminto estää numerot, jotka eivät ole yhteystiedoissasi"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Yksityinen"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Estä soittajat, jotka ovat estäneet oman numeronsa näkymisen"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Yleisöpuhelin"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Estä yleisöpuhelimista soitetut puhelut"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Tuntematon"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Estä tuntemattomien soittajien puhelut"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Puhelujen esto"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Puhelujen esto poistettu käytöstä"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Hätäpuhelu soitettu"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Puhelujen esto on poistettu käytöstä, jotta pelastusviranomaiset voivat soittaa puhelimeesi."</string>
 </resources>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index b90b2ff..7cba712 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Impossible de faire l\'appel en raison d\'un appel dans une autre application."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Appels entrants"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Appels manqués"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Blocage des appels"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Si vous passez cet appel, vous mettrez fin à l\'appel <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Blocage des appels"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Numéros non répertoriés dans les contacts"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Bloquer les numéros non répertoriés dans vos contacts"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privé"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Bloquer les appelants qui ne divulguent pas leur numéro"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Téléphone public"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Bloquer les appels provenant de téléphones publics"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Inconnu"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Bloquer les appels provenant d\'appelants non identifiés"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Blocage des appels"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Blocage des appels désactivé"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Appel d\'urgence effectué"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Le blocage des appels a été désactivé pour permettre aux intervenants d\'urgence de communiquer avec vous."</string>
 </resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index f7a5a00..12701d8 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -28,10 +28,10 @@
     <string name="notification_missedCall_message" msgid="3049928912736917988">"Message"</string>
     <string name="accessibility_call_muted" msgid="2776111226185342220">"Son coupé"</string>
     <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"Haut-parleur activé"</string>
-    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"Je ne peux pas répondre. Ça va ?"</string>
+    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"Peux pas parler. Quoi de neuf ?"</string>
     <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"Je te rappelle tout de suite."</string>
-    <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"Je t\'appelle plus tard."</string>
-    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"Peux pas répondre. On se rappelle ?"</string>
+    <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"Je t\'appellerai plus tard."</string>
+    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"Peux pas parler. On se rappelle ?"</string>
     <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"Réponses rapides"</string>
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Modifier les réponses rapides"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
@@ -54,7 +54,7 @@
     <string name="block_number" msgid="1101252256321306179">"Ajouter un numéro"</string>
     <string name="unblock_dialog_body" msgid="1614238499771862793">"Débloquer <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g> ?"</string>
     <string name="unblock_button" msgid="3078048901972674170">"Débloquer"</string>
-    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"Bloquer les appels et les SMS provenant du :"</string>
+    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"Bloquer les appels et les SMS provenant du numéro :"</string>
     <string name="add_blocked_number_hint" msgid="6847675097085433553">"Numéro de téléphone"</string>
     <string name="block_button" msgid="8822290682524373357">"Bloquer"</string>
     <string name="non_primary_user" msgid="5180129233352533459">"Seul le propriétaire de l\'appareil peut afficher et gérer les numéros bloqués."</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Vous ne pouvez pas passer cet appel, car vous avez une communication en cours dans une autre application."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Appels entrants"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Appels manqués"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Blocage d\'appels"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Si vous passez cet appel, vous mettrez fin à celui qui est en cours dans l\'application <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Blocage d\'appels"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Numéros non répertoriés dans Contacts"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Bloquez les numéros qui ne figurent pas dans votre annuaire Contacts"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Appels masqués"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Bloquez les appelants qui masquent leur numéro"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Cabines téléphoniques"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Bloquez les appels provenant de cabines téléphoniques"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Numéros inconnus"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Bloquez les appels provenant de personnes non identifiées"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Blocage d\'appels"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Blocage d\'appels désactivé"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Appel d\'urgence"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Le blocage d\'appels a été désactivé pour que les services d\'urgence puissent vous contacter."</string>
 </resources>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index abfecee..7217797 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -38,7 +38,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Resposta rápida"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mensaxe enviada ao <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Contas de chamadas"</string>
-    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Só se permiten chamadas de emerxencia."</string>
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Só se permiten chamadas de urxencia."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Esta aplicación non pode facer chamadas saíntes sen permiso do teléfono."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Para realizar unha chamada, introduce un número válido."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Neste momento non se pode engadir a chamada."</string>
@@ -60,11 +60,11 @@
     <string name="non_primary_user" msgid="5180129233352533459">"Só o propietario do dispositivo pode ver e xestionar os números bloqueados."</string>
     <string name="delete_icon_description" msgid="8903995728252556724">"Desbloquear"</string>
     <string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"O bloqueo desactivouse temporalmente"</string>
-    <string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"Despois de facer unha chamada ou enviar unha mensaxe a un número de emerxencia, desactívase o bloqueo para garantir que os servizos de emerxencia poidan poñerse en contacto contigo."</string>
+    <string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"Despois de facer unha chamada ou enviar unha mensaxe a un número de urxencia, desactívase o bloqueo para garantir que os servizos de urxencia poidan poñerse en contacto contigo."</string>
     <string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"Volver activar agora"</string>
     <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"Bloqueouse o <xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g>"</string>
     <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"Desbloqueouse o <xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g>"</string>
-    <string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"Non se pode bloquear o número de emerxencia."</string>
+    <string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"Non se pode bloquear o número de urxencia."</string>
     <string name="blocked_numbers_number_already_blocked_message" msgid="4392247814500811798">"O <xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> xa está bloqueado."</string>
     <string name="toast_personal_call_msg" msgid="5115361633476779723">"Usando o marcador persoal para facer a chamada"</string>
     <string name="notification_incoming_call" msgid="7713197997773986670">"Chamada de <xliff:g id="CALL_FROM">%2$s</xliff:g> a través de <xliff:g id="CALL_VIA">%1$s</xliff:g>"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Non se pode realizar a chamada porque hai chamadas en curso noutra aplicación."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Chamadas entrantes"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Chamadas perdidas"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Bloqueo de chamadas"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Ao facer esta chamada, finalizarase o túa chamada de <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Bloqueo de chamadas"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Números que non aparezan nos contactos"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Bloquea números que non aparezan entre os teus contactos"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privado"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Bloquea os emisores de chamada que non revelen os seus números"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Teléfono público"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Bloquea as chamadas de teléfonos públicos"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Descoñecido"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Bloquea as chamadas de emisores non identificados"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Bloqueo de chamadas"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Desactivouse o bloqueo de chamadas"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Realizouse unha chamada de emerxencia"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Desactivouse o bloqueo de chamadas parar permitir que os servizos de emerxencias se poidan poñer en contacto contigo."</string>
 </resources>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index 950a0ed..daa3945 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"અન્ય ઍપ્લિકેશનમાં કૉલને કારણે કૉલ કરી શકતાં નથી."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"ઇનકમિંગ કૉલ"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"છૂટેલા કૉલ"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"કૉલ બ્લૉક કરી રહ્યાં છીએ"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"આ કૉલ કરવાથી તમારો <xliff:g id="OTHER_APP">%1$s</xliff:g> કૉલ સમાપ્ત થઈ જશે."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"કૉલ બ્લૉક કરી રહ્યાં છીએ"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"સંપર્કોમાં આ નંબર નથી"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"તમારા સંપર્કોમાં જે નંબર સૂચિબદ્ધ ન હોય તેને બ્લૉક કરો"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"ખાનગી"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"જે કૉલર પોતાનો નંબર ન બતાવે તેમને બ્લૉક કરો"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"પે ફોન"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"પે ફોન પરના કૉલ બ્લૉક કરો"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"અજાણ્યા"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"અજાણ્યા કૉલરના કૉલ બ્લૉક કરો"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"કૉલ બ્લૉક કરી રહ્યાં છીએ"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"કૉલ બ્લૉક કરવાનું બંધ કરવામાં આવ્યું છે"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"કટોકટીનો કૉલ કર્યો"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"કટોકટીમાં પ્રતિસાદ કરનારાઓ તમારો સંપર્ક કરી શકે તે માટે કૉલ બ્લૉક કરવાનું બંધ કરવામાં આવ્યું છે."</string>
 </resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index a804a8b..2c4dd3c 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -25,15 +25,15 @@
     <string name="notification_missedCallsMsg" msgid="4575787816055205600">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> छूटी कॉल"</string>
     <string name="notification_missedCallTicker" msgid="504686252427747209">"<xliff:g id="MISSED_CALL_FROM">%s</xliff:g> की कॉल छूटी"</string>
     <string name="notification_missedCall_call_back" msgid="2684890353590890187">"वापस कॉल करें"</string>
-    <string name="notification_missedCall_message" msgid="3049928912736917988">"मैसेज"</string>
+    <string name="notification_missedCall_message" msgid="3049928912736917988">"संदेश"</string>
     <string name="accessibility_call_muted" msgid="2776111226185342220">"कॉल म्‍यूट की गई."</string>
     <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"स्‍पीकरफ़ोन सक्षम."</string>
-    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"अभी बात नहीं हो सकती. क्‍या हो रहा है?"</string>
-    <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"मैं जल्दी ही कॉल करता हूं/करती हूं."</string>
+    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"अभी बात नहीं हो सकती. क्‍या चल रहा है?"</string>
+    <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"मैं आपको वापस कॉल करूंगा/करूंगी."</string>
     <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"मैं आपको बाद में कॉल करूंगा/करूंगी."</string>
-    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"अभी बात नहीं हो सकती. मुझे बाद में कॉल करेंगे?"</string>
+    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"अभी बात नहीं हो सकती. बाद में कॉल करें?"</string>
     <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"झटपट उत्तर"</string>
-    <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"पहले से तैयार जवाब में बदलाव करें"</string>
+    <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"झटपट उत्तर संपादित करें"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"झटपट उत्तर"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> को संदेश भेजा गया."</string>
@@ -50,11 +50,11 @@
     <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"अभी नहीं"</string>
     <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> कॉल करने और कॉल से संबंधित सभी पहलुओं को नियंत्रित कर पाएगा. केवल उन्हीं ऐप्लिकेशन को डिफ़ॉल्ट फ़ोन ऐप्लिकेशन के रूप में सेट करना चाहिए जिन पर आप विश्वास करते हैं."</string>
     <string name="blocked_numbers" msgid="2751843139572970579">"अवरोधित नंबर"</string>
-    <string name="blocked_numbers_msg" msgid="1045015186124965643">"आपको ब्लॉक किए गए नंबर से कॉल या मैसेज नहीं मिलेंगे."</string>
+    <string name="blocked_numbers_msg" msgid="1045015186124965643">"आपको अवरुद्ध किए गए नंबर से कॉल या लेख संदेश नहीं मिलेंगे."</string>
     <string name="block_number" msgid="1101252256321306179">"नंबर जोड़ें"</string>
     <string name="unblock_dialog_body" msgid="1614238499771862793">"<xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g> को अनवरोधित करें?"</string>
     <string name="unblock_button" msgid="3078048901972674170">"अनवरोधित करें"</string>
-    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"इसके कॉल और मैसेज रोकें"</string>
+    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"इसके कॉल और लेख अवरुद्ध करें"</string>
     <string name="add_blocked_number_hint" msgid="6847675097085433553">"फ़ोन नंबर"</string>
     <string name="block_button" msgid="8822290682524373357">"अवरुद्ध करें"</string>
     <string name="non_primary_user" msgid="5180129233352533459">"केवल डिवाइस स्वामी अवरुद्ध किए गए नंबर देख और प्रबंधित कर सकते हैं."</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"किसी दूसरे ऐप्लिकेशन में कॉल के कारण कॉल नहीं लगाया जा सकता."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"इनकमिंग कॉल"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"छूटे कॉल"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"कॉल पर रोक"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"इस कॉल को करने से आपका <xliff:g id="OTHER_APP">%1$s</xliff:g> कॉल समाप्त हो जाएगा."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"कॉल पर रोक"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"वे नंबर जो संपर्कों में नहीं हैं"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"उन नंबरों पर रोक लगाएं, जो आपके संपर्क में मौजूद नहीं हैं"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"निजी"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"अपना नंबर ज़ाहिर न करने वाले कॉलर पर रोक लगाएं"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"पे फ़ोन"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"पे फ़ोन से आने वाले कॉल पर रोक लगाएं"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"अज्ञात"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"अनजान कॉलर के कॉल पर रोक लगाएं"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"कॉल पर रोक"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"कॉल पर रोक लगाने की सुविधा बंद है"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"आपातकालीन कॉल किया गया"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"आपातकालीन सहायता कर्मचारी आपसे संपर्क कर सकें, इसलिए कॉल पर रोक लगाने की सुविधा बंद कर दी गई है."</string>
 </resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 1b46287..6889507 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Poziv se ne može uspostaviti zbog poziva u drugoj aplikaciji."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Dolazni pozivi"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Propušteni pozivi"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Blokiranje poziva"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Upućivanjem ovog poziva prekinut ćete poziv u aplikaciji <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Blokiranje poziva"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Brojevi koji nisu u kontaktima"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blokirajte brojeve koje nemate u kontaktima"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privatno"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Blokirajte pozivatelje koji ne žele otkriti svoj broj"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Telefonska govornica"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Blokirajte pozive s telefonskih govornica"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Nepoznato"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Blokirajte pozive nepoznatih pozivatelja"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Blokiranje poziva"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Blokiranje poziva je onemogućeno"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Hitni je poziv upućen"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Blokiranje poziva onemogućeno je da bi vas mogli kontaktirati djelatnici hitnih službi."</string>
 </resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index effd923..26d0c42 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Egy másik alkalmazásban folytatott hívás miatt nem indítható hívás."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Beérkező hívások"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Nem fogadott hívások"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Hívásletiltás"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Ha hívást indít, azzal megszakítja a(z) <xliff:g id="OTHER_APP">%1$s</xliff:g>-hívást."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Hívásletiltás"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"A névjegyek között nem szereplő számok"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"A névjegyek között nem szereplő számok letiltása"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privát"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"A privát számról hívók letiltása"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Nyilvános telefon"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"A nyilvános telefonokról bejövő hívások letiltása"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Ismeretlen"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"A nem azonosított hívók letiltása"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Hívásletiltás"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Hívásletiltás kikapcsolva"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Segélyhívás indítva"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"A hívásletiltás ki van kapcsolva, hogy a segélyszolgálatok kapcsolatba léphessenek Önnel."</string>
 </resources>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 6782685..c768e8d 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -25,7 +25,7 @@
     <string name="notification_missedCallsMsg" msgid="4575787816055205600">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> բաց թողնված զանգ"</string>
     <string name="notification_missedCallTicker" msgid="504686252427747209">"Բաց թողնված զանգ <xliff:g id="MISSED_CALL_FROM">%s</xliff:g>-ից"</string>
     <string name="notification_missedCall_call_back" msgid="2684890353590890187">"Հետ զանգել"</string>
-    <string name="notification_missedCall_message" msgid="3049928912736917988">"Գրել"</string>
+    <string name="notification_missedCall_message" msgid="3049928912736917988">"Ուղարկել հաղորդագրություն"</string>
     <string name="accessibility_call_muted" msgid="2776111226185342220">"Զանգը խլացված է:"</string>
     <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"Բարձրախոսը միացված է:"</string>
     <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"Հիմա չեմ կարող խոսել: Ի՞նչ կա:"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Զանգը հնարավոր չէ կատարել՝ մեկ այլ հավելվածի ընթացիկ զանգի պատճառով:"</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Մուտքային զանգեր"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Բաց թողնված զանգեր"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Զանգերի արգելափակում"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Այս զանգը կատարելու դեպքում <xliff:g id="OTHER_APP">%1$s</xliff:g>-ի ընթացիկ զանգը կընդհատվի"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Զանգերի արգելափակում"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Կոնտակտներում չներառված համարներ"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Արգելափակել համարները, որոնք ձեր կոնտակտներում չկան"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Փակ համարներ"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Արգելափակել փակ համարներից եկող զանգերը"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Ավտոմատ հեռախոսներ"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Արգելափակել ավտոմատ հեռախոսներից եկող զանգերը"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Անհայտ համարներ"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Արգելափակել անհայտ համարներից եկող զանգերը"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Զանգերի արգելափակում"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Զանգերի արգելափակումն անջատած է"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Կատարվեց շտապ կանչ"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Զանգերի արգելափակումն անջատվել է, որպեսզի արտակարգ ծառայությունները կարողանան ձեզ զանգել:"</string>
 </resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 0d9a31f..5fdf63b 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Panggilan tidak dapat dilakukan karena adanya panggilan di aplikasi lain."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Panggilan masuk"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Panggilan tak terjawab"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Pemblokiran Panggilan"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Melakukan panggilan ini akan mengakhiri panggilan <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Pemblokiran Panggilan"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Nomor yang tidak ada di Kontak"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blokir nomor yang tidak tercantum di Kontak Anda"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Pribadi"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Blokir penelepon yang menyembunyikan nomornya"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Telepon umum"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Blokir panggilan dari telepon umum"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Tidak tahu"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Blokir panggilan dari penelepon yang tidak dikenal"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Pemblokiran Panggilan"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Pemblokiran Panggilan dinonaktifkan"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Panggilan darurat dibuat"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Pemblokiran Panggilan dinonaktifkan untuk mengizinkan penjawab darurat menghubungi Anda."</string>
 </resources>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index c41f657..743aa5a 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Ekki er hægt að hringja sökum símtals í öðru forriti."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Móttekin símtöl"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Ósvöruð símtöl"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Lokað fyrir símtöl"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Ef þú hringir mun þessu símtali í <xliff:g id="OTHER_APP">%1$s</xliff:g> ljúka."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Lokað fyrir símtöl"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Númer sem eru ekki í tengiliðum"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Loka fyrir númer sem eru ekki á tengiliðalista"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Lokað"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Loka á hringjendur sem birta ekki símanúmer"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Almenningssími"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Loka fyrir símtöl úr almenningssímum"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Óþekkt"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Loka fyrir símtöl frá óþekktum hringjendum"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Lokað fyrir símtöl"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Ekki er lokað fyrir símtöl"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Neyðarsímtal var hringt"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Slökkt hefur verið á „Lokað fyrir símtöl“ svo neyðarþjónustuaðilar geti haft samband við þig."</string>
 </resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index e5e63cc..af92640 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Impossibile effettuare la chiamata a causa di una chiamata in un\'altra app."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Chiamate in arrivo"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Chiamate perse"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Blocco delle chiamate"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Se effettui questa chiamata, la chiamata di <xliff:g id="OTHER_APP">%1$s</xliff:g> verrà terminata."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Blocco delle chiamate"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Numeri esterni ai Contatti"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blocca i numeri non elencati nei Contatti"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privato"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Blocca i chiamanti che nascondono il loro numero"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Cabina telefonica"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Blocca le chiamate dalle cabine telefoniche"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Sconosciuto"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Blocca le chiamate da chiamanti non identificati"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Blocco delle chiamate"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Blocco delle chiamate disattivato"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Chiamata di emergenza effettuata"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Il blocco delle chiamate è stato disattivato per consentire ai servizi di emergenza di contattarti."</string>
 </resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 9027561..a68ceee 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -25,13 +25,13 @@
     <string name="notification_missedCallsMsg" msgid="4575787816055205600">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> שיחות שלא נענו"</string>
     <string name="notification_missedCallTicker" msgid="504686252427747209">"שיחה שלא נענתה מאת <xliff:g id="MISSED_CALL_FROM">%s</xliff:g>"</string>
     <string name="notification_missedCall_call_back" msgid="2684890353590890187">"התקשר חזרה"</string>
-    <string name="notification_missedCall_message" msgid="3049928912736917988">"שליחת הודעה"</string>
+    <string name="notification_missedCall_message" msgid="3049928912736917988">"שלח הודעה"</string>
     <string name="accessibility_call_muted" msgid="2776111226185342220">"שיחה מושתקת."</string>
     <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"רמקול מופעל."</string>
     <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"לא נוח לי עכשיו. מה קורה?"</string>
     <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"תיכף אחזור אליך."</string>
     <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"אני אתקשר אליך יותר מאוחר."</string>
-    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"לא נוח לי עכשיו. נדבר אחר כך?"</string>
+    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"לא נוח לי עכשיו. תתקשר מאוחר יותר?"</string>
     <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"תגובות מהירות"</string>
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"תגובות מהירות"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
@@ -53,10 +53,10 @@
     <string name="blocked_numbers_msg" msgid="1045015186124965643">"לא יגיעו אליך שיחות או הודעות טקסט מהמספרים החסומים."</string>
     <string name="block_number" msgid="1101252256321306179">"מספר חדש"</string>
     <string name="unblock_dialog_body" msgid="1614238499771862793">"האם לבטל את חסימת המספר <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>?"</string>
-    <string name="unblock_button" msgid="3078048901972674170">"ביטול חסימה"</string>
-    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"חסימת שיחות והודעות טקסט מ-"</string>
+    <string name="unblock_button" msgid="3078048901972674170">"בטל חסימה"</string>
+    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"חסום שיחות והודעות טקסט מ-"</string>
     <string name="add_blocked_number_hint" msgid="6847675097085433553">"מספר טלפון"</string>
-    <string name="block_button" msgid="8822290682524373357">"חסימה"</string>
+    <string name="block_button" msgid="8822290682524373357">"חסום"</string>
     <string name="non_primary_user" msgid="5180129233352533459">"רק בעל המכשיר יכול להציג ולנהל מספרים חסומים."</string>
     <string name="delete_icon_description" msgid="8903995728252556724">"ביטול חסימה"</string>
     <string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"החסימה הושבתה זמנית"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"אי אפשר להתקשר בגלל שיש שיחה באפליקציה אחרת."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"שיחות נכנסות"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"שיחות שלא נענו"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"חסימת שיחות"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"ביצוע השיחה הזו יסיים את השיחה ב-<xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"חסימת שיחות"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"מספרים שאינם באנשי הקשר"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"חסימת שיחות ממספרים שאינם ברשימה של אנשי הקשר"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"מספרים פרטיים"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"חסימת שיחות מאנשים שלא חושפים את המספר שלהם"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"טלפונים ציבוריים"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"חסימת שיחות מטלפונים ציבוריים"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"מספרים לא ידועים"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"חסימת שיחות ממספרים לא מזוהים"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"חסימת שיחות"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"חסימת השיחות הושבתה"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"בוצעה שיחת חירום"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"חסימת השיחות הושבתה כדי לאפשר לצוותי עזרה ראשונה להתקשר אליך."</string>
 </resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 70543e7..a7fcb0e 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"別のアプリで通話中のため、この通話を発信することはできません。"</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"着信"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"不在着信"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"着信のブロック"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"この通話を発信すると、<xliff:g id="OTHER_APP">%1$s</xliff:g> の通話が終了します。"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"着信のブロック"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"連絡帳にない番号"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"連絡帳にリストされていない番号をブロック"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"非通知"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"番号非通知の発信者をブロック"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"公衆電話"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"公衆電話からの着信をブロック"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"不明"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"不明な発信者からの着信をブロック"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"着信のブロック"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"着信のブロックを無効にしました"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"緊急通報"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"着信のブロックを無効して、救急隊員などがあなたに連絡できるようにしました。"</string>
 </resources>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index 1a39384..34dc303 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"ზარი ვერ ხორციელდება ზარის გამო სხვა აპში."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"შემომავალი ზარები"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"გამოტოვებული ზარები"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"ზარების დაბლოკვა"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"ამ ზარის განხორციელება თქვენს <xliff:g id="OTHER_APP">%1$s</xliff:g> ზარს დაასრულებს."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"ზარების დაბლოკვა"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"ნომრები არ არის კონტაქტებში"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"ნომრების დაბლოკვა, რომლებიც არ არის შეტანილი თქვენს კონტაქტებში"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"პირადი"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"ზარების დაბლოკვა, რომლებიც არ ამხელს ნომერს"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"საზოგადოებრივი ტელეფონი"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"ზარების დაბლოკვა საზოგადოებრივი ტელეფონებიდან"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"უცნობი"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"ზარების დაბლოკვა ამოუცნობი აბონენტებისგან"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"ზარების დაბლოკვა"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"ზარების დაბლოკვა გათიშულია"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"საგანგებო ზარი შესრულდა"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"ზარების დაბლოკვა გათიშულია, რათა საგანგებო სიტუაციებში მოპასუხეებმა თქვენთან დაკავშირება შეძლონ"</string>
 </resources>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index 2e9d572..aa98d40 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Қоңырау шалу мүмкін емес, себебі басқа қолданбадан қоңырау шалынуда."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Кіріс қоңыраулары"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Қабылданбаған қоңыраулар"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Қоңырауды бөгеу"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Жаңа қоңырау шалу <xliff:g id="OTHER_APP">%1$s</xliff:g> қоңырауын тоқтатады."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Қоңырауды бөгеу"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Контактілерде жоқ нөмірлер"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Контактілерде жоқ нөмірлерді бөгеу"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Жеке"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Нөмірі жасырын қоңырауларды бөгеу"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Ақылы телефон"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Ақылы телефон қоңырауларын бөгеу"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Белгісіз"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Белгісіз қоңырауларды бөгеу"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Қоңырауды бөгеу"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Қоңырау бөгеу функциясы өшірулі"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Төтенше жағдай қоңырауы шалынды"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Төтенше жағдай қызметтері сізге хабарласа алуы үшін, қоңырау бөгеу функциясы өшірілді."</string>
 </resources>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index 4fbf16c..e9f3cff 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -17,7 +17,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="382363169988504520">"គ្រប់គ្រងការហៅ"</string>
-    <string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"ទូរសព្ទ"</string>
+    <string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"ទូរស័ព្ទ"</string>
     <string name="unknown" msgid="6878797917991465859">"មិន​ស្គាល់"</string>
     <string name="notification_missedCallTitle" msgid="7554385905572364535">"ខកខាន​ទទួល"</string>
     <string name="notification_missedWorkCallTitle" msgid="6242489980390803090">"បានខកខានការហៅចូលពីកន្លែងការងារ"</string>
@@ -28,7 +28,7 @@
     <string name="notification_missedCall_message" msgid="3049928912736917988">"សារ"</string>
     <string name="accessibility_call_muted" msgid="2776111226185342220">"ការ​ហៅ​បិទ​សំឡេង។"</string>
     <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"បាន​បើក​អូប៉ាល័រ​ទូរស័ព្ទ។"</string>
-    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"មិន​អាច​និយាយ​បានទេ ​ឥឡូវ​នេះ។ មានការអីដែរ?"</string>
+    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"មិន​អាច​និយាយ​បាន​ឥឡូវ​នេះ។ មានការអីដែរ?"</string>
     <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"ខ្ញុំ​នឹង​ហៅ​​​​ទៅ​អ្នក​​វិញ។"</string>
     <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"ខ្ញុំ​នឹង​ហៅ​ទៅ​អ្នក​នៅ​ពេល​ក្រោយ។"</string>
     <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"មិន​អាច​និយាយ​បាន​ទេ​ឥឡូវ​នេះ។ ហៅ​​​​មក​ខ្ញុំ​ពេល​ក្រោយ?"</string>
@@ -49,21 +49,21 @@
     <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"កំណត់​លំនាំដើម"</string>
     <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"បោះបង់"</string>
     <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> នឹង​អាច​ដាក់ចុះ និង​ត្រួតពិនិត្យ​​ទិដ្ឋភាព​ការ​ហៅ​ទាំងអស់។ មាន​តែ​កម្មវិធី​ដែល​អ្នក​ទុកចិត្ត​ប៉ុណ្ណោះ​​អាច​​ត្រូវ​បាន​​កំណត់​ជា​កម្មវិធី​ទូរសព្ទ​លំនាំដើម។"</string>
-    <string name="blocked_numbers" msgid="2751843139572970579">"លេខដែល​បានទប់ស្កាត់"</string>
-    <string name="blocked_numbers_msg" msgid="1045015186124965643">"អ្នក​នឹង​មិន​ទទួល​បាន​ការ​ហៅទូរសព្ទ ឬ​សារ​​ពី​លេខ​ដែល​បានទប់ស្កាត់ឡើយ។"</string>
+    <string name="blocked_numbers" msgid="2751843139572970579">"លេខដែល​បានរារាំង"</string>
+    <string name="blocked_numbers_msg" msgid="1045015186124965643">"អ្នក​នឹង​មិន​ទទួល​បាន​ការ​ហៅទូរសព្ទ ឬ​សារ​​ពី​លេខ​ដែល​បាន​​រារាំង​ឡើយ។"</string>
     <string name="block_number" msgid="1101252256321306179">"បញ្ចូល​លេខ"</string>
-    <string name="unblock_dialog_body" msgid="1614238499771862793">"ឈប់ទប់ស្កាត់ <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g> ឬ?"</string>
-    <string name="unblock_button" msgid="3078048901972674170">"ឈប់ទប់ស្កាត់"</string>
-    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"ទប់ស្កាត់ការហៅ និងការផ្ញើសារពី"</string>
+    <string name="unblock_dialog_body" msgid="1614238499771862793">"ឈប់រារាំង <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g> ឬ?"</string>
+    <string name="unblock_button" msgid="3078048901972674170">"ឈប់រារាំង"</string>
+    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"រារាំងការហៅ និងការផ្ញើសារពី"</string>
     <string name="add_blocked_number_hint" msgid="6847675097085433553">"លេខទូរសព្ទ"</string>
-    <string name="block_button" msgid="8822290682524373357">"ទប់ស្កាត់"</string>
+    <string name="block_button" msgid="8822290682524373357">"រារាំង"</string>
     <string name="non_primary_user" msgid="5180129233352533459">"មានតែម្ចាស់ឧបករណ៍តែប៉ុណ្ណោះដែលអាចមើល និងគ្រប់គ្រងបញ្ជីរារាំងបាន"</string>
     <string name="delete_icon_description" msgid="8903995728252556724">"ឈប់​ទប់ស្កាត់"</string>
     <string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"បាន​បិទ​ការ​ទប់ស្កាត់​​​ជា​បណ្ដោះអាសន្ន"</string>
     <string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"បន្ទាប់​ពី​អ្នក​ចុច​ហៅ ឬ​ផ្ញើ​សារ​លេខ​​អាសន្ន ការ​ទប់ស្កាត់​​ត្រូវ​បាន​បិទ​​ដើម្បី​​ប្រាកដ​ថា​សេវាកម្ម​អាសន្ន​អាច​ទាក់ទង​អ្នក​បាន។"</string>
     <string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"បើក​ដំណើរការ​ឡើងវិញ​ឥឡូវនេះ"</string>
     <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"បាន​ទប់ស្កាត់ <xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g>"</string>
-    <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"បានឈប់​ទប់ស្កាត់ <xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g>"</string>
+    <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"បាន​អនុញ្ញាត <xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g>"</string>
     <string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"មិន​អាច​​​ទប់ស្កាត់​លេខ​បន្ទាន់​បាន​ទេ។"</string>
     <string name="blocked_numbers_number_already_blocked_message" msgid="4392247814500811798">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> ត្រូវ​បាន​ទប់ស្កាត់​រួច​ហើយ។"</string>
     <string name="toast_personal_call_msg" msgid="5115361633476779723">"កំពុងប្រើកម្មវិធីហៅផ្ទាល់ខ្លួនដើម្បីធ្វើការហៅទូរស័ព្ទ"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"ការ​ហៅ​មិន​អាច​ធ្វើ​បាន​ទេ ដោយ​សារ​មាន​ការហៅ​មួយ​នៅ​ក្នុង​កម្មវិធី​ផ្សេង។"</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"ការ​ហៅ​ចូល"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"ការ​ហៅ​ដែល​មិន​បាន​ទទួល"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"ការទប់ស្កាត់ការហៅ"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"ការ​ហៅ​ទូរសព្ទ​នេះ នឹង​បញ្ចប់​ការហៅ <xliff:g id="OTHER_APP">%1$s</xliff:g> របស់​អ្នក។"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"ការទប់ស្កាត់ការហៅ"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"លេខ​មិន​នៅ​ក្នុង​ទំនាក់ទំនង"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"ទប់ស្កាត់​លេខ​ដែល​មិនស្ថិត​​នៅ​ក្នុង​បញ្ជី​ទំនាក់ទំនង​របស់​អ្នក"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"ឯកជន"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"ទប់ស្កាត់​​អ្នកហៅទូរសព្ទ​​ដែល​មិន​ឲ្យ​ឃើញ​លេខ​របស់​ពួកគេ"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"ទូរសព្ទ​ដែល​បង់ប្រាក់"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"ទប់ស្កាត់​ការហៅ​ពី​ទូរសព្ទ​ដែល​បង់ប្រាក់"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"មិនស្គាល់"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"ទប់ស្កាត់​ការហៅ​ពី​អ្នក​ហៅ​ដែល​មិន​សម្គាល់​អត្តសញ្ញាណ"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"ការទប់ស្កាត់​ការហៅ"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"បាន​បិទ​ការទប់ស្កាត់​ការហៅ"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"បាន​ធ្វើការហៅ​បន្ទាន់"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"ការទប់ស្កាត់​ការហៅ​ត្រូវបាន​បិទ ដើម្បី​អនុញ្ញាត​ឲ្យ​អ្នក​ឆ្លើយតប​បន្ទាន់​អាច​ទាក់ទង​អ្នក​បាន។"</string>
 </resources>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 1680bd6..9dd0f09 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"ಬೇರೊಂದು ಅಪ್ಲಿಕೇಶನ್‍ನಲ್ಲಿ ಕರೆಯಲ್ಲಿರುವುದರಿಂದ ಕರೆ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"ಒಳಬರುವ ಕರೆಗಳು"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"ಮಿಸ್ಡ್‌ ಕರೆಗಳು"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"ಕರೆ ನಿರ್ಬಂಧಿಸುವಿಕೆ"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"ಈ ಕರೆಯನ್ನು ಮಾಡುವುದರಿಂದ ನಿಮ್ಮ <xliff:g id="OTHER_APP">%1$s</xliff:g> ಕರೆಯು ಅಂತ್ಯಗೊಳ್ಳುತ್ತದೆ."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"ಕರೆ ನಿರ್ಬಂಧಿಸುವಿಕೆ"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"ಸಂಖ್ಯೆಗಳು ಸಂಪರ್ಕದಲ್ಲಿಲ್ಲ"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"ನಿಮ್ಮ ಸಂಪರ್ಕಗಳಲ್ಲಿ ಪಟ್ಟಿ ಮಾಡಿರದ ಸಂಪರ್ಕಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿ"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"ಖಾಸಗಿ"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"ತಮ್ಮ ಸಂಖ್ಯೆಯನ್ನು ಬಹಿರಂಗಪಡಿಸದ ಕರೆ ಮಾಡುವವರನ್ನು ನಿರ್ಬಂಧಿಸಿ"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"ಪಾವತಿ ಫೋನ್"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"ಪಾವತಿ ಫೋನ್‌ಗಳಿಂದ ಕರೆಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿ"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"ಅಪರಿಚಿತ"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"ಗುರುತಿಸದ ಕರೆದಾರರಿಂದ ಕರೆಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿ"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"ಕರೆ ನಿರ್ಬಂಧಿಸುವಿಕೆ"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"ಕರೆ ನಿರ್ಬಂಧಿಸುವಿಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"ತುರ್ತು ಕರೆ ಮಾಡಲಾಗಿದೆ"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"ನಿಮ್ಮನ್ನು ಸಂಪರ್ಕಿಸುವುದಕ್ಕಾಗಿ ತುರ್ತಾಗಿ ಪ್ರತಿಕ್ರಿಯಿಸುವವರ ಸಂಖ್ಯೆಯನ್ನು ನಿರ್ಬಂಧಿಸುವುದನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ."</string>
 </resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 22fcde6..33e1c40 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -62,8 +62,8 @@
     <string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"차단 기능이 일시적으로 중지됨"</string>
     <string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"긴급 전화번호로 전화를 걸거나 문자를 보내면 긴급 서비스를 사용할 수 있도록 차단 기능이 중지됩니다."</string>
     <string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"지금 다시 사용 설정"</string>
-    <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g>번이 차단되었습니다."</string>
-    <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g>번이 차단 해제되었습니다."</string>
+    <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g>번은 차단되었습니다."</string>
+    <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g>번은 차단 해제되었습니다."</string>
     <string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"긴급 전화번호를 차단할 수 없습니다."</string>
     <string name="blocked_numbers_number_already_blocked_message" msgid="4392247814500811798">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g>번은 이미 차단되었습니다."</string>
     <string name="toast_personal_call_msg" msgid="5115361633476779723">"전화를 걸 때 개인 다이얼러 사용"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"다른 앱에서 통화 중이므로 전화를 걸 수 없습니다."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"수신 전화"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"부재중 전화"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"통화 차단"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"이 전화를 걸면 현재 <xliff:g id="OTHER_APP">%1$s</xliff:g>에서 진행 중인 통화가 종료됩니다."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"통화 차단"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"연락처에 없는 번호"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"연락처에 없는 번호 차단"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"익명"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"전화번호를 공개하지 않는 발신자 차단"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"공중전화"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"공중전화에서 걸려 온 통화 차단"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"알 수 없는 발신자"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"신원을 확인할 수 없는 발신자로부터 걸려 온 통화 차단"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"통화 차단"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"통화 차단이 사용 중지됨"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"긴급 통화가 사용됨"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"응급 구조 요원이 연락할 수 있도록 통화 차단이 사용 중지되었습니다."</string>
 </resources>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 760fdb1..b973486 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Башка колдонмодо чалып жатасыз, ошондуктан чала албайсыз."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Кирүүчү чалуулар"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Кабыл алынбаган чалуулар"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Чалууну бөгөттөө"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Эгер чалып баштасаңыз, <xliff:g id="OTHER_APP">%1$s</xliff:g> чалууңуз аяктайт."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Чалууну бөгөттөө"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Номерлер Байланыштар тизмесинде жок"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Байланыштар тизмеңизде болбогон номерлерди бөгөттөңүз"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Купуя"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Номерин көрсөтпөгөн чалуучуларды бөгөттөө"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Телефон-автомат"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Телефон-автоматтардан келген чалууларды бөгөттөө"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Белгисиз"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Белгисиз чалуучуларды бөгөттөө"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Чалууну бөгөттөө"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Чалууну бөгөттөө өчүрүлдү"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Шашылыш чалуу аткарылды"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Өзгөчө кырдаалдардагы кызматчылар сиз менен байланышуусу үчүн чалууну бөгөттөө функциясы өчүрүлгөн."</string>
 </resources>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 4c7ec9e..0b7a3b6 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"ບໍ່ສາມາດໂທອອກໄດ້ເນື່ອງຈາກສາຍໃນແອັບອື່ນ."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"ສາຍໂທເຂົ້າ"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"ສາຍບໍ່ໄດ້ຮັບ"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"ການບລັອກສາຍ"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"ການໂທສາຍນີ້ຈະເປັນການສິ້ນສຸດສາຍ <xliff:g id="OTHER_APP">%1$s</xliff:g> ຂອງທ່ານ."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"ການບລັອກສາຍ"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"ເບີໂທບໍ່ໄດ້ຢູ່ໃນລາຍຊື່ຜູ້ຕິດຕໍ່"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"ບລັອກເບີໂທທີ່ບໍ່ຢູ່ໃນລາຍຊື່ຜູ້ຕິດຕໍ່ຂອງທ່ານ"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"ສ່ວນຕົວ"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"ບລັອກຜູ້ໂທທີ່ບໍ່ສະແດງເບີໂທຂອງເຂົາເຈົ້າ"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"ຕູ້ໂທ"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"ບລັອກສາຍຈາກຕູ້ໂທ"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"ບໍ່ຮູ້ຈັກ"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"ບລັອກສາຍຈາກຜູ້ໂທທີ່ລະບຸຕົວຕົນບໍ່ໄດ້"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"ການບລັອກສາຍ"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"ປິດການບລັອກສາຍແລ້ວ"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"ໂທສຸກເສີນແລ້ວ"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"ປິດການບລັອກສາຍແລ້ວເພື່ອອະນຸຍາດໃຫ້ສາຍສຸກເສີນສາມາດຕິດຕໍ່ຫາທ່ານໄດ້."</string>
 </resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 4891114..45f125c 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Negalima skambinti dėl skambučio kitoje programoje."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Gaunamieji skambučiai"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Praleisti skambučiai"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Skambučių blokavimas"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Atliekant šį skambutį bus užbaigtas „<xliff:g id="OTHER_APP">%1$s</xliff:g>“ skambutis."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Skambučių blokavimas"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Numerių nėra Kontaktuose"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blokuoti Kontaktuose nepateiktus numerius"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privatus"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Blokuoti skambintojus, neatskleidžiančius savo numerių"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Taksofonas"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Blokuoti skambučius iš taksofonų"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Nežinomas"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Blokuoti skambučius nuo nenustatytų skambintojų"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Skambučių blokavimas"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Skambučių blokavimas išjungtas"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Atliktas skambutis pagalbos numeriu"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Skambučių blokavimas išjungtas, kad pagalbos numeriu atsiliepusiems žmonėms būtų leidžiama su jumis susisiekti."</string>
 </resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 8b8d36a..db710d5 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Nevar veikt zvanu citā lietotnē notiekoša zvana dēļ."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Ienākošie zvani"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Neatbildētie zvani"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Zvanu bloķēšana"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Veicot šo zvanu, tiks beigts zvans lietotnē <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Zvanu bloķēšana"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Numuri, kas nav ietverti kontaktpersonu sarakstā"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Bloķēt numurus, kas nav ietverti kontaktpersonu sarakstā"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privāts"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Bloķēt zvanītājus, kas neatklāj savu numuru"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Taksofons"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Bloķēt zvanus no taksofoniem"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Nezināms"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Bloķēt zvanus no neidentificētiem zvanītājiem"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Zvanu bloķēšana"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Zvanu bloķēšana atspējota"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Ārkārtas zvans ir veikts"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Zvanu bloķēšana ir atspējota, lai ļautu ar jums sazināties avārijas dienestu darbiniekiem."</string>
 </resources>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 6fcfa2a..a8debe9 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -52,7 +52,7 @@
     <string name="blocked_numbers" msgid="2751843139572970579">"Блокирани броеви"</string>
     <string name="blocked_numbers_msg" msgid="1045015186124965643">"Нема да добивате повици или SMS од блокирани броеви."</string>
     <string name="block_number" msgid="1101252256321306179">"Додај број"</string>
-    <string name="unblock_dialog_body" msgid="1614238499771862793">"Да се одблокира <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>?"</string>
+    <string name="unblock_dialog_body" msgid="1614238499771862793">"Одблокирајте го <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>?"</string>
     <string name="unblock_button" msgid="3078048901972674170">"Одблокирај"</string>
     <string name="add_blocked_dialog_body" msgid="9030243212265516828">"Блокирај повици и пораки од"</string>
     <string name="add_blocked_number_hint" msgid="6847675097085433553">"Телефонски број"</string>
@@ -63,7 +63,7 @@
     <string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"Откако ќе повикате или ќе испратите SMS на број за итни случаи, блокирањето се исклучува за да може да ве контактираат службите за итни случаи."</string>
     <string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"Овозможи сега повторно"</string>
     <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> е блокиран"</string>
-    <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> е одблокиран"</string>
+    <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> е деблокиран"</string>
     <string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"Бројот за итни случаи не може да се блокира."</string>
     <string name="blocked_numbers_number_already_blocked_message" msgid="4392247814500811798">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> е веќе блокиран."</string>
     <string name="toast_personal_call_msg" msgid="5115361633476779723">"Користење на личниот бирач за остварување повик"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Не може да се воспостави повик поради вашиот повик на друга апликација."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Дојдовни повици"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Пропуштени повици"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Блокирање повици"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Ако се воспостави повиков, вашиот повик на <xliff:g id="OTHER_APP">%1$s</xliff:g> ќе заврши."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Блокирање повици"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Броеви што не се наведени во „Контакти“"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Блокирани броеви што не се наведени во вашите „Контакти“"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Приватно"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Блокирај повикувачи со сокриен број"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Телефонска говорница"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Блокирај повици од телефонски говорници"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Непознато"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Блокирај повици од неидентификувани повикувачи"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Блокирање повици"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Блокирањето повици е оневозможено"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Воспоставен е итен повик"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Блокирањето повици е оневозможено за да им се овозможи на лицата од службите за итни случаи да контактираат со вас."</string>
 </resources>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 0ce1758..d604690 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"മറ്റൊരു ആപ്പിലുള്ള കോൾ കാരണം കോൾ ചെയ്യാനായില്ല."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"ഇൻകമിംഗ് കോളുകൾ"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"മിസ്‌ഡ് കോളുകൾ"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"കോൾ ബ്ലോക്ക് ചെയ്യൽ"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"ഈ കോൾ ചെയ്യുന്നത് നിങ്ങളുടെ <xliff:g id="OTHER_APP">%1$s</xliff:g> കോൾ അവസാനിക്കാനിടയാക്കും."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"കോൾ ബ്ലോക്ക് ചെയ്യൽ"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"കോൺടാക്‌റ്റുകളിൽ ഇല്ലാത്ത നമ്പറുകൾ"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"നിങ്ങളുടെ കോൺടാക്റ്റുകളിൽ ലിസ്‌റ്റ് ചെയ്യാത്ത നമ്പറുകൾ ബ്ലോക്ക് ചെയ്യുക"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"സ്വകാര്യം"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"വിളിക്കുന്നവരിൽ നമ്പർ വെളിപ്പെടുത്താത്തവരെ ബ്ലോക്ക് ചെയ്യുക"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"പേ ഫോൺ"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"പേ ഫോണുകളിൽ നിന്നുള്ള കോളുകൾ ബ്ലോക്ക് ചെയ്യുക"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"അജ്ഞാതം"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"തിരിച്ചറിയാത്ത കോളർമാരിൽ നിന്നുള്ള കോളുകൾ ബ്ലോക്ക് ചെയ്യുക"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"കോൾ ബ്ലോക്ക് ചെയ്യൽ"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"കോൾ ബ്ലോക്ക് ചെയ്യൽ പ്രവർത്തനരഹിതമാക്കി"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"അടിയന്തര കോൾ ചെയ്തു"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"അടിയന്തരമായി ബന്ധപ്പെടുന്നവരെ അനുവദിക്കാനായി കോൾ ബ്ലോക്ക് ചെയ്യൽ പ്രവർത്തനരഹിതമാക്കി."</string>
 </resources>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index 696e954..82b4ebd 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Өөр апп доторх дуудлагаас шалтгаалан дуудлага хийх боломжгүй байна."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Ирж буй дуудлага"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Аваагүй дуудлага"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Дуудлага хориглох"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Энэ дуудлагыг хийснээр таны <xliff:g id="OTHER_APP">%1$s</xliff:g> дуудлагыг дуусгана."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Дуудлага хориглох"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Харилцагчид дотор байхгүй дугаарууд"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Өөрийн Харилцагчид дотор байхгүй дугааруудыг хориглох"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Хувийн"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Дугаараа нууцалсан дуудлагыг хориглох"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Төлбөртэй утас"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Төлбөртэй утаснаас залгасан дуудлагуудыг хориглох"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Тодорхойгүй"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Тодорхойгүй дугаараас ирсэн дуудлагуудыг хориглох"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Дуудлага хориглох"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Дуудлага хориглохыг идэвхгүй болгосон"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Яаралтай тусламжийн дуудлага хийсэн"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Яаралтай тусламжийнханд тантай холбогдохыг зөвшөөрөхийн тулд дуудлага хориглохыг идэвхгүй болгосон."</string>
 </resources>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 865bd53..9f2991a 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -25,7 +25,7 @@
     <string name="notification_missedCallsMsg" msgid="4575787816055205600">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> सुटलेले कॉल"</string>
     <string name="notification_missedCallTicker" msgid="504686252427747209">"<xliff:g id="MISSED_CALL_FROM">%s</xliff:g> कडील सुटलेला कॉल"</string>
     <string name="notification_missedCall_call_back" msgid="2684890353590890187">"पुन्हा कॉल करा"</string>
-    <string name="notification_missedCall_message" msgid="3049928912736917988">"मेसेज"</string>
+    <string name="notification_missedCall_message" msgid="3049928912736917988">"संदेश"</string>
     <string name="accessibility_call_muted" msgid="2776111226185342220">"कॉल नि.शब्‍द केला."</string>
     <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"स्‍पीकरफोन सक्षम केला."</string>
     <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"आत्ता बोलू शकत नाही. काय चालले आहे?"</string>
@@ -36,31 +36,31 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"द्रुत प्रतिसाद संपादित करा"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"द्रुत प्रतिसाद"</string>
-    <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"मेसेज <xliff:g id="PHONE_NUMBER">%s</xliff:g> वर पाठविला."</string>
+    <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"संदेश <xliff:g id="PHONE_NUMBER">%s</xliff:g> वर पाठविला."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"कॉल करण्याची खाती"</string>
     <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"फक्त आणीबाणी कॉल करण्याची परवानगी आहे."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"हा अॅप्लिकेशन फोन परवानगी शिवाय कॉल करू शकत नाही."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"कॉल करण्यासाठी, एक वैध नंबर एंटर करा."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"यावेळी कॉल जोडला जाऊ शकत नाही."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"व्हॉइसमेल नंबर गहाळ"</string>
-    <string name="no_vm_number_msg" msgid="1300729501030053828">"सिम कार्डवर कोणताही व्हॉइसमेल नंबर स्टोअर केला नाही."</string>
+    <string name="no_vm_number_msg" msgid="1300729501030053828">"सिम कार्डवर कोणताही व्हॉइसमेल नंबर संचयित केला नाही."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"नंबर जोडा"</string>
-    <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> ला तुमचा डीफॉल्ट अ‍ॅप बनवायचा?"</string>
+    <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> ला आपला डीफॉल्ट अॅप बनवायचा?"</string>
     <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"डीफॉल्ट म्हणून सेट करा"</string>
     <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"रद्द करा"</string>
-    <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> कॉल करण्यात आणि त्याचे सर्व पैलू नियंत्रित करण्‍यात सक्षम असेल. ज्या अ‍ॅप्सवर तुमचा विश्वास आहे फक्त त्यांंनाच तुमचा डीफॉल्ट फोन अ‍ॅप म्हणून सेट करावे."</string>
-    <string name="blocked_numbers" msgid="2751843139572970579">"ब्लॉक केलेले नंबर"</string>
-    <string name="blocked_numbers_msg" msgid="1045015186124965643">"तुम्हाला ब्लॉक केलेल्या नंबरवरून कॉल किंवा मजकूर येणार नाहीत."</string>
+    <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> कॉल करण्यात आणि त्याचे सर्व पैलू नियंत्रित करण्‍यात सक्षम असेल. ज्या अॅप्सवर आपला विश्वास आहे फक्त त्यांंनाच आपला डीफॉल्ट फोन अॅप म्हणून सेट करावे."</string>
+    <string name="blocked_numbers" msgid="2751843139572970579">"अवरोधित केलेले नंबर"</string>
+    <string name="blocked_numbers_msg" msgid="1045015186124965643">"आपल्याला अवरोधित नंबरवरून कॉल किंवा मजकूर प्राप्त होणार नाहीत."</string>
     <string name="block_number" msgid="1101252256321306179">"एक नंबर जोडा"</string>
-    <string name="unblock_dialog_body" msgid="1614238499771862793">"<xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g> अनब्लॉक करायचा?"</string>
-    <string name="unblock_button" msgid="3078048901972674170">"ब्लॉक करा"</string>
-    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"यावरील कॉल आणि मजकूर ब्लॉक करा"</string>
+    <string name="unblock_dialog_body" msgid="1614238499771862793">"<xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g> अनावरोधित करायचा?"</string>
+    <string name="unblock_button" msgid="3078048901972674170">"अनावरोधित करा"</string>
+    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"यावरील कॉल आणि मजकूर अवरोधित करा"</string>
     <string name="add_blocked_number_hint" msgid="6847675097085433553">"फोन नंबर"</string>
     <string name="block_button" msgid="8822290682524373357">"अवरोधित करा"</string>
     <string name="non_primary_user" msgid="5180129233352533459">"फक्त डिव्हाइस मालक अवरोधित केलेले नंबर पाहू आणि व्यवस्थापित करू शकतो."</string>
-    <string name="delete_icon_description" msgid="8903995728252556724">"ब्लॉक करा"</string>
+    <string name="delete_icon_description" msgid="8903995728252556724">"अनावरोधित करा"</string>
     <string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"अवरोधित करणे तात्पुरते बंद आहे"</string>
-    <string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"तुम्ही एखादा आणीबाणी नंबर डायल केला किंवा त्यावर मजकूर पाठविल्यानंतर, आणीबाणी सेवा आपल्याशी संपर्क साधू शकतात हे सुनिश्चित करण्यासाठी अवरोधित करणे बंद करते."</string>
+    <string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"आपण एखादा आणीबाणी नंबर डायल केला किंवा त्यावर मजकूर पाठविल्यानंतर, आणीबाणी सेवा आपल्याशी संपर्क साधू शकतात हे सुनिश्चित करण्यासाठी अवरोधित करणे बंद करते."</string>
     <string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"आता पुन्हा-सक्षम करा"</string>
     <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> अवरोधित केला"</string>
     <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> अनावरोधित केला"</string>
@@ -69,12 +69,12 @@
     <string name="toast_personal_call_msg" msgid="5115361633476779723">"कॉल करण्यासाठी वैयक्तिक डायलर वापरणे"</string>
     <string name="notification_incoming_call" msgid="7713197997773986670">"<xliff:g id="CALL_FROM">%2$s</xliff:g> कडील <xliff:g id="CALL_VIA">%1$s</xliff:g> मधील कॉल"</string>
     <string name="notification_incoming_video_call" msgid="6638486071698373893">"<xliff:g id="CALL_FROM">%2$s</xliff:g> कडील <xliff:g id="CALL_VIA">%1$s</xliff:g> मधील व्हिडिओ कॉल"</string>
-    <string name="answering_ends_other_call" msgid="8282145910153766401">"उत्तर देण्यामुळे तुमचा <xliff:g id="CALL_VIA">%1$s</xliff:g> कॉल समाप्त होईल"</string>
-    <string name="answering_ends_other_calls" msgid="1198589551399049197">"उत्तर देण्यामुळे तुमचे <xliff:g id="CALL_VIA">%1$s</xliff:g> कॉल समाप्त होतील"</string>
-    <string name="answering_ends_other_video_call" msgid="8510410917384186360">"उत्तर देण्यामुळे तुमचा <xliff:g id="CALL_VIA">%1$s</xliff:g> व्हिडिओ कॉल समाप्त होईल"</string>
-    <string name="answering_ends_other_managed_call" msgid="5186137550267947785">"उत्तर देण्यामुळे तुमचा सुरु असलेला कॉल समाप्त होईल"</string>
-    <string name="answering_ends_other_managed_calls" msgid="6429838309560397988">"उत्तर देण्यामुळे तुमचे सुरु असलेले कॉल समाप्त होतील"</string>
-    <string name="answering_ends_other_managed_video_call" msgid="1585423762458248435">"उत्तर देण्यामुळे तुमचा सुरु असलेला व्हिडिओ कॉल समाप्त होईल"</string>
+    <string name="answering_ends_other_call" msgid="8282145910153766401">"उत्तर देण्यामुळे आपला <xliff:g id="CALL_VIA">%1$s</xliff:g> कॉल समाप्त होईल"</string>
+    <string name="answering_ends_other_calls" msgid="1198589551399049197">"उत्तर देण्यामुळे आपले <xliff:g id="CALL_VIA">%1$s</xliff:g> कॉल समाप्त होतील"</string>
+    <string name="answering_ends_other_video_call" msgid="8510410917384186360">"उत्तर देण्यामुळे आपला <xliff:g id="CALL_VIA">%1$s</xliff:g> व्हिडिओ कॉल समाप्त होईल"</string>
+    <string name="answering_ends_other_managed_call" msgid="5186137550267947785">"उत्तर देण्यामुळे आपला सुरु असलेला कॉल समाप्त होईल"</string>
+    <string name="answering_ends_other_managed_calls" msgid="6429838309560397988">"उत्तर देण्यामुळे आपले सुरु असलेले कॉल समाप्त होतील"</string>
+    <string name="answering_ends_other_managed_video_call" msgid="1585423762458248435">"उत्तर देण्यामुळे आपला सुरु असलेला व्हिडिओ कॉल समाप्त होईल"</string>
     <string name="answer_incoming_call" msgid="4140530013111794587">"उत्तर द्या"</string>
     <string name="decline_incoming_call" msgid="806026168661598368">"नकार द्या"</string>
     <string name="cant_call_due_to_ongoing_call" msgid="4952615196237854748">"आपल्या <xliff:g id="OTHER_CALL">%1$s</xliff:g> कॉलमुळे कॉल केला जाऊ शकत नाही."</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"दुसर्‍या अॅपमधील कॉलमुळे कॉल केला जाऊ शकत नाही."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"येणारे कॉल"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"सुटलेले कॉल"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"कॉल ब्‍लॉक करणे"</string>
-    <string name="alert_outgoing_call" msgid="982908156825958001">"हा कॉल केल्याने तुमचा <xliff:g id="OTHER_APP">%1$s</xliff:g> कॉल समाप्त होईल."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"कॉल ब्‍लॉक करणे"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"संपर्कांमध्‍ये क्रमांक नाहीत"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"तुमच्‍या संपर्कांच्‍या सूचीमध्‍ये नसलेले क्रमांक ब्‍लॉक करा"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"खाजगी"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"अशा कॉलरना ब्‍लॉक करा, जे त्‍यांचे क्रमांक उघड करत नाहीत"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"पे फोन"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"पे फोनवरून येणारे कॉल ब्‍लॉक करा"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"अज्ञात"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"अनोळखी कॉलरकडून येणारे कॉल ब्‍लॉक करा"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"कॉल ब्‍लॉक करणे"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"कॉल ब्‍लॉक करणे बंद केले"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"आणीबाणी कॉल केला"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"आणीबाणीत प्रतिसाद देणार्‍यांना तुमच्‍याशी संपर्क साधण्‍याची अनुमती देण्‍यासाठी कॉल ब्‍लॉक करणे बंद केले आहे."</string>
+    <string name="alert_outgoing_call" msgid="982908156825958001">"हा कॉल केल्याने आपला <xliff:g id="OTHER_APP">%1$s</xliff:g> कॉल समाप्त होईल."</string>
 </resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index ce0e2d1..8c59a02 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -29,7 +29,7 @@
     <string name="accessibility_call_muted" msgid="2776111226185342220">"Panggilan diredam."</string>
     <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"Telefon pembesar suara didayakan."</string>
     <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"Sedang sibuk. Ada apa?"</string>
-    <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"Saya akan hubungi awak semula."</string>
+    <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"Saya akn segera hubungi awak nanti."</string>
     <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"Saya akan hubungi awak kemudian."</string>
     <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"Sedang sibuk. Telefon saya nanti?"</string>
     <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"Respons pantas"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Panggilan tidak dapat dibuat disebabkan panggilan dalam apl lain."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Panggilan masuk"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Panggilan tidak dijawab"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Sekatan Panggilan"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Membuat panggilan ini akan menamatkan panggilan <xliff:g id="OTHER_APP">%1$s</xliff:g> anda."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Sekatan Panggilan"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Nombor bukan dalam Kenalan"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Sekat nombor yang tidak disenaraikan dalam Kenalan anda"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Persendirian"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Sekat pemanggil yang tidak mendedahkan nombor mereka"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Telefon awam"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Sekat panggilan daripada telefon awam"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Tidak diketahui"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Sekat panggilan daripada pemanggil yang tidak dikenal pasti"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Sekatan Panggilan"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Sekatan Panggilan dilumpuhkan"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Panggilan kecemasan dibuat"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Sekatan Panggilan telah dilumpuhkan untuk membolehkan pasukan bantuan kecemasan menghubungi anda."</string>
 </resources>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 597924b..165dd0e 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -18,7 +18,7 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="telecommAppLabel" product="default" msgid="382363169988504520">"ခေါ်ဆိုမှုစီမံခန့်ခွဲရေး"</string>
     <string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"ဖုန်း"</string>
-    <string name="unknown" msgid="6878797917991465859">"မသိပါ"</string>
+    <string name="unknown" msgid="6878797917991465859">"အကြောင်းအရာ မသိရှိ"</string>
     <string name="notification_missedCallTitle" msgid="7554385905572364535">"လွဲသွားသော ဖုန်းခေါ်မှု"</string>
     <string name="notification_missedWorkCallTitle" msgid="6242489980390803090">"လွတ်သွားသည့် အလုပ်ဆိုင်ရာ ခ​ေါ်ဆိုမှု"</string>
     <string name="notification_missedCallsTitle" msgid="1361677948941502522">"လွဲသွားသော ဖုန်းခေါ်မှုများ"</string>
@@ -29,8 +29,8 @@
     <string name="accessibility_call_muted" msgid="2776111226185342220">"နားထောင်ရုံသာ (စကားပြောပိတ်ထားသည်)"</string>
     <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"စပီကာဖုန်း သုံးလို့ရသည်"</string>
     <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"အခုပြောလို့မရဘူး။ အကြောင်းထူးရှိလား။"</string>
-    <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"အခုပဲ ပြန်ခေါ်လိုက်မယ်။"</string>
-    <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"နောက်မှ ပြန်ခေါ်လိုက်မယ်။"</string>
+    <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"ပြန်ခေါ်လိုက်မယ်နော်"</string>
+    <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"နောက်မှ ပြန်ခေါ်လိုက်မယ်"</string>
     <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"အခုပြောလို့မရဘူး။ ပြန်ခေါ်ပါလား။"</string>
     <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"အမြန်တုံ့ပြန်ချက်များ"</string>
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"အမြန်တုံ့ပြန်ချက်များပြင်ခြင်း"</string>
@@ -42,8 +42,8 @@
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"ဤအပ္ပလီကေးရှင်းသည် ဖုန်းခွင့်ပြုချက်မရှိဘဲ အထွက်ခေါ်ဆိုမှု ပြုလုပ်၍မရပါ။"</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"ဖုန်းခေါ်ရန်အတွက်၊ သင့်လျော်သည့်နံပါတ် ရိုက်ထည့်ပါ။"</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"ဗွီဒီယိုခေါ်နေစဉ် ထပ်ခေါ်မရပါ။"</string>
-    <string name="no_vm_number" msgid="4164780423805688336">"အသံမေးလ် နံပါတ် ပျောက်နေပါသည်"</string>
-    <string name="no_vm_number_msg" msgid="1300729501030053828">"ဆင်းမ်ကဒ်ပေါ်တွင် အသံမေးလ် နံပါတ် သိမ်းဆည်ထားခြင်း မရှိပါ"</string>
+    <string name="no_vm_number" msgid="4164780423805688336">"အသံစာပို့စနစ် နံပါတ် ပျောက်နေပါသည်"</string>
+    <string name="no_vm_number_msg" msgid="1300729501030053828">"ဆင်းမ်ကဒ်ပေါ်တွင် အသံစာပို့စနစ် နံပါတ် သိမ်းဆည်ထားခြင်း မရှိပါ"</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"နံပါတ်ထပ်ထည့်ရန်"</string>
     <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g> ကို သင့်ဖုန်း၏မူရင်းအက်ပ်အဖြစ် ထားမလား။"</string>
     <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"မူရင်း သတ်မှတ်ရန်"</string>
@@ -54,7 +54,7 @@
     <string name="block_number" msgid="1101252256321306179">"နံပါတ်တစ်ခု ထည့်ပါ"</string>
     <string name="unblock_dialog_body" msgid="1614238499771862793">"<xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g> ကို ပိတ်ဆို့မှုပြန်ဖွင့်မလား။"</string>
     <string name="unblock_button" msgid="3078048901972674170">"ပိတ်ဆို့မှုပြန်ဖွင့်ပါ"</string>
-    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"ဤနံပါတ်မှ ခေါ်ဆိုမှုနှင့် စာများကို ပိတ်ဆို့ပါ"</string>
+    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"ဖော်ပြပါပုဂ္ဂိုလ်ထံမှ စာနှင့် ခေါ်ဆိုမှုများကို ပိတ်ဆို့ပါ"</string>
     <string name="add_blocked_number_hint" msgid="6847675097085433553">"ဖုန်းနံပါတ်"</string>
     <string name="block_button" msgid="8822290682524373357">"ပိတ်ဆို့ပါ"</string>
     <string name="non_primary_user" msgid="5180129233352533459">"ပိတ်ဆို့ထားသည့် နံပါတ်များကို စက်ပစ္စည်းပိုင်ရှင်သာလျှင် ကြည့်ရှု၍ စီမံခန့်ခွဲနိုင်ပါသည်။"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"အခြားအက်ပ်သုံးပြီးပြောနေသည့်အတွက် အထွက်ခေါ်ဆိုမှုကို မပြုလုပ်နိုင်ပါ။"</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"အဝင်ဖုန်းခေါ်ဆိုမှုများ"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"လွတ်သွားသော ဖုန်းခေါ်ဆိုမှုများ"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"ခေါ်ဆိုမှု ပိတ်ခြင်း"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"ဤခေါ်ဆိုမှု ပြုလုပ်ပါက <xliff:g id="OTHER_APP">%1$s</xliff:g> သုံးပြီးပြောနေခြင်းကို ဖြတ်ပစ်ပါမည်။"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"ခေါ်ဆိုမှု ပိတ်ခြင်း"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"\'အဆက်အသွယ်များ\' ထဲတွင် မရှိသော နံပါတ်များ"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"သင်၏ \'အဆက်အသွယ်များ\' ထဲတွင် မပါဝင်သော နံပါတ်များကို ပိတ်ပါ"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"သီးသန့်"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"နံပါတ်မပြသသော ခေါ်ဆိုမှုများကို ပိတ်ပါ"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"အများသုံးဖုန်း"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"အများသုံးဖုန်းများမှ ခေါ်ဆိုမှုများကို ပိတ်ပါ"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"အမည်မသိ"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"အမည်မသိသော ခေါ်ဆိုသူများကို ပိတ်ပါ"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"ခေါ်ဆိုမှု ပိတ်ခြင်း"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"\'ခေါ်ဆိုမှု ပိတ်ခြင်း\' ကို ရပ်ထားပါသည်"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"အရေးပေါ် ခေါ်ဆိုမှု ပြုလုပ်ထားပါသည်"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"အရေးပေါ်တုံ့ပြန်သူများက သင့်အား ဆက်သွယ်နိုင်စေရန် \'ခေါ်ဆိုမှု ပိတ်ခြင်း\' ကို ရပ်ထားပါသည်။"</string>
 </resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 6e63c1e..cd5b1cd 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Kan ikke ringe ut på grunn av en samtale i en annen app."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Innkommende anrop"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Tapte anrop"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Anropsblokkering"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Samtalen din i <xliff:g id="OTHER_APP">%1$s</xliff:g> avsluttes hvis du foretar dette anropet."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Anropsblokkering"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Numre som ikke står i Kontakter"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blokkér numre som ikke står i kontaktene mine"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privat"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Blokkér oppringere som ikke viser telefonnummeret sitt"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Telefonkiosk"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Blokkér anrop fra telefonkiosker"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Ukjent"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Blokkér anrop fra oppringere som ikke er identifisert"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Anropsblokkering"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Anropsblokkering er slått av"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Nødanrop utført"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Anropsblokkering er slått av for å gjøre det mulig for nødtjenester å kontakte deg."</string>
 </resources>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 155ae7e..7f15ebe 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -40,7 +40,7 @@
     <string name="enable_account_preference_title" msgid="2021848090086481720">"कलिङ खाताहरू"</string>
     <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"आपतकालीन कलहरूलाई मात्र अनुमति दिइएको छ।"</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"यो अनुप्रयोगले फोनको अनुमति बिना बहिर्गमन कलहरू गर्न सक्दैन।"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"एक कल गर्नको लागि, एक वैध नम्बर प्रविष्टि गर्नुहोस्।"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"एक कल गर्नको लागि, एक वैध नम्बर प्रविष्ट गर्नुहोस्।"</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"यस समयमा कल थप गर्न सकिँदैन।"</string>
     <string name="no_vm_number" msgid="4164780423805688336">"भ्वाइसमेल नम्बर हराइरहेको छ"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"SIM कार्डमा कुनै पनि भ्वाइसमेल नम्बर भण्डारण भएको छैन।"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"अर्को अनुप्रयोगमा जारी कलका कारण कल गर्न सकिँदैन।"</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"आगमन कलहरू"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"छुटेका कलहरू"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"कलमाथि रोक लगाउने सुविधा"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"यो कल गर्नुले तपाईंको <xliff:g id="OTHER_APP">%1$s</xliff:g> कल अन्त्य गर्दछ।"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"कलमाथि रोक लगाउने सुविधा"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"सम्पर्क सूचीहरूमा नरहेका नम्बरहरू"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"आफ्नो सम्पर्क सूचीहरूमा सूचीबद्ध नगरिएका नम्बरहरूमाथि रोक लगाउनुहोस्"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"निजी"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"आफ्नो नम्बरको खुलासा नगरी कल गर्ने व्यक्तिहरूमाथि रोक लगाउनुहोस्"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"पे फोन"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"पे फोनहरूबाट आउने कलहरूमाथि रोक लगाउनुहोस्"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"अज्ञात"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"अज्ञात कल गर्ने व्यक्तिहरूको कलमाथि रोक लगाउनुहोस्"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"कलमाथि रोक लगाउने सुविधा"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"कलमाथि रोक लगाउने सुविधालाई असक्षम पारियो"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"आपतकालीन कल गरियो"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"आपतकालीन अवस्थामा उद्दार गर्ने मान्छेहरूलाई तपाईंलाई सम्पर्क गर्न दिन कलमाथि रोक लगाउने सुविधा असक्षम पारिएको छ।"</string>
 </resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index a85d66e..324b5fb 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -19,15 +19,15 @@
     <string name="telecommAppLabel" product="default" msgid="382363169988504520">"Oproepbeheer"</string>
     <string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"Telefoon"</string>
     <string name="unknown" msgid="6878797917991465859">"Onbekend"</string>
-    <string name="notification_missedCallTitle" msgid="7554385905572364535">"Gemist gesprek"</string>
-    <string name="notification_missedWorkCallTitle" msgid="6242489980390803090">"Gemist zakelijk gesprek"</string>
-    <string name="notification_missedCallsTitle" msgid="1361677948941502522">"Gemiste gesprekken"</string>
-    <string name="notification_missedCallsMsg" msgid="4575787816055205600">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> gemiste gesprekken"</string>
-    <string name="notification_missedCallTicker" msgid="504686252427747209">"Gemist gesprek van <xliff:g id="MISSED_CALL_FROM">%s</xliff:g>"</string>
+    <string name="notification_missedCallTitle" msgid="7554385905572364535">"Gemiste oproep"</string>
+    <string name="notification_missedWorkCallTitle" msgid="6242489980390803090">"Gemiste zakelijke oproep"</string>
+    <string name="notification_missedCallsTitle" msgid="1361677948941502522">"Gemiste oproepen"</string>
+    <string name="notification_missedCallsMsg" msgid="4575787816055205600">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> gemiste oproepen"</string>
+    <string name="notification_missedCallTicker" msgid="504686252427747209">"Gemiste oproep van <xliff:g id="MISSED_CALL_FROM">%s</xliff:g>"</string>
     <string name="notification_missedCall_call_back" msgid="2684890353590890187">"Terugbellen"</string>
     <string name="notification_missedCall_message" msgid="3049928912736917988">"Bericht"</string>
-    <string name="accessibility_call_muted" msgid="2776111226185342220">"Gesprek gedempt."</string>
-    <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"Luidspreker is aan."</string>
+    <string name="accessibility_call_muted" msgid="2776111226185342220">"Oproep gedempt."</string>
+    <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"Telefoonluidspreker is ingeschakeld."</string>
     <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"Kan nu niet opnemen. Alles goed?"</string>
     <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"Ik bel je zo terug."</string>
     <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"Ik bel je later."</string>
@@ -37,24 +37,24 @@
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Snelle reactie"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Bericht verzonden naar <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="enable_account_preference_title" msgid="2021848090086481720">"Gespreksaccounts"</string>
+    <string name="enable_account_preference_title" msgid="2021848090086481720">"Oproepaccounts"</string>
     <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Alleen noodoproepen zijn toegestaan."</string>
-    <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Deze app kan geen uitgaande gesprekken starten zonder telefoonrechten."</string>
+    <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Deze app kan geen uitgaande oproepen starten zonder telefoonrechten."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Als je wilt bellen, moet je een geldig nummer invoeren."</string>
-    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Gesprek kan momenteel niet worden toegevoegd."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Oproep kan momenteel niet worden toegevoegd."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Voicemailnummer ontbreekt"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Er is geen voicemailnummer op de simkaart opgeslagen."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Nummer toevoegen"</string>
     <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Wil je <xliff:g id="NEW_APP">%s</xliff:g> instellen als je standaard telefoon-app?"</string>
     <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Standaard instellen"</string>
     <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Annuleren"</string>
-    <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> kan gesprekken plaatsen en alle aspecten hiervan beheren. Stel alleen apps in als je standaard telefoon-app als je ze vertrouwt."</string>
+    <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> kan oproepen plaatsen en alle aspecten hiervan beheren. Stel alleen apps in als je standaard telefoon-app als je ze vertrouwt."</string>
     <string name="blocked_numbers" msgid="2751843139572970579">"Geblokkeerde nummers"</string>
-    <string name="blocked_numbers_msg" msgid="1045015186124965643">"Je ontvangt geen gesprekken of sms\'jes van geblokkeerde nummers."</string>
+    <string name="blocked_numbers_msg" msgid="1045015186124965643">"Je ontvangt geen oproepen of sms\'jes van geblokkeerde nummers."</string>
     <string name="block_number" msgid="1101252256321306179">"Een nummer toevoegen"</string>
     <string name="unblock_dialog_body" msgid="1614238499771862793">"Blokkering van <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g> opheffen?"</string>
     <string name="unblock_button" msgid="3078048901972674170">"Blokkering opheffen"</string>
-    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"Gesprekken en sms\'jes blokkeren van"</string>
+    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"Oproepen en sms\'jes blokkeren van"</string>
     <string name="add_blocked_number_hint" msgid="6847675097085433553">"Telefoonnummer"</string>
     <string name="block_button" msgid="8822290682524373357">"Blokkeren"</string>
     <string name="non_primary_user" msgid="5180129233352533459">"Alleen de eigenaar van het apparaat kan geblokkeerd nummers bekijken en beheren."</string>
@@ -67,34 +67,20 @@
     <string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"Kan alarmnummer niet blokkeren."</string>
     <string name="blocked_numbers_number_already_blocked_message" msgid="4392247814500811798">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> is al geblokkeerd."</string>
     <string name="toast_personal_call_msg" msgid="5115361633476779723">"De persoonlijke kiezer gebruiken om te bellen"</string>
-    <string name="notification_incoming_call" msgid="7713197997773986670">"<xliff:g id="CALL_VIA">%1$s</xliff:g>-gesprek van <xliff:g id="CALL_FROM">%2$s</xliff:g>"</string>
+    <string name="notification_incoming_call" msgid="7713197997773986670">"<xliff:g id="CALL_VIA">%1$s</xliff:g>-oproep van <xliff:g id="CALL_FROM">%2$s</xliff:g>"</string>
     <string name="notification_incoming_video_call" msgid="6638486071698373893">"<xliff:g id="CALL_VIA">%1$s</xliff:g>-videogesprek van <xliff:g id="CALL_FROM">%2$s</xliff:g>"</string>
-    <string name="answering_ends_other_call" msgid="8282145910153766401">"Als je opneemt, wordt je <xliff:g id="CALL_VIA">%1$s</xliff:g>-gesprek beëindigd"</string>
-    <string name="answering_ends_other_calls" msgid="1198589551399049197">"Als je opneemt, worden je <xliff:g id="CALL_VIA">%1$s</xliff:g>-gesprekken beëindigd"</string>
+    <string name="answering_ends_other_call" msgid="8282145910153766401">"Als je opneemt, wordt je <xliff:g id="CALL_VIA">%1$s</xliff:g>-oproep beëindigd"</string>
+    <string name="answering_ends_other_calls" msgid="1198589551399049197">"Als je opneemt, worden je <xliff:g id="CALL_VIA">%1$s</xliff:g>-oproepen beëindigd"</string>
     <string name="answering_ends_other_video_call" msgid="8510410917384186360">"Als je opneemt, wordt je <xliff:g id="CALL_VIA">%1$s</xliff:g>-videogesprek beëindigd"</string>
-    <string name="answering_ends_other_managed_call" msgid="5186137550267947785">"Als je opneemt, wordt je actief gesprek beëindigd"</string>
-    <string name="answering_ends_other_managed_calls" msgid="6429838309560397988">"Als je opneemt, worden je actieve gesprekken beëindigd"</string>
+    <string name="answering_ends_other_managed_call" msgid="5186137550267947785">"Als je opneemt, wordt je actieve oproep beëindigd"</string>
+    <string name="answering_ends_other_managed_calls" msgid="6429838309560397988">"Als je opneemt, worden je actieve oproepen beëindigd"</string>
     <string name="answering_ends_other_managed_video_call" msgid="1585423762458248435">"Als je opneemt, wordt je actieve videogesprek beëindigd"</string>
     <string name="answer_incoming_call" msgid="4140530013111794587">"Beantwoorden"</string>
     <string name="decline_incoming_call" msgid="806026168661598368">"Weigeren"</string>
-    <string name="cant_call_due_to_ongoing_call" msgid="4952615196237854748">"Gesprek kan niet worden gestart vanwege je <xliff:g id="OTHER_CALL">%1$s</xliff:g>-gesprek."</string>
-    <string name="cant_call_due_to_ongoing_calls" msgid="1380804892363503856">"Gesprek kan niet worden gestart vanwege je <xliff:g id="OTHER_CALL">%1$s</xliff:g>-gesprekken."</string>
-    <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Gesprek kan niet worden gestart vanwege een gesprek in een andere app."</string>
-    <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Inkomende gesprekken"</string>
-    <string name="notification_channel_missed_call" msgid="8727062678632713146">"Gemiste gesprekken"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Gesprekken blokkeren"</string>
-    <string name="alert_outgoing_call" msgid="982908156825958001">"Als je dit gesprek start, wordt je <xliff:g id="OTHER_APP">%1$s</xliff:g>-gesprek beëindigd."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Gesprekken blokkeren"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Nummers die niet op je contactenlijst staan"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blokkeer nummers die niet op je contactenlijst staan"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privé"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Bellers met een anoniem nummer blokkeren"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Betaaltelefoon"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Gesprekken van betaaltelefoons blokkeren"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Onbekend"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Gesprekken van onbekende bellers blokkeren"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Gesprekken blokkeren"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Gesprekken blokkeren uitgeschakeld"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Noodoproep geplaatst"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Gesprekken blokkeren is uitgeschakeld zodat nooddiensten je kunnen bereiken."</string>
+    <string name="cant_call_due_to_ongoing_call" msgid="4952615196237854748">"Oproep kan niet worden gestart vanwege je <xliff:g id="OTHER_CALL">%1$s</xliff:g>-oproep."</string>
+    <string name="cant_call_due_to_ongoing_calls" msgid="1380804892363503856">"Oproep kan niet worden gestart vanwege je <xliff:g id="OTHER_CALL">%1$s</xliff:g>-oproepen."</string>
+    <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Oproep kan niet worden gestart vanwege een oproep in een andere app."</string>
+    <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Inkomende oproepen"</string>
+    <string name="notification_channel_missed_call" msgid="8727062678632713146">"Gemiste oproepen"</string>
+    <string name="alert_outgoing_call" msgid="982908156825958001">"Als je deze oproep start, wordt je <xliff:g id="OTHER_APP">%1$s</xliff:g>-oproep beëindigd."</string>
 </resources>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
deleted file mode 100644
index c3c6cbe..0000000
--- a/res/values-or/strings.xml
+++ /dev/null
@@ -1,100 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  Copyright (C) 2013 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.
- -->
-
-<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="382363169988504520">"କଲ୍ ପରିଚାଳନା"</string>
-    <string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"ଫୋନ୍ କରନ୍ତୁ"</string>
-    <string name="unknown" msgid="6878797917991465859">"ଅଜଣା"</string>
-    <string name="notification_missedCallTitle" msgid="7554385905572364535">"ମିସଡ୍ କଲ୍‌"</string>
-    <string name="notification_missedWorkCallTitle" msgid="6242489980390803090">"କାର୍ଯ୍ୟସ୍ଥଳୀରୁ ଆସିଥିବା ମିସଡ୍ କଲ୍"</string>
-    <string name="notification_missedCallsTitle" msgid="1361677948941502522">"ମିସଡ୍ କଲ୍"</string>
-    <string name="notification_missedCallsMsg" msgid="4575787816055205600">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g>ଟି ମିସଡ୍ କଲ୍"</string>
-    <string name="notification_missedCallTicker" msgid="504686252427747209">"<xliff:g id="MISSED_CALL_FROM">%s</xliff:g>ଙ୍କ ଠାରୁ ମିସ୍-କଲ୍ ମିଳିଛି"</string>
-    <string name="notification_missedCall_call_back" msgid="2684890353590890187">"କଲବ୍ୟାକ୍ କରନ୍ତୁ"</string>
-    <string name="notification_missedCall_message" msgid="3049928912736917988">"ମେସେଜ୍‍ ଦିଅନ୍ତୁ"</string>
-    <string name="accessibility_call_muted" msgid="2776111226185342220">"କଲ୍ ମ୍ୟୁଟ୍ କରାଯାଇଛି।"</string>
-    <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"ସ୍ପିକରଫୋନ୍‌କୁ ସକ୍ଷମ କରାଯାଇଛି ।"</string>
-    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"ବର୍ତ୍ତମାନ କଥା ହୋ‌ଇପାରିବ ନାହିଁ। କଥା କ’ଣ?"</string>
-    <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"ମୁଁ ଟିକେ ପରେ ଆପଣଙ୍କୁ କଲ୍ କରିବି।"</string>
-    <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"ମୁଁ ଆପଣଙ୍କୁ ପରେ କଲ୍ କରିବି।"</string>
-    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"ବର୍ତ୍ତମାନ କଥା ହୋ‌ଇପାରିବ ନାହିଁ। ମୋତେ ପରେ କଲ୍ କରିବେ?"</string>
-    <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"ଶୀଘ୍ର ଉତ୍ତର"</string>
-    <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"ଶୀଘ୍ର ଉତ୍ତରକୁ ଏଡିଟ୍ କରନ୍ତୁ"</string>
-    <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
-    <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"ଶୀଘ୍ର ଉତ୍ତର"</string>
-    <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g>କୁ ମେସେଜ୍ ପଠାଗଲା।"</string>
-    <string name="enable_account_preference_title" msgid="2021848090086481720">"କଲ୍ କରିବା ଆକାଉଣ୍ଟ"</string>
-    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"କେବଳ ଜରୁରିକାଳୀନ କଲ୍‌କୁ ଅନୁମତି ଦିଆଯାଇଛି।"</string>
-    <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"ଫୋନ୍‌ର ବିନାଅନୁମତିରେ ଏହି ଆପ୍ଲିକେଶନ୍ ଆଉଟ୍‌ଗୋ‌ଇଙ୍ଗ କଲ୍ କରିପାରିବ ନାହିଁ।"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"ଗୋଟିଏ କଲ୍ କରିବା ପାଇଁ ଏକ ବୈଧ ନମ୍ବର୍ ପ୍ରବେଶ କରନ୍ତୁ।"</string>
-    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"ଏହି ସମୟରେ କଲ୍ ଯୋଡ଼ାଯାଇପାରିବ ନାହିଁ।"</string>
-    <string name="no_vm_number" msgid="4164780423805688336">"ହଜିଯାଇଥିବା ଭଏସମେଲ୍ ନମ୍ବର୍"</string>
-    <string name="no_vm_number_msg" msgid="1300729501030053828">"SIM କାର୍ଡରେ କୌଣସି ଭଏସମେଲ୍ ନମ୍ବର୍ ଷ୍ଟୋର୍ କରାଯାଇନାହିଁ।"</string>
-    <string name="add_vm_number_str" msgid="4676479471644687453">"ନମ୍ବର୍ ଯୋଡ଼ନ୍ତୁ"</string>
-    <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"<xliff:g id="NEW_APP">%s</xliff:g>କୁ ଆପଣଙ୍କ ଫୋନ୍‌ର ଡିଫଲ୍ଟ ଆପ୍ କରିବେ?"</string>
-    <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"ଡିଫଲ୍ଟ ସେଟ୍ କରନ୍ତୁ"</string>
-    <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"କ୍ୟାନ୍ସଲ୍‍ କରନ୍ତୁ"</string>
-    <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> କଲ୍ କରିବା ଏବଂ କଲ୍‌ର ସମସ୍ତ ଦିଗକୁ ନିୟନ୍ତ୍ରଣ କରିବାରେ ସକ୍ଷମ ହେବ। କେବଳ ନିଜର ଭରସାଯୋଗ୍ୟ ଆପ୍‌କୁ ଡିଫଲ୍ଟ ଫୋନ୍ ଆପ୍ ଭାବେ ସେଟ୍ କରିବା ଉଚିତ୍।"</string>
-    <string name="blocked_numbers" msgid="2751843139572970579">"ଅବରୋଧ କରାଯାଇଥିବା ନମ୍ବର୍"</string>
-    <string name="blocked_numbers_msg" msgid="1045015186124965643">"ଅବରୋଧ କରାଯାଇଥିବା ନମ୍ବର୍‌ରୁ ଆପଣ କଲ୍ କିମ୍ବା ଟେକ୍ସଟ୍ ଗ୍ରହଣ କରିପାରିବେ ନାହିଁ।"</string>
-    <string name="block_number" msgid="1101252256321306179">"ଗୋଟିଏ ନମ୍ବର୍ ଯୋଡ଼ନ୍ତୁ"</string>
-    <string name="unblock_dialog_body" msgid="1614238499771862793">"<xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>ରୁ ଅବରୋଧ ହଟାଇବେ?"</string>
-    <string name="unblock_button" msgid="3078048901972674170">"ଅବରୋଧ ହଟାନ୍ତୁ"</string>
-    <string name="add_blocked_dialog_body" msgid="9030243212265516828">"ଏହାର କଲ୍ ଓ ଟେକ୍ସଟ୍‌କୁ ଅବରୋଧ କରନ୍ତୁ"</string>
-    <string name="add_blocked_number_hint" msgid="6847675097085433553">"ଫୋନ୍ ନମ୍ଵର୍"</string>
-    <string name="block_button" msgid="8822290682524373357">"ଅବରୋଧ କରନ୍ତୁ"</string>
-    <string name="non_primary_user" msgid="5180129233352533459">"କେବଳ ଡିଭାଇସ୍‌ର ମାଲିକ ଅବରୋଧ କରାଯାଇଥିବା ନମ୍ବର୍‌କୁ ଦେଖିପାରିବେ ଓ ପରିଚାଳନା କରିପାରିବେ।"</string>
-    <string name="delete_icon_description" msgid="8903995728252556724">"ଅବରୋଧ ହଟାନ୍ତୁ"</string>
-    <string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"ଅସ୍ଥାୟୀରୂପେ ଅବରୋଧ ଅଫ୍ ଅଛି"</string>
-    <string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"ଆପଣ ଗୋଟିଏ ଜରୁରିକାଳୀନ ନମ୍ବର୍‌କୁ ଡାଏଲ୍ କିମ୍ବା ଟେକ୍ସଟ୍ କରିବା ପରେ, ଜରୁରିକାଳୀନ ସେବା ଆପଣଙ୍କୁ ଯୋଗାଯୋଗ କରିବାକୁ ସୁନିଶ୍ଚିତ କରିବା ପାଇଁ ଅବରୋଧକୁ ବନ୍ଦ କରିଦିଆଯାଇଥାଏ।"</string>
-    <string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"ବର୍ତ୍ତମାନ ପୁନଃସକ୍ଷମ କରନ୍ତୁ"</string>
-    <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> ଅବରୋଧ କରାଯାଇଛି"</string>
-    <string name="blocked_numbers_number_unblocked_message" msgid="977894647366750418">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> ଅବରୋଧ ହଟାଇଦିଆଯାଇଛି"</string>
-    <string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"ଜରୁରିକାଳୀନ ନମ୍ବର୍‌କୁ ଅବରୋଧ କରିବାରେ ଅକ୍ଷମ।"</string>
-    <string name="blocked_numbers_number_already_blocked_message" msgid="4392247814500811798">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g>କୁ ଅବରୋଧ କରାଯାଇସରିଛି।"</string>
-    <string name="toast_personal_call_msg" msgid="5115361633476779723">"କଲ୍ କରିବା ପାଇଁ ବ୍ୟକ୍ତିଗତ ଡାଏଲର୍‌କୁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
-    <string name="notification_incoming_call" msgid="7713197997773986670">"<xliff:g id="CALL_FROM">%2$s</xliff:g> ଠାରୁ <xliff:g id="CALL_VIA">%1$s</xliff:g>କୁ କଲ୍ କରନ୍ତୁ"</string>
-    <string name="notification_incoming_video_call" msgid="6638486071698373893">"<xliff:g id="CALL_FROM">%2$s</xliff:g> ଠାରୁ <xliff:g id="CALL_VIA">%1$s</xliff:g> ଭିଡିଓ କଲ୍ କରନ୍ତୁ"</string>
-    <string name="answering_ends_other_call" msgid="8282145910153766401">"ଉତ୍ତର ଦେବାଦ୍ଵାରା ଆପଣଙ୍କର <xliff:g id="CALL_VIA">%1$s</xliff:g> କଲ୍ ସମାପ୍ତ ହୋ‌ଇଯିବ"</string>
-    <string name="answering_ends_other_calls" msgid="1198589551399049197">"ଉତ୍ତର ଦେବାଦ୍ଵାରା ଆପଣଙ୍କର <xliff:g id="CALL_VIA">%1$s</xliff:g> କଲ୍ ସମାପ୍ତ ହୋ‌ଇଯିବ"</string>
-    <string name="answering_ends_other_video_call" msgid="8510410917384186360">"ଉତ୍ତର ଦେବାଦ୍ଵାରା ଆପଣଙ୍କର <xliff:g id="CALL_VIA">%1$s</xliff:g> ଭିଡିଓ କଲ୍ ସମାପ୍ତ ହୋ‌ଇଯିବ"</string>
-    <string name="answering_ends_other_managed_call" msgid="5186137550267947785">"ଉତ୍ତର ଦେବାଦ୍ଵାରା ଆପଣଙ୍କର ଜାରି ରହିଥିବା କଲ୍ ସମାପ୍ତ ହୋ‌ଇଯିବ"</string>
-    <string name="answering_ends_other_managed_calls" msgid="6429838309560397988">"ଉତ୍ତର ଦେବାଦ୍ଵାରା ଆପଣଙ୍କର ଜାରି ରହିଥିବା କଲ୍ ସମାପ୍ତ ହୋ‌ଇଯିବ"</string>
-    <string name="answering_ends_other_managed_video_call" msgid="1585423762458248435">"ଉତ୍ତର ଦେବାଦ୍ଵାରା ଆପଣଙ୍କର ଜାରି ରହିଥିବା ଭିଡିଓ କଲ୍ ସମାପ୍ତ ହୋ‌ଇଯିବ"</string>
-    <string name="answer_incoming_call" msgid="4140530013111794587">"ଉତ୍ତର ଦିଅନ୍ତୁ"</string>
-    <string name="decline_incoming_call" msgid="806026168661598368">"ଅସ୍ୱୀକାର"</string>
-    <string name="cant_call_due_to_ongoing_call" msgid="4952615196237854748">"ଆପଣଙ୍କର <xliff:g id="OTHER_CALL">%1$s</xliff:g> କଲ୍ ହେତୁ କଲ୍ କରାଯାଇପାରିବ ନାହିଁ।"</string>
-    <string name="cant_call_due_to_ongoing_calls" msgid="1380804892363503856">"ଆପଣଙ୍କର <xliff:g id="OTHER_CALL">%1$s</xliff:g> କଲ୍ ହେତୁ କଲ୍ କରାଯାଇପାରିବ ନାହିଁ।"</string>
-    <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"ଅନ୍ୟ ଆପ୍‌ରେ କରାଯାଇଥିବା କଲ୍ ହେତୁ କଲ୍ କରାଯାଇପାରିବ ନାହିଁ।"</string>
-    <string name="notification_channel_incoming_call" msgid="3513761697082968084">"ଇନ୍‌କମିଙ୍ଗ କଲ୍"</string>
-    <string name="notification_channel_missed_call" msgid="8727062678632713146">"ମିସଡ୍ କଲ୍"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"କଲ୍‌କୁ ଅବରୋଧ କରନ୍ତୁ"</string>
-    <string name="alert_outgoing_call" msgid="982908156825958001">"ଏହି କଲ୍‌କୁ ସ୍ଥାପନ କରିବା ଦ୍ଵାରା ଆପଣଙ୍କର <xliff:g id="OTHER_APP">%1$s</xliff:g> କଲ୍ ସମାପ୍ତ ହୋ‌ଇଯିବ।"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"କଲ୍‌କୁ ଅବରୋଧ କରନ୍ତୁ"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"ଯୋଗାଯୋଗରେ ନଥିବା ନମ୍ବର୍"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"ଆପଣଙ୍କ ଯୋଗାଯୋଗରେ ତାଲିକାଭୁକ୍ତ ହୋ‌ଇନଥିବା ନମ୍ବର୍‌କୁ ଅବରୋଧ କରନ୍ତୁ"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"ଗୋପନୀୟ"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"ନିଜର ନମ୍ବର୍‌କୁ ପ୍ରକାଶ କରୁନଥିବା କଲ୍‌କର୍ତ୍ତାଙ୍କୁ ଅବରୋଧ କରନ୍ତୁ"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"ପେ-ଫୋନ୍"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"ପେ-ଫୋନ୍‌ରୁ କଲ୍‌କୁ ଅବରୋଧ କରନ୍ତୁ"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"ଅଜଣା"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"ଅଚିହ୍ନା କଲକର୍ତ୍ତାଙ୍କର କଲ୍‌କୁ ଅବରୋଧ କରନ୍ତୁ"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"କଲ୍‌କୁ ଅବରୋଧ କରନ୍ତୁ"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"କଲ୍ ଅବରୋଧ ସୁବିଧାକୁ ଅକ୍ଷମ କରାଯାଇଛି"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"ଜରୁରିକାଳୀନ କଲ୍ କରାଗଲା"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"ଜରୁରିକାଳୀନ ସହାୟତା କର୍ମଚାରୀମାନେ ଆପଣଙ୍କୁ ଯୋଗଯୋଗ କରିବା ପାଇଁ କଲ୍ ଅବରୋଧକୁ ଅକ୍ଷମ କରାଯାଇଛି।"</string>
-</resources>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 47e279b..5bf26f3 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -67,7 +67,7 @@
     <string name="blocked_numbers_block_emergency_number_message" msgid="917851876780698387">"ਐਮਰਜੈਂਸੀ ਨੰਬਰ ਨੂੰ ਬਲੌਕ ਕਰਨ ਵਿੱਚ ਅਸਮਰੱਥ।"</string>
     <string name="blocked_numbers_number_already_blocked_message" msgid="4392247814500811798">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> ਪਹਿਲਾਂ ਤੋਂ ਹੀ ਬਲੌਕ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string>
     <string name="toast_personal_call_msg" msgid="5115361633476779723">"ਕਾਲ ਕਰਨ ਲਈ ਨਿੱਜੀ ਡਾਇਲਰ ਦੀ ਵਰਤੋਂ ਕਰਨੀ"</string>
-    <string name="notification_incoming_call" msgid="7713197997773986670">"<xliff:g id="CALL_VIA">%1$s</xliff:g> ਕਾਲ ਕਰਤਾ <xliff:g id="CALL_FROM">%2$s</xliff:g>"</string>
+    <string name="notification_incoming_call" msgid="7713197997773986670">"<xliff:g id="CALL_FROM">%2$s</xliff:g> ਵੱਲੋਂ <xliff:g id="CALL_VIA">%1$s</xliff:g> ਕਾਲ"</string>
     <string name="notification_incoming_video_call" msgid="6638486071698373893">"<xliff:g id="CALL_FROM">%2$s</xliff:g> ਵੱਲੋਂ <xliff:g id="CALL_VIA">%1$s</xliff:g> ਵੀਡੀਓ ਕਾਲ"</string>
     <string name="answering_ends_other_call" msgid="8282145910153766401">"ਜਵਾਬ ਦੇਣ ਨਾਲ ਤੁਹਾਡੀ <xliff:g id="CALL_VIA">%1$s</xliff:g> ਕਾਲ ਸਮਾਪਤ ਹੋ ਜਾਵੇਗੀ"</string>
     <string name="answering_ends_other_calls" msgid="1198589551399049197">"ਜਵਾਬ ਦੇਣ ਨਾਲ ਤੁਹਾਡੀਆਂ <xliff:g id="CALL_VIA">%1$s</xliff:g> ਕਾਲਾਂ ਸਮਾਪਤ ਹੋ ਜਾਣਗੀਆਂ"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"ਕਿਸੇ ਹੋਰ ਐਪ ਵਿੱਚ ਇੱਕ ਕਾਲ ਹੋਣ ਦੇ ਕਾਰਨ ਕਾਲ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"ਇਨਕਮਿੰਗ ਕਾਲਾਂ"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"ਖੁੰਝੀਆਂ ਕਾਲਾਂ"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"ਕਾਲ ਬਲਾਕਿੰਗ"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"ਇਹ ਕਾਲ ਕਰਨ ਨਾਲ ਤੁਹਾਡੀ <xliff:g id="OTHER_APP">%1$s</xliff:g> ਕਾਲ ਸਮਾਪਤ ਹੋ ਜਾਵੇਗੀ।"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"ਕਾਲ ਬਲਾਕਿੰਗ"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"ਨੰਬਰ ਜੋ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਵਿੱਚ ਨਹੀਂ ਹਨ"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"ਉਹ ਨੰਬਰ ਬਲਾਕ ਕਰੋ ਜੋ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਵਿੱਚ ਨਹੀਂ ਹਨ"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"ਨਿੱਜੀ"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"ਉਹ ਕਾਲਰ ਬਲਾਕ ਕਰੋ ਜਿਨ੍ਹਾਂ ਦਾ ਨੰਬਰ ਨਹੀਂ ਦਿਖਾਈ ਦਿੰਦਾ ਹੈ"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"ਜਨਤਕ ਫ਼ੋਨ"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"ਜਨਤਕ ਫ਼ੋਨਾਂ ਵਾਲੀਆਂ ਕਾਲਾਂ ਬਲਾਕ ਕਰੋ"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"ਅਗਿਆਤ"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"ਅਣਪਛਾਤੇ ਕਾਲਰਾਂ ਵਾਲੀਆਂ ਕਾਲਾਂ ਬਲਾਕ ਕਰੋ"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"ਕਾਲ ਬਲਾਕਿੰਗ"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"ਕਾਲ ਬਲਾਕਿੰਗ ਵਿਕਲਪ ਬੰਦ ਕੀਤਾ ਗਿਆ"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"ਸੰਕਟਕਾਲੀਨ ਕਾਲ ਕੀਤੀ ਗਈ"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"ਸੰਕਟਕਾਲੀਨ ਸਥਿਤੀ ਵਿੱਚ ਮਦਦ ਕਰਨ ਵਾਲੇ ਵਿਅਕਤੀ ਨੂੰ ਤੁਹਾਨੂੰ ਸੰਪਰਕ ਕਰਨ ਦੇਣ ਲਈ ਕਾਲ ਬਲਾਕਿੰਗ ਵਿਕਲਪ ਬੰਦ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ।"</string>
 </resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index b48bdb3..4a5820f 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Nie możesz zadzwonić z powodu trwającej rozmowy w innej aplikacji."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Połączenia przychodzące"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Połączenia nieodebrane"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Blokowanie połączeń"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Jeśli zadzwonisz, połączenie w aplikacji <xliff:g id="OTHER_APP">%1$s</xliff:g> zostanie zakończone."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Blokowanie połączeń"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Numery spoza Kontaktów"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blokuj połączenia od numerów, które nie znajdują się w Kontaktach"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Zastrzeżone"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Blokuj połączenia z numerów zastrzeżonych"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Budki telefoniczne"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Blokuj połączenia z budek telefonicznych"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Nieznane"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Blokuj połączenia z nieznanych numerów"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Blokowanie połączeń"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Blokowanie połączeń wyłączone"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Wykonano połączenie alarmowe"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Blokowanie połączeń zostało wyłączone, aby służby ratownicze mogły się z Tobą skontaktować."</string>
 </resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 8dc9405..9b7d239 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Não é possível efetuar a chamada devido a uma chamada noutra aplicação."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Chamadas recebidas"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Chamadas não atendidas"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Bloqueio de chamadas"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Ao efetuar esta chamada, irá terminar a chamada na aplicação <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Bloqueio de chamadas"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Números não incluídos nos Contactos"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Bloquear números que não estejam na sua lista de Contactos"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privadas"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Bloquear autores de chamadas que não revelem o número"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Telefone público"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Bloquear chamadas de telefones públicos"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Desconhecidas"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Bloquear chamadas não identificadas"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Bloqueio de chamadas"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Bloqueio de chamadas desativado"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Chamada de emergência efetuada"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"O bloqueio de chamadas foi desativado para permitir a receção de contactos de resposta a emergências."</string>
 </resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 25d2345..597e75e 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -43,12 +43,12 @@
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Para realizar uma chamada, digite um número válido."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"No momento, não é possível adicionar a chamada."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Número correio de voz ausente"</string>
-    <string name="no_vm_number_msg" msgid="1300729501030053828">"Não há um número correio de voz armazenado no chip."</string>
+    <string name="no_vm_number_msg" msgid="1300729501030053828">"Não há um número correio de voz armazenado no cartão SIM."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Adicionar número"</string>
-    <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Usar o <xliff:g id="NEW_APP">%s</xliff:g> como seu app de telefone padrão?"</string>
+    <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Usar o <xliff:g id="NEW_APP">%s</xliff:g> como seu aplicativo de smartphone padrão?"</string>
     <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Definir padrão"</string>
     <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Cancelar"</string>
-    <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"O <xliff:g id="NEW_APP">%s</xliff:g> poderá ligar e controlar todos os aspectos das chamadas. Defina como aplicativo Telefone padrão somente aqueles em que você confia."</string>
+    <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"O <xliff:g id="NEW_APP">%s</xliff:g> poderá ligar e controlar todos os aspectos das chamadas. Defina como aplicativo de smartphone padrão somente aqueles em que você confia."</string>
     <string name="blocked_numbers" msgid="2751843139572970579">"Números bloqueados"</string>
     <string name="blocked_numbers_msg" msgid="1045015186124965643">"Você não receberá chamadas nem mensagens de texto dos números bloqueados."</string>
     <string name="block_number" msgid="1101252256321306179">"Adicionar um número"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Não é possível ligar com uma chamada em andamento em outro aplicativo."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Chamadas recebidas"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Chamadas perdidas"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Bloqueio de chamadas"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Se você ligar agora, sua chamada será encerrada no <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Bloqueio de chamadas"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Números que não estão nos contatos"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Bloquear os números que não estão nos seus contatos"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Particular"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Bloquear os autores das chamadas que não divulgam o número"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Orelhão"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Bloquear chamadas de orelhão"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Desconhecido"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Bloquear chamadas de autores não identificados"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Bloqueio de chamadas"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Bloqueio de chamadas desativado"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"A chamada de emergência foi feita"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"O bloqueio de chamadas foi desativado para permitir que a equipe de emergência entre em contato com você."</string>
 </resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index ae17707..770fb24 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Apelul nu poate fi inițiat din cauza unui apel din altă aplicație."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Apeluri primite"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Apeluri nepreluate"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Blocarea apelurilor"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Dacă inițiați acest apel, cel din <xliff:g id="OTHER_APP">%1$s</xliff:g> va fi încheiat."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Blocarea apelurilor"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Numere care nu sunt în Agendă"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blocați numerele care nu sunt înregistrate în Agendă"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privat"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Blocați apelanții care nu își afișează numărul"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Telefon public"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Blocați apelurile de la telefoane publice"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Necunoscut"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Blocați apelurile de la apelanți neidentificați"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Blocarea apelurilor"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Blocarea apelurilor este dezactivată."</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"S-a efectuat un apel de urgență."</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Blocarea apelurilor a fost dezactivată pentru a permite serviciilor de urgență să vă contacteze."</string>
 </resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 8b56d7b..d1a7a56 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Вы не можете отправить новый вызов, пока не завершите текущий в другом приложении"</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Входящие вызовы"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Пропущенные вызовы"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Блокировка вызовов"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Если вы начнете этот звонок, вызов в <xliff:g id="OTHER_APP">%1$s</xliff:g> будет завершен."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Блокировка вызовов"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Незнакомые номера"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Блокировать номера, которых нет в ваших контактах"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Скрытые номера"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Блокировать вызовы со скрытых номеров"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Телефоны-автоматы"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Блокировать вызовы с телефонов-автоматов"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Неизвестные номера"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Блокировать вызовы с неопределяемых номеров"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Блокировка вызовов"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Блокировка вызовов отключена"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Выполнен экстренный вызов"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Блокировка вызовов отключена, чтобы у экстренных служб была возможность позвонить вам."</string>
 </resources>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index 538f96d..b5e2110 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"වෙනත් යෙදුමක ඇමතුමක් හේතුවෙන් ඇමතුම ගැනීමට නොහැකිය."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"එන ඇමතුම්"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"මඟ හැරුණු ඇමතුම්"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"ඇමතුම් අවහිර කිරීම"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"මෙම ඇමතුම ගැනීම ඔබේ <xliff:g id="OTHER_APP">%1$s</xliff:g> ඇමතුම අවසන් කරනු ඇත."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"ඇමතුම් අවහිර කිරීම"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"සම්බන්ධතා තුළ නොමැති අංක"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"ඔබගේ සම්බන්ධතා තුළ ලැයිස්තුගත නොකරන ලද අංක අවහිර කරන්න"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"පෞද්ගලික"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"ඔවුන්ගේ අංකය අනාවරණය නොකරන අමතන්නන් අවහිර කරන්න"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"ගෙවුම් දුරකථනය"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"ගෙවුම් දුරකථන වෙතින් වන ඇමතුම් අවහිර කරන්න"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"නොදනී"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"නොහඳුනන අමතන්නන් වෙතින් වන ඇමතුම් අවහිර කරන්න"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"ඇමතුම් අවහිර කිරීම"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"ඇමතුම් අවහිර කිරීම අබල කර ඇත"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"හදිසි ඇමතුම් ගැනීම"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"හදිසි අමතන්නන්ට ඔබව සම්බන්ධ කර ගැනීමට ඉඩ දීමට ඇමතුම් අවහිර කිරීම අබල කර ඇත."</string>
 </resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index eb7fc51..5268ba4 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -28,10 +28,10 @@
     <string name="notification_missedCall_message" msgid="3049928912736917988">"Napísať"</string>
     <string name="accessibility_call_muted" msgid="2776111226185342220">"Zvuk hovoru bol vypnutý."</string>
     <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"Reproduktor je povolený."</string>
-    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"Teraz nemôžem hovoriť, o čo ide?"</string>
+    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"Teraz nemôžem hovoriť, o čo ide?"</string>
     <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"Zavolám späť."</string>
     <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"Zavolám neskôr."</string>
-    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"Nemôžem hovoriť, zavoláte neskôr?"</string>
+    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"Teraz nemôžem, zavolajte inokedy."</string>
     <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"Rýchle odpovede"</string>
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Upraviť rýchle odpovede"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Hovor sa nedá uskutočniť, pretože prebieha hovor v inej aplikácii."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Prichádzajúce hovory"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Zmeškané hovory"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Blokovanie hovorov"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Ak uskutočníte tento hovor, hovor cez <xliff:g id="OTHER_APP">%1$s</xliff:g> bude ukončený."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Blokovanie hovorov"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Čísla, ktoré nie sú v kontaktoch"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blokovať čísla, ktoré nemáte v kontaktoch"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Skryté čísla"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Blokovať volajúcich, ktorí skrývajú svoje číslo"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Verejný telefón"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Blokovať hovory z verejných telefónov"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Nerozpoznané číslo"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Blokovať hovory od nerozpoznaných volajúcich"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Blokovanie hovorov"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Blokovanie hovorov je vypnuté"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Bolo uskutočnené tiesňové volanie"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Blokovanie hovorov bolo vypnuté, aby vás mohli kontaktovať pracovníci tiesňových služieb."</string>
 </resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 083a7c5..de9716a 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Klica ni mogoče vzpostaviti zaradi klica prek druge aplikacije."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Dohodni klici"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Neodgovorjeni klici"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Blokiranje klicev"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Če opravite ta klic, bo končan klic prek aplikacije <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Blokiranje klicev"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Številke, ki niso v stikih"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blokirajte številke, ki niso na seznamu vaših stikov"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Zasebno"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Blokirajte klicatelje, ki ne razkrijejo številke"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Telefonska govorilnica"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Blokirajte klice iz telefonskih govorilnic"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Neznano"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Blokirajte klice neznanih klicateljev"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Blokiranje klicev"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Blokiranje klicev je onemogočeno"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Opravljen je klic v sili"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Blokiranje klicev je onemogočeno, da lahko stik z vami vzpostavijo uslužbenci služb za klic v sili."</string>
 </resources>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 325f62b..06d5f09 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Telefonata nuk mund të kryhet për shkak të një telefonate në një aplikacion tjetër."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Telefonatat hyrëse"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Telefonatat e humbura"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Bllokimi i telefonatave"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Kryerja e kësaj telefonate do të mbyllë telefonatën tënde në <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Bllokimi i telefonatave"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Numrat që nuk janë te \"Kontaktet\""</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blloko numrat që nuk janë të listuar te \"Kontaktet\" e tua"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Private"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Blloko telefonuesit që nuk e zbulojnë numrin e tyre"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Telefon me pagesë"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Blloko telefonatat nga telefonat me pagesë"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"E panjohur"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Blloko telefonatat nga telefonuesit e paidentifikuar"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Bllokimi i telefonatave"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Bllokimi i telefonatave u çaktivizua"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Telefonata e urgjencës u krye"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Bllokimi i telefonatave është çaktivizuar për të lejuar që personat që përgjigjen në rast urgjence të kontaktojnë me ty."</string>
 </resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 59f5969..b3f1554 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Не можете да упутите позив због позива у другој апликацији."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Долазни позиви"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Пропуштени позиви"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Блокирање позива"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Ако упутите овај позив, завршићете <xliff:g id="OTHER_APP">%1$s</xliff:g> позив."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Блокирање позива"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Бројеви који нису у контактима"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Блокирајте бројеве који вам нису у контактима"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Скривени бројеви"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Блокирајте позиваоце који скривају број"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Телефонска говорница"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Блокирајте позиве са телефонских говорница"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Непознати бројеви"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Блокирајте позиве неидентификованих позивалаца"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Блокирање позива"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Блокирање позива је онемогућено"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Упућен је хитни позив"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Блокирање позива је онемогућено да би хитне службе могле да вас контактирају."</string>
 </resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 78a3963..6e4d661 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Det går inte att ringa på grund av ett samtal via en annan app."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Inkommande samtal"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Missade samtal"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Samtalsblockering"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Ringer du det här samtalet avslutas samtalet i <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Samtalsblockering"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Nummer inte i Kontakter"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Blockera nummer som inte finns i Kontakter"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Privat"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Blockera uppringare som inte visar sitt nummer"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Telefonautomat"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Blockera samtal från telefonautomater"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Okänd"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Blockera samtal från oidentifierade uppringare"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Samtalsblockering"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Samtalsblockering inaktiverad"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Nödsamtal ringt"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Samtalsblockering har inaktiverats för att tillåta att räddningstjänsten kontaktar dig."</string>
 </resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 86b83a5..6ba2995 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -45,10 +45,10 @@
     <string name="no_vm_number" msgid="4164780423805688336">"Nambari ya sauti inayokosekana"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Hakuna nambari ya ujumbe wa sauti iliyohifadhiwa katika SIM kadi."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Ongeza nambari"</string>
-    <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Unataka kufanya <xliff:g id="NEW_APP">%s</xliff:g> iwe programu chaguomsingi ya simu?"</string>
+    <string name="change_default_dialer_dialog_title" msgid="9101655962941740507">"Unataka kufanya <xliff:g id="NEW_APP">%s</xliff:g> iwe programu chaguo-msingi ya simu?"</string>
     <string name="change_default_dialer_dialog_affirmative" msgid="8606546663509166276">"Fanya iwe Chaguo-Msingi"</string>
     <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"Ghairi"</string>
-    <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> itaweza kupiga simu na kudhibiti kila kipengele cha simu. Unastahili kuweka programu unazoziamini tu kama programu chaguomsingi ya kupiga simu."</string>
+    <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> itaweza kupiga simu na kudhibiti kila kipengele cha simu. Unastahili kuweka programu unazoziamini tu kama programu chaguo-msingi ya kupiga simu."</string>
     <string name="blocked_numbers" msgid="2751843139572970579">"Nambari zilizozuiwa"</string>
     <string name="blocked_numbers_msg" msgid="1045015186124965643">"Hutapokea simu au SMS kutoka kwa nambari zilizozuiwa."</string>
     <string name="block_number" msgid="1101252256321306179">"Ongeza nambari"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Haiwezekani kwa sababu kuna simu inayoendelea kwenye programu nyingine."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Simu zinazoingia"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Simu ambazo hukujibu"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Kuzuia Simu"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Ukipiga simu hii, simu yako kwenye <xliff:g id="OTHER_APP">%1$s</xliff:g> itakatwa."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Kuzuia Simu"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Nambari ambazo haziko kwenye Anwani"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Zuia nambari ambazo hazipo kwenye orodha ya Anwani zako"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Faragha"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Zuia wapigaji ambao wameficha nambari zao za simu"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Simu ya kulipia"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Zuia simu kutoka kwa nambari ya simu za kulipia"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Zisizojulikani"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Zuia simu kutoka kwa wapigaji wasiojulikana"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Kuzuia Simu"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Kipengele cha Kuzuia Simu kimezimwa"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Simu ya dharura imepigwa"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Kipengele cha Kuzuia Simu kimezimwa ili kuruhusu wapigaji simu za dharura kuwasiliana nawe."</string>
 </resources>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index 8c2d3a1..6fbf74a 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -28,10 +28,10 @@
     <string name="notification_missedCall_message" msgid="3049928912736917988">"செய்தி"</string>
     <string name="accessibility_call_muted" msgid="2776111226185342220">"அழைப்பு முடக்கப்பட்டது."</string>
     <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"ஸ்பீக்கர்ஃபோன் இயக்கப்பட்டது."</string>
-    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"இப்போது பேசமுடியாது. என்ன விசேஷம்?"</string>
+    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"இப்போது பேசமுடியாது. என்ன விஷேசம்?"</string>
     <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"சிறிதுநேரம் கழித்து நான் அழைக்கிறேன்."</string>
     <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"பிறகு அழைக்கிறேன்."</string>
-    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"இப்போது பேசமுடியாது, பிறகு அழைக்கிறீர்களா?"</string>
+    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"இப்போது பேச முடியவில்லை. பிறகு அழைக்க முடியுமா?"</string>
     <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"விரைவு பதில்கள்"</string>
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"விரைவு பதில்களை மாற்று"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"மற்றொரு பயன்பாட்டில் அழைப்பு செயலில் உள்ளதால், புதிய அழைப்பைச் செய்ய முடியாது."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"உள்வரும் அழைப்புகள்"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"தவறிய அழைப்புகள்"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"அழைப்புத் தடுப்பு"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"புதிய அழைப்பைச் செய்தால், செயலில் உள்ள <xliff:g id="OTHER_APP">%1$s</xliff:g> அழைப்பு துண்டிக்கப்படும்."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"அழைப்புத் தடுப்பு"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"தொடர்புகளில் இல்லாத எண்கள்"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"உங்கள் தொடர்புகளில் பட்டியலிடப்படாத எண்களைத் தடுக்கும்"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"தனிப்பட்ட எண்கள்"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"எண்ணை வெளிப்படுத்தாத அழைப்பாளர்களைத் தடுக்கும்"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"கட்டண ஃபோன்"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"கட்டண ஃபோன்களில் இருந்து வரும் அழைப்புகளைத் தடுக்கும்"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"தெரியாத அழைப்புகள்"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"அடையாளம் தெரியாத அழைப்பாளர்களின் அழைப்புகளைத் தடுக்கும்"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"அழைப்புத் தடுப்பு"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"அழைப்புத் தடுப்பு முடக்கப்பட்டுள்ளது"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"அவசர அழைப்பு செய்யப்பட்டது"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"அவசரநிலையில் பதிலளிப்பவர்களை உங்களைத் தொடர்புகொள்வதற்கு அனுமதிக்க, அழைப்புத் தடுப்பு முடக்கப்பட்டுள்ளது."</string>
 </resources>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index d6cd091..74bc7f0 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"వేరొక అనువర్తనంలో కాల్ కొనసాగుతున్నందున కాల్ చేయడం సాధ్యపడదు."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"ఇన్‌కమింగ్ కాల్‌లు"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"సమాధానం ఇవ్వని కాల్‌లు"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"కాల్ బ్లాక్ చేయడం"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"ఈ కాల్ చేయడం వలన మీ <xliff:g id="OTHER_APP">%1$s</xliff:g> కాల్ ముగుస్తుంది."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"కాల్ బ్లాక్ చేయడం"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"పరిచయాలలో లేని నంబర్‌లు"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"మీ పరిచయాలలో లేని నంబర్‌లను బ్లాక్ చేయండి"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"ప్రైవేట్"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"తమ నంబర్‌ను కనిపించకుండా చేసే కాలర్‌లను బ్లాక్ చేయండి"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"పే ఫోన్"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"పే ఫోన్‌ల నుండి కాల్‌లను బ్లాక్ చేయండి"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"తెలియని"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"తెలియని కాలర్‌ల నుండి కాల్‌లను బ్లాక్ చేయండి"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"కాల్ బ్లాక్ చేయడం"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"కాల్ బ్లాక్ చేయడం నిలిపివేయబడింది"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"అత్యవసర కాల్ చేయబడింది"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"మిమ్మల్ని సంప్రదించడానికి అత్యవసర ప్రతిస్పందనదారులను అనుమతించడానికి కాల్ బ్లాక్ చేయడం నిలిపివేయబడింది."</string>
 </resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 913d1da..d130b0f 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -50,7 +50,7 @@
     <string name="change_default_dialer_dialog_negative" msgid="9078144617060173845">"ยกเลิก"</string>
     <string name="change_default_dialer_warning_message" msgid="1417671460801684999">"<xliff:g id="NEW_APP">%s</xliff:g> จะจัดการการโทรและควบคุมการติดต่อทุกด้าน โปรดติดตั้งเฉพาะแอปที่คุณไว้วางใจให้เป็นแอปโทรศัพท์เริ่มต้น"</string>
     <string name="blocked_numbers" msgid="2751843139572970579">"หมายเลขที่ถูกบล็อก"</string>
-    <string name="blocked_numbers_msg" msgid="1045015186124965643">"คุณจะไม่สามารถรับสายหรือข้อความจากหมายเลขที่บล็อก"</string>
+    <string name="blocked_numbers_msg" msgid="1045015186124965643">"คุณจะไม่สามารถรับสายหรือข้อความจากหมายเลขที่บล็อกได้"</string>
     <string name="block_number" msgid="1101252256321306179">"เพิ่มหมายเลข"</string>
     <string name="unblock_dialog_body" msgid="1614238499771862793">"เลิกบล็อก <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g> ใช่ไหม"</string>
     <string name="unblock_button" msgid="3078048901972674170">"เลิกบล็อก"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"ไม่สามารถโทรออกได้เนื่องจากกำลังใช้สายอยู่ในแอปอื่น"</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"สายโทรเข้า"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"สายที่ไม่ได้รับ"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"การบล็อกสาย"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"การโทรออกนี้จะวางสายใน <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"การบล็อกสาย"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"หมายเลขที่ไม่อยู่ในรายชื่อติดต่อ"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"บล็อกหมายเลขที่ไม่อยู่ในรายชื่อติดต่อของคุณ"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"ส่วนตัว"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"บล็อกผู้โทรที่ไม่เปิดเผยหมายเลขโทรศัพท์"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"โทรศัพท์สาธารณะ"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"บล็อกสายจากโทรศัพท์สาธารณะ"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"ไม่ทราบ"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"บล็อกสายจากผู้โทรที่ไม่สามารถระบุได้"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"การบล็อกสาย"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"ปิดใช้การบล็อกสาย"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"โทรหมายเลขฉุกเฉินแล้ว"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"ปิดใช้การบล็อกสายแล้วเพื่อให้ทีมฉุกเฉินติดต่อคุณ"</string>
 </resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index d4182da..8f56cb2 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Hindi makakatawag dahil sa isang tawag sa isa pang app."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Mga papasok na tawag"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Mga hindi nasagot na tawag"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Pag-block ng Tawag"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Tatapusin ng pagtawag na ito ang iyong tawag sa <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Pag-block ng Tawag"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Mga numerong wala sa Mga Contact"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"I-block ang mga numero na hindi nakalista sa iyong Mga Contact"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Pribado"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Bina-block ang mga tumatawag na hindi hinahayag ang kanilang numero"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Pay phone"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Bina-block ang mga tawag mula sa mga pay phone"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Hindi Alam"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Bina-block ang mga tumatawag mula sa mga hindi kilalang tumatawag"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Pag-block ng Tawag"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Naka-disable ang Pag-block ng Tawag"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Ginawang emergency na tawag"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Na-disable ang Pag-block ng Tawag para payagan ang mga tumutugon sa emergency na kontakin ka."</string>
 </resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index b5a05f3..ccef824 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Başka bir uygulamada devam eden çağrınız nedeniyle telefon araması yapılamıyor."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Gelen çağrılar"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Cevapsız çağrılar"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Çağrı Engelleme"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Bu çağrıyı yaptığınızda <xliff:g id="OTHER_APP">%1$s</xliff:g> çağrınız sona erecek."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Çağrı Engelleme"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Kişiler arasında bulunmayan numaralar"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Kişileriniz arasında bulunmayan numaralar engellenir"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Gizli"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Gizli numaradan arayanlar engellenir"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Ankesörlü telefon"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Ankesörlü telefonlardan gelen çağrılar engellenir"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Bilinmeyen"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Tanımlanamayan arayanlardan gelen çağrılar engellenir"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Çağrı Engelleme"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Çağrı Engelleme devre dışı bırakıldı"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Acil durum çağrısı yapıldı"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Acil durum müdahale ekibinin sizinle iletişime geçmesine olanak tanımak için Çağrı Engelleme devre dışı bırakıldı."</string>
 </resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index f17be5c..5a22892 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Неможливо зателефонувати через поточний виклик в іншому додатку."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Вхідні виклики"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Пропущені виклики"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Блокування викликів"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Якщо здійснити цей виклик, буде завершено виклик у додатку <xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Блокування викликів"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Номери, які не входять до списку контактів"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Блокування номерів, які не входять до вашого списку контактів"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Приватно"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Блокування абонентів, які не розкривають свої номери"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Таксофон"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Блокування викликів із таксофонів"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Невідомо"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Блокування викликів від невизначених абонентів"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Блокування викликів"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Блокування викликів вимкнено"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Здійснено екстрений виклик"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Блокування викликів вимкнено, щоб ви могли отримувати екстрені сповіщення."</string>
 </resources>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index 186bdf1..f94d85b 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"کسی دوسری ایپ میں موجود کال کی کی وجہ سے کال نہیں کی جا سکتی۔"</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"آنے والی کالیں"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"چھوٹی ہوئی کالیں"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"کال مسدود کرنا"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"یہ کال کرنے سے <xliff:g id="OTHER_APP">%1$s</xliff:g> کال ختم ہو جائے گی۔"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"کال مسدود کرنا"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"وہ نمبرز جو رابطوں میں نہیں ہیں"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"ان نمبرز کو مسدود کریں جو آپ کے رابطوں میں مندرج نہیں ہیں"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"نجی"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"ان کالرز کو مسدود کریں جو اپنے نمبرز کا افشاء نہیں کرتے ہیں"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"پے فون"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"پے فونز سے آنے والی کالز کو مسدود کریں"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"نامعلوم"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"غیر شناخت کردہ کالرز سے آنے والی کالز کو مسدود کریں"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"کال مسدود کرنا"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"کال مسدود کرنا غیر فعال ہو گیا ہے"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"ہنگامی کال کی گئی"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"ہنگامی حالت میں جواب دہندگان کو آپ سے رابطہ کرنے کی اجازت دینے کیلئے کال مسدود کرنا غیر فعال ہو گیا ہے۔"</string>
 </resources>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 11cc6fa..714ddc9 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -68,7 +68,7 @@
     <string name="blocked_numbers_number_already_blocked_message" msgid="4392247814500811798">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> raqami allaqachon bloklangan."</string>
     <string name="toast_personal_call_msg" msgid="5115361633476779723">"Qo‘ng‘iroq qilish uchun shaxsiy raqam tergichdan foydalanilmoqda"</string>
     <string name="notification_incoming_call" msgid="7713197997773986670">"<xliff:g id="CALL_FROM">%2$s</xliff:g> <xliff:g id="CALL_VIA">%1$s</xliff:g> orqali chaqirmoqda"</string>
-    <string name="notification_incoming_video_call" msgid="6638486071698373893">"<xliff:g id="CALL_FROM">%2$s</xliff:g> <xliff:g id="CALL_VIA">%1$s</xliff:g> orqali video chaqiruv"</string>
+    <string name="notification_incoming_video_call" msgid="6638486071698373893">"<xliff:g id="CALL_FROM">%2$s</xliff:g> <xliff:g id="CALL_VIA">%1$s</xliff:g> orqali video qo‘ng‘iroq qilmoqda"</string>
     <string name="answering_ends_other_call" msgid="8282145910153766401">"Chaqiruvga javob berilsa, <xliff:g id="CALL_VIA">%1$s</xliff:g> qo‘ng‘irog‘i tugatiladi."</string>
     <string name="answering_ends_other_calls" msgid="1198589551399049197">"Chaqiruvga javob berilsa, <xliff:g id="CALL_VIA">%1$s</xliff:g> qo‘ng‘iroqlari tugatiladi."</string>
     <string name="answering_ends_other_video_call" msgid="8510410917384186360">"Chaqiruvga javob berilsa, <xliff:g id="CALL_VIA">%1$s</xliff:g> video suhbati tugatiladi."</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Boshqa ilovadagi joriy qo‘ng‘iroq tufayli boshqa raqamni chaqirib bo‘lmaydi."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Kiruvchi chaqiruvlar"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Javobsiz chaqiruvlar"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Chaqiruvlarni bloklash"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Bu qo‘ng‘iroqni amalga oshirsangiz, <xliff:g id="OTHER_APP">%1$s</xliff:g> qo‘ng‘irog‘i tugatiladi."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Chaqiruvlarni bloklash"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Notanish raqamlar"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Kontaktlaringizga kiritilmagan notanish raqamlarni bloklash"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Yashirin raqamlar"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Yashirin raqamlardan keluvchi chaqiruvlarni bloklash"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Taksofon"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Taksofondan keluvchi chaqiruvlarni bloklash"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Notanish raqamlar"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Aniqlanmagan raqamlardan keluvchi chaqiruvlarni bloklash"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Chaqiruvlarni bloklash"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Chaqiruvlarni bloklash funksiyasi yoqilmagan"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Favqulodda chaqiruv qilindi"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Sizga favqulodda chiqiruv qilish imkoni bo‘lishi uchun chaqiruvlarni bloklash funksiyasi o‘chirib qo‘yilgan."</string>
 </resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index b0f6560..3a7e4b9 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Không thể thực hiện cuộc gọi do có cuộc gọi trong một ứng dụng khác."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Cuộc gọi đến"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Cuộc gọi nhỡ"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Chặn cuộc gọi"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Thực hiện cuộc gọi này sẽ kết thúc cuộc gọi <xliff:g id="OTHER_APP">%1$s</xliff:g> của bạn."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Chặn cuộc gọi"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Các số không có trong Danh bạ"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Chặn các số không có trong Danh bạ của bạn"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Riêng tư"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Chặn người gọi không tiết lộ số của họ"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Điện thoại công cộng"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Chặn các cuộc gọi từ điện thoại công cộng"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Không xác định"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Chặn cuộc gọi từ người gọi không xác định"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Chặn cuộc gọi"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Đã tắt tính năng Chặn cuộc gọi"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Đã thực hiện cuộc gọi khẩn cấp"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Đã tắt tính năng Chặn cuộc gọi để cho phép người trả lời khẩn cấp liên hệ với bạn."</string>
 </resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 370b718..2edc91a 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"由于当前正在通过其他应用通话,因此无法拨打电话。"</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"来电"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"未接电话"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"来电屏蔽"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"拨打此电话将导致<xliff:g id="OTHER_APP">%1$s</xliff:g>通话结束。"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"来电屏蔽"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"不在通讯录中的号码"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"屏蔽未列在您通讯录中的号码"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"不显示号码"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"屏蔽不显示号码的来电者"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"公用电话"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"屏蔽公用电话来电"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"未知"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"屏蔽身份不明的来电者的电话"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"来电屏蔽"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"来电屏蔽功能已停用"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"已拨打紧急呼救电话"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"系统已停用来电屏蔽功能,以便急救人员与您联系。"</string>
 </resources>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 1d2dd46..5d783ad 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"由於已在另一個應用程式中進行通話,因此無法撥打電話。"</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"來電"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"未接來電"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"來電封鎖"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"如果撥打此電話,您的 <xliff:g id="OTHER_APP">%1$s</xliff:g> 通話將會結束。"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"來電封鎖"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"不在通訊錄中的號碼"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"封鎖不在通訊錄中的號碼"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"私人"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"封鎖不透露號碼的來電者"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"公共電話"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"封鎖公共電話來電"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"不明"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"封鎖不明來電者的來電"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"來電封鎖"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"已停用來電封鎖功能"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"已撥緊急電話"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"已停用來電封鎖功能,以便救援人員與您聯絡。"</string>
 </resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index da34cd2..8a9ca00 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -33,7 +33,7 @@
     <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"我晚點回電。"</string>
     <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"我現在不方便講話,晚點再打來好嗎?"</string>
     <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"應答短訊"</string>
-    <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"編輯快速回應"</string>
+    <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"編輯應答短訊"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"快速回應"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"訊息已傳送至 <xliff:g id="PHONE_NUMBER">%s</xliff:g>。"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"你正在使用其他應用程式進行通話,因此無法撥打電話。"</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"來電"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"未接來電"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"來電封鎖"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"撥打這通電話將結束你的「<xliff:g id="OTHER_APP">%1$s</xliff:g>」通話。"</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"來電封鎖"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"不屬於聯絡人的號碼"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"封鎖不屬於聯絡人的號碼"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"不顯示號碼"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"封鎖不顯示號碼的來電者"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"公共電話"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"封鎖公共電話來電"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"不明"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"封鎖不明來電者的來電"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"來電封鎖"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"已停用來電封鎖"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"已撥打緊急電話"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"系統已停用來電封鎖功能,以便緊急應變人員與你聯絡。"</string>
 </resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 79e5846..ac7e9b5 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -59,7 +59,7 @@
     <string name="block_button" msgid="8822290682524373357">"Vimba"</string>
     <string name="non_primary_user" msgid="5180129233352533459">"Umnikazi wedivayisi kuphela ongabuka aphinde aphathe izinombolo ezivinjelwe."</string>
     <string name="delete_icon_description" msgid="8903995728252556724">"Vulela"</string>
-    <string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"Ukuvimbela kuvaliwe okwesikhashana"</string>
+    <string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"Ukuvimble kuvaliwe okwesikhashana"</string>
     <string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"Ngemuva kokudayela noma ubhalele inombolo yesimo esiphuthumayo, ukuvimbela kuvaliwe ukuqinisekisa amasevisi esimo esiphuthumayo angakwazi ukuxhumana nawe."</string>
     <string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"Nika amandla manje"</string>
     <string name="blocked_numbers_number_blocked_message" msgid="7678509606805029540">"I-<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> ivinjiwe"</string>
@@ -82,19 +82,5 @@
     <string name="cant_call_due_to_ongoing_unknown_call" msgid="149091978697302211">"Ikholi ayikwazi ukwenziwa ngenxa yekholi kolunye uhlelo lokusebenza."</string>
     <string name="notification_channel_incoming_call" msgid="3513761697082968084">"Amakholi angenayo"</string>
     <string name="notification_channel_missed_call" msgid="8727062678632713146">"Amakholi akuphuthile"</string>
-    <string name="notification_channel_call_blocking" msgid="2943358779746676070">"Ukuvimbela ikholi"</string>
     <string name="alert_outgoing_call" msgid="982908156825958001">"Ukwenza le kholi kuzoqeda enye ikholi yakho ye-<xliff:g id="OTHER_APP">%1$s</xliff:g>."</string>
-    <string name="phone_settings_call_blocking_txt" msgid="3976004073043846733">"Ukuvimbela ikholi"</string>
-    <string name="phone_settings_number_not_in_contact_txt" msgid="3126829421867168652">"Inombolo ayikho koxhumana nabo"</string>
-    <string name="phone_settings_number_not_in_contact_summary_txt" msgid="9043147855140079119">"Vimbela izinombolo ezingafakiwe kuhlu loxhumana nabo"</string>
-    <string name="phone_settings_private_num_txt" msgid="8623574188879134262">"Kuyimfihlo"</string>
-    <string name="phone_settings_private_num_summary_txt" msgid="7516314821207782191">"Vimbela abashayayo abangayidaluli inombolo yabo"</string>
-    <string name="phone_settings_payphone_txt" msgid="2493356957416981318">"Ifoni ekhokhelwayo"</string>
-    <string name="phone_settings_payphone_summary_txt" msgid="6126709946103814653">"Vimbela amakholi kusukela kumafoni akhokhelwayo"</string>
-    <string name="phone_settings_unknown_txt" msgid="5836407031508172721">"Akwaziwa"</string>
-    <string name="phone_settings_unknown_summary_txt" msgid="3457690230497753233">"Vimbela amakholi kusukela kwabashayayo abangaziwa"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="628536625775266096">"Ukuvimbela ikholi"</string>
-    <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="6264230048947693941">"Ukuvimbela ikholi kukhutshaziwe"</string>
-    <string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="7421611725400166580">"Ikholi ephuthumayo yenziwe"</string>
-    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="4083285098613193052">"Ukuvimbela ikholi kukhutshaziwe ukuze kuvunyelwe abaphenduli besimo esiphuthumayo ukuthi baxhumane nawe."</string>
 </resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 8ff0b8e..144f699 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -15,17 +15,21 @@
   -->
 
 <resources>
+    <!--follows the dialer theme color-->
     <color name="theme_color">#2a56c6</color>
+    <color name="background_color">#fafafa</color>
 
-    <color name="dialer_settings_actionbar_text_color">#ffffff</color>
-    <color name="dialer_settings_actionbar_background_color">@color/theme_color</color>
-    <color name="dialer_settings_color_dark">#1c3aa9</color>
+    <!--Use the one consistence with dialer-->
+    <color name="blocked_numbers_divider_color">#d8d8d8</color>
+    <color name="blocked_numbers_primary_text_color">#202124</color>
+    <color name="blocked_numbers_secondary_text_color">#5f6368</color>
 
-    <color name="blocked_numbers_divider_color">#e5e5e5</color>
-    <color name="blocked_numbers_butter_bar_color">#f5f5f5</color>
-    <color name="blocked_numbers_title_text_color">#ba000000</color>
-    <color name="blocked_numbers_secondary_text_color">#89000000</color>
-
+    <!--follows dialer color-->
     <color name="notification_action_answer">#097138</color>
     <color name="notification_action_decline">#A52714</color>
+
+    <color name="call_redirection_dialog_icon_tint_color">#4089F4</color>
+    <color name="call_redirection_dialog_text_color">#212121</color>
+    <color name="call_redirection_dialog_view_divider_color">#B8B8B8</color>
+
 </resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 8c84688..c0162b2 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -60,4 +60,21 @@
          between repeats of the ringtone.
          When false, the ringtone will be looping with no pause. -->
     <bool name="should_pause_between_ringtone_repeats">true</bool>
+
+    <!-- Threshold for the X+Y component of gravity needed for the device orientation to be
+         classified as being on a user's ear. -->
+    <item name="device_on_ear_xy_gravity_threshold" format="float" type="dimen">5.5</item>
+
+    <!-- Lower threshold for the Y-component of gravity needed for the device orientation to be
+         classified as being on a user's ear. If the Y-component is less than this negative value,
+         the device is probably upside-down and therefore not on a ear -->
+    <item name="device_on_ear_y_gravity_negative_threshold" format="float" type="dimen">-1</item>
+
+    <!-- When true, an option is shown in the call blocking screen which allows the user to block
+         all incoming calls from callers not in their contacts. -->
+    <bool name="show_option_to_block_callers_not_in_contacts">false</bool>
+
+    <!-- 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>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 7b085ad..52b688c 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -27,9 +27,19 @@
     <dimen name="blocked_numbers_dialog_padding">24dp</dimen>
     <dimen name="blocked_numbers_delete_icon_padding">12dp</dimen>
     <dimen name="blocked_numbers_progress_bar_padding">100dp</dimen>
-    <dimen name="blocked_numbers_font_size">16sp</dimen>
+    <dimen name="blocked_numbers_head1_font_size">18sp</dimen>
+    <dimen name="blocked_numbers_primary2_font_size">16sp</dimen>
     <dimen name="blocked_numbers_secondary_font_size">14sp</dimen>
     <dimen name="blocked_numbers_line_spacing">8sp</dimen>
     <dimen name="blocked_numbers_secondary_line_spacing">6sp</dimen>
     <dimen name="blocked_numbers_divider_stroke">1dp</dimen>
+
+    <dimen name="call_redirection_dialog_title_font_size">18sp</dimen>
+    <dimen name="call_redirection_dialog_button_font_size">16sp</dimen>
+    <dimen name="call_redirection_dialog_image_upper_margin">16dp</dimen>
+    <dimen name="call_redirection_dialog_image_bottom_margin">10dp</dimen>
+    <dimen name="call_redirection_dialog_title_bottom_margin">26dp</dimen>
+    <dimen name="call_redirection_dialog_button_text_upper_bottom_margin">15dp</dimen>
+    <dimen name="call_redirection_dialog_button_text_left_margin">15dp</dimen>
+
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index bb63ad2..e4e588c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -79,6 +79,10 @@
         a text response. [CHAR LIMIT=40] -->
     <string name="respond_via_sms_confirmation_format">Message sent to <xliff:g id="phone_number">%s</xliff:g>.</string>
 
+    <!-- "Respond via SMS": Error toast shown after failing to send
+        a text response. [CHAR LIMIT=40] -->
+    <string name="respond_via_sms_failure_format">Message failed to send to <xliff:g id="phone_number">%s</xliff:g>.</string>
+
     <!-- Title of settings screen that allows user to enable and disable phone-accounts.
          Each method for placing a call (SIM1, SIM2, SIP account, etc) has a phone-account.
          Phone-accounts that are created by third party apps can be disabled and enabled by user.
@@ -107,7 +111,7 @@
     <!-- Button label on the "Missing voicemail number" dialog -->
     <string name="add_vm_number_str">Add number</string>
 
-    <!-- Title of dialog used to comfirm whether the user intends to change the default dialer
+    <!-- Title of dialog used to confirm whether the user intends to change the default dialer
             application [CHAR LIMIT=55]-->
     <string name="change_default_dialer_dialog_title">Make <xliff:g id="new_app">%s</xliff:g> your default Phone app?</string>
     <!-- Confirmation text that a user taps on to change the Default Phone App-->
@@ -117,6 +121,18 @@
     <!-- Warning message indicating what may happen if a user allows a 3rd party app to become the default dialer.-->
     <string name="change_default_dialer_warning_message"><xliff:g id="new_app">%s</xliff:g> will be able to place and control all aspects of calls. Only apps you trust should be set as the default Phone app.</string>
 
+    <!-- Title of dialog used to confirm whether the user intends to change the default call screening
+            application [CHAR LIMIT=55]-->
+    <string name="change_default_call_screening_dialog_title">Make <xliff:g id="new_app">%s</xliff:g> your default call screening app?</string>
+    <!-- Warning message indicating the old call screening app will no longer be able to screen calls.-->
+    <string name="change_default_call_screening_warning_message_for_disable_old_app"><xliff:g id="old_app">%s</xliff:g> will no longer be able to screen calls.</string>
+    <!-- Warning message indicating what may happen if a user allows a 3rd party app to become the default call screening.-->
+    <string name="change_default_call_screening_warning_message"><xliff:g id="new_app">%s</xliff:g> will be able to see information about callers not in your contacts and will be able to block these calls. Only apps you trust should be set as the default call screening app.</string>
+    <!-- Confirmation text that a user taps on to change the Default call screening App-->
+    <string name="change_default_call_screening_dialog_affirmative">Set Default</string>
+    <!-- Cancel text that a user taps on to not change the Default call screening App-->
+    <string name="change_default_call_screening_dialog_negative">Cancel</string>
+
     <!-- Blocked numbers -->
     <string name="blocked_numbers">Blocked numbers</string>
     <!-- Text shown at the beginning of the blocked numbers screen to explain what the screen is about. -->
@@ -233,6 +249,12 @@
     <!-- The "decline" button for an incoming call. [CHAR LIMIT=60] -->
     <string name="decline_incoming_call">Decline</string>
 
+    <!-- Error message shown to the user when an outgoing call cannot be placed because there no
+         calling service is present on the device which supports this call type.
+         This is typically encountered when the user tries to dial a SIP/VOIP call, but there are
+         no calling services present which support SIP calling. [CHAR LIMIT=none] -->
+    <string name="cant_call_due_to_no_supported_service">Call cannot be placed because there are no calling accounts which support calls of this type.</string>
+
     <!-- Error message shown to the user when an outgoing call cannot be placed due to an ongoing
          phone call in a third-party app.  For example:
          Call cannot be placed due to your Duo call. [CHAR LIMIT=none] -->
@@ -259,6 +281,18 @@
          ongoing call in the app "other_app". -->
     <string name="alert_outgoing_call">Placing this call will end your <xliff:g id="other_app">%1$s</xliff:g> call.</string>
 
+    <!-- Alert dialog content used to ask the user to confirm if they want to place a new outgoing call redirected by the app "other_app". -->
+    <string name="alert_redirect_outgoing_call_or_not">Choose how to place this call</string>
+
+    <!-- A button in the alert dialog "alert_redirect_outgoing_call" to place the call with the redirected number provided by App. -->
+    <string name="alert_place_outgoing_call_with_redirection">Redirect call using <xliff:g id="other_app">%1$s</xliff:g></string>
+
+    <!-- A button in the alert dialog "alert_redirect_outgoing_call" to place the call without the redirected number provided by App. -->
+    <string name="alert_place_unredirect_outgoing_call">Call using my phone number</string>
+
+    <!-- Alert dialog content used to tell the user the call is canceled because no response from the call redirection app "other_app". -->
+    <string name="alert_redirect_outgoing_call_timeout">Call can\'t be placed by <xliff:g id="other_app">%1$s</xliff:g>. Try using a different call redirecting app or contacting the developer for help.</string>
+
     <!-- The name of a feature available under the Call settings. -->
     <string name="phone_settings_call_blocking_txt">Call Blocking</string>
     <!-- Call type to be blocked. See the explanatory text "phone_settings_number_not_in_contact_summary_txt". -->
@@ -285,4 +319,10 @@
     <string name="phone_strings_emergency_call_made_dialog_title_txt">Emergency call made</string>
     <!-- Notification details that appear when the user taps the notification "phone_strings_call_blocking_turned_off_notification_text_txt". -->
     <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt">Call Blocking has been disabled to allow emergency responders to contact you.</string>
+    <!-- Window title used for the Telecom Developer Menu -->
+    <string name="developer_title">Telecom Developer Menu</string>
+    <!-- Label for a switch in the Telecom Developer Menu which is used to enable the enhanced call
+         blocking functionality (for test purposes).
+         DO NOT TRANSLATE -->
+    <string name="developer_enhanced_call_blocking" translatable="false">Enhanced Call Blocking</string>
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 3216719..2e8e624 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -26,58 +26,66 @@
     </style>
 
     <style name="Theme.Telecom.DialerSettings" parent="@android:style/Theme.Material.Light">
+        <item name="android:tint">@color/blocked_numbers_secondary_text_color</item>
         <item name="android:actionBarStyle">@style/TelecomDialerSettingsActionBarStyle</item>
         <item name="android:actionOverflowButtonStyle">@style/TelecomDialerSettingsActionOverflowButtonStyle</item>
-        <item name="android:colorPrimaryDark">@color/dialer_settings_color_dark</item>
-        <item name="android:homeAsUpIndicator">@drawable/ic_back_arrow</item>
+        <item name="android:colorPrimaryDark">@color/background_color</item>
+        <item name="android:windowLightStatusBar">true</item>
+        <item name="android:navigationBarColor">@color/background_color</item>
+        <item name="android:navigationBarDividerColor">@color/blocked_numbers_divider_color</item>
+        <item name="android:windowLightNavigationBar">true</item>
         <item name="android:windowContentOverlay">@null</item>
     </style>
 
     <style name="Theme.Telecom.BlockedNumbers" parent="@android:style/Theme.Material.Light">
+        <item name="android:tint">@color/blocked_numbers_secondary_text_color</item>
         <item name="android:actionBarStyle">@style/TelecomDialerSettingsActionBarStyle</item>
-        <item name="android:colorPrimaryDark">@color/dialer_settings_color_dark</item>
-        <item name="android:homeAsUpIndicator">@drawable/ic_back_arrow</item>
+        <item name="android:colorPrimaryDark">@color/background_color</item>
+        <item name="android:windowLightStatusBar">true</item>
+        <item name="android:navigationBarColor">@color/background_color</item>
+        <item name="android:navigationBarDividerColor">@color/blocked_numbers_divider_color</item>
+        <item name="android:windowLightNavigationBar">true</item>
         <item name="android:windowContentOverlay">@null</item>
         <item name="android:colorAccent">@color/theme_color</item>
         <item name="android:listDivider">@null</item>
     </style>
 
     <style name="TelecomDialerSettingsActionBarStyle" parent="android:Widget.Material.ActionBar">
-        <item name="android:background">@color/dialer_settings_actionbar_background_color</item>
-        <item name="android:titleTextStyle">@style/TelecomDialerSettingsActionBarTitleText</item>
+        <item name="android:background">@color/background_color</item>
+        <item name="android:titleTextStyle">@style/BlockedNumbersTextHead1</item>
         <item name="android:elevation">@dimen/dialer_settings_actionbar_elevation</item>
         <!-- Empty icon -->
         <item name="android:icon">@android:color/transparent</item>
     </style>
 
-    <style name="TelecomDialerSettingsActionBarTitleText"
-            parent="@android:style/TextAppearance.Material.Widget.ActionBar.Title">
-        <item name="android:textColor">@color/dialer_settings_actionbar_text_color</item>
-    </style>
-
     <style name="TelecomDialerSettingsActionOverflowButtonStyle"
             parent="@android:style/Widget.Material.Light.ActionButton.Overflow">
         <item name="android:src">@drawable/ic_more_vert_24dp</item>
     </style>
 
-    <style name="BlockedNumbersButton">
+    <style name="BlockedNumbersButton" parent="BlockedNumbersTextPrimary2">
         <item name="android:textColor">@color/theme_color</item>
-        <item name="android:textSize">@dimen/blocked_numbers_font_size</item>
         <item name="android:textAllCaps">true</item>
     </style>
 
-    <style name="BlockedNumbersText">
-        <item name="android:textSize">@dimen/blocked_numbers_font_size</item>
+    <style name="BlockedNumbersTextHead1"
+           parent="@android:style/TextAppearance.Material.Widget.ActionBar.Title">
+        <item name="android:textColor">@color/blocked_numbers_primary_text_color</item>
+        <item name="android:textSize">@dimen/blocked_numbers_head1_font_size</item>
+        <item name="android:fontFamily">sans-serif-regular</item>
+    </style>
+
+    <style name="BlockedNumbersTextPrimary2">
+        <item name="android:textColor">@color/blocked_numbers_primary_text_color</item>
+        <item name="android:textSize">@dimen/blocked_numbers_primary2_font_size</item>
+        <item name="android:fontFamily">sans-serif-regular</item>
         <item name="android:lineSpacingExtra">@dimen/blocked_numbers_line_spacing</item>
     </style>
 
-    <style name="BlockedNumbersTitleText"  parent="BlockedNumbersText">
-        <item name="android:textColor">@color/blocked_numbers_title_text_color</item>
-    </style>
-
-    <style name="BlockedNumbersSecondaryText">
+    <style name="BlockedNumbersTextSecondary">
         <item name="android:textColor">@color/blocked_numbers_secondary_text_color</item>
         <item name="android:textSize">@dimen/blocked_numbers_secondary_font_size</item>
+        <item name="android:fontFamily">sans-serif-regular</item>
         <item name="android:lineSpacingExtra">@dimen/blocked_numbers_secondary_line_spacing</item>
     </style>
 </resources>
diff --git a/res/xml/activity_blocked_numbers.xml b/res/xml/activity_blocked_numbers.xml
index 15e1859..e137313 100644
--- a/res/xml/activity_blocked_numbers.xml
+++ b/res/xml/activity_blocked_numbers.xml
@@ -43,7 +43,7 @@
                     android:paddingTop="@dimen/blocked_numbers_large_padding"
                     android:paddingLeft="@dimen/blocked_numbers_large_padding"
                     android:paddingRight="@dimen/blocked_numbers_large_padding"
-                    style="@style/BlockedNumbersTitleText"
+                    style="@style/BlockedNumbersTextPrimary2"
                     android:visibility="gone" />
 
             <LinearLayout
@@ -70,7 +70,7 @@
                             android:layout_height="wrap_content"
                             android:text="@string/blocked_numbers_msg"
                             android:paddingBottom="@dimen/blocked_numbers_extra_large_padding"
-                            style="@style/BlockedNumbersTitleText" />
+                            style="@style/BlockedNumbersTextPrimary2" />
 
                     <TextView
                             android:id="@+id/add_blocked"
diff --git a/res/xml/add_blocked_number_dialog.xml b/res/xml/add_blocked_number_dialog.xml
index ed7d507..35ab633 100644
--- a/res/xml/add_blocked_number_dialog.xml
+++ b/res/xml/add_blocked_number_dialog.xml
@@ -20,18 +20,22 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical"
+        android:gravity="start"
         android:padding="@dimen/blocked_numbers_dialog_padding">
     <TextView
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="@string/add_blocked_dialog_body"
             android:paddingBottom="@dimen/blocked_numbers_large_padding"
-            style="@style/BlockedNumbersTitleText" />
+            android:gravity="start"
+            style="@style/BlockedNumbersTextPrimary2" />
     <EditText
             android:id="@+id/add_blocked_number"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:paddingTop="@dimen/blocked_numbers_large_padding"
+            android:textDirection="locale"
+            android:textAlignment="viewStart"
             android:hint="@string/add_blocked_number_hint"
             android:inputType="phone" />
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/res/xml/blocking_suppressed_butterbar.xml b/res/xml/blocking_suppressed_butterbar.xml
index d6a8472..8b941b9 100644
--- a/res/xml/blocking_suppressed_butterbar.xml
+++ b/res/xml/blocking_suppressed_butterbar.xml
@@ -19,7 +19,7 @@
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:background="@color/blocked_numbers_butter_bar_color">
+        android:background="@color/background_color">
 
     <ImageView
             android:id="@+id/icon"
@@ -39,7 +39,7 @@
             android:paddingTop="@dimen/blocked_numbers_large_padding"
             android:paddingRight="@dimen/blocked_numbers_large_padding"
             android:text="@string/blocked_numbers_butter_bar_title"
-            style="@style/BlockedNumbersTitleText" />
+            style="@style/BlockedNumbersTextPrimary2" />
 
     <TextView
             android:id="@+id/description"
@@ -51,7 +51,7 @@
             android:paddingBottom="@dimen/blocked_numbers_large_padding"
             android:paddingRight="@dimen/blocked_numbers_large_padding"
             android:text="@string/blocked_numbers_butter_bar_body"
-            style="@style/BlockedNumbersSecondaryText" />
+            style="@style/BlockedNumbersTextSecondary" />
 
     <TextView
             android:id="@+id/reenable_button"
diff --git a/res/xml/layout_blocked_number.xml b/res/xml/layout_blocked_number.xml
index fbd7de3..720d71a 100644
--- a/res/xml/layout_blocked_number.xml
+++ b/res/xml/layout_blocked_number.xml
@@ -20,7 +20,7 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:focusable="true"
-    style="@style/BlockedNumbersText"
+    style="@style/BlockedNumbersTextPrimary2"
     android:gravity="start">
 
     <TextView
diff --git a/scripts/aosp_tag_preupload.py b/scripts/aosp_tag_preupload.py
new file mode 100755
index 0000000..77a9714
--- /dev/null
+++ b/scripts/aosp_tag_preupload.py
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+
+import re
+import subprocess
+import sys
+
+# Looks for a string of the form [aosp/branch-name]
+AOSP_BRANCH_REGEX = "\[aosp/[^\]]+\]"
+
+AOSP_COMMIT_TAG_REGEX = "AOSP:"
+AOSP_COMMIT_LINK_REGEX = "aosp/\d+"
+AOSP_INFEASIBLE_REGEX = "Infeasible[ ]?\S+"
+
+ERROR_MESSAGE = """
+The source of truth for this project is AOSP. If you are uploading something to
+a non-AOSP branch first, please provide a link in your commit message to the
+corresponding patch in AOSP. The link should be formatted as follows:
+
+  AOSP: aosp/<patch number>
+
+If it's infeasible for the change to be included in AOSP (for example, if a
+change contains confidential or security-sensitive information), please state
+that it's infeasible and provide reasoning as follows:
+
+  AOSP: Infeasible <your reasoning here>
+
+If you need to cherry-pick your change from an internal branch to AOSP before
+uploading, you can do so locally by adding the internal branch as a remote in
+AOSP:
+  git remote add goog-master /path/to/your/remote/branch/.git
+starting a new branch in AOSP:
+  repo start <your-branch-name>-cp
+then fetching and cherry-picking the change:
+  git fetch goog-master your-branch-name && git cherry-pick FETCH_HEAD
+"""
+
+def main():
+  if _is_in_aosp():
+    sys.exit(0)
+
+  commit_msg = subprocess.check_output(["git", "show",
+                                        sys.argv[1], "--no-notes"])
+  for commit_line in commit_msg.splitlines():
+    if re.search(AOSP_COMMIT_TAG_REGEX, commit_line, re.IGNORECASE):
+      _check_aosp_message(commit_line)
+
+  print(ERROR_MESSAGE)
+  sys.exit(0)
+
+def _is_in_aosp():
+  branch_info = subprocess.check_output(["git", "branch", "-vv"])
+  return re.search(AOSP_BRANCH_REGEX, branch_info) is not None
+
+def _check_aosp_message(aosp_line):
+  if re.search(AOSP_COMMIT_LINK_REGEX, aosp_line):
+    sys.exit(0)
+
+  if re.search(AOSP_INFEASIBLE_REGEX, aosp_line, re.IGNORECASE):
+    sys.exit(0)
+
+  print(ERROR_MESSAGE)
+  sys.exit(0)
+
+if __name__ == '__main__':
+  main()
diff --git a/scripts/telecom_testing.sh b/scripts/telecom_testing.sh
index 779f449..788597b 100644
--- a/scripts/telecom_testing.sh
+++ b/scripts/telecom_testing.sh
@@ -58,12 +58,12 @@
       build_dir="packages/services/Telecomm/tests"
       apk_loc="data/app/TelecomUnitTests/TelecomUnitTests.apk"
       package_prefix="com.android.server.telecom.tests"
-      instrumentation="android.support.test.runner.AndroidJUnitRunner";;
+      instrumentation="androidx.test.runner.AndroidJUnitRunner";;
     "telephony")
       build_dir="frameworks/opt/telephony/tests/"
       apk_loc="data/app/FrameworksTelephonyTests/FrameworksTelephonyTests.apk"
       package_prefix="com.android.frameworks.telephonytests"
-      instrumentation="android.support.test.runner.AndroidJUnitRunner";;
+      instrumentation="androidx.test.runner.AndroidJUnitRunner";;
   esac
 
   local T=$(gettop)
@@ -121,7 +121,7 @@
   if [ $coverage = true ] && [ $project =~ "telecom" ] ; then
     e_options="${e_options} -e coverage 'true'"
   fi
-  adb shell am instrument ${e_options} -w "$package_prefix/$instrumentation"
+  adb shell am instrument --no-hidden-api-checks ${e_options} -w "$package_prefix/$instrumentation"
 
   # Code coverage only enabled for Telecom.
   if [ $coverage = true ] && [ $project =~ "telecom" ] ; then
diff --git a/src/com/android/server/telecom/Analytics.java b/src/com/android/server/telecom/Analytics.java
index d2cdeca..1d3a90e 100644
--- a/src/com/android/server/telecom/Analytics.java
+++ b/src/com/android/server/telecom/Analytics.java
@@ -31,6 +31,9 @@
 import com.android.server.telecom.nano.TelecomLogClass;
 
 import java.io.PrintWriter;
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -39,6 +42,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.PriorityQueue;
+import java.util.concurrent.LinkedBlockingDeque;
 import java.util.stream.Collectors;
 
 import static android.telecom.ParcelableCallAnalytics.AnalyticsEvent;
@@ -165,6 +169,9 @@
         public void setCallIsAdditional(boolean isAdditional) {
         }
 
+        public void setCallIsEmergency(boolean isEmergency) {
+        }
+
         public void setCallIsInterrupted(boolean isInterrupted) {
         }
 
@@ -305,6 +312,12 @@
         }
 
         @Override
+        public void setCallIsEmergency(boolean isEmergency) {
+            Log.d(TAG, "setting call as emergency: " + isEmergency);
+            this.isEmergency = isEmergency;
+        }
+
+        @Override
         public void setCallDisconnectCause(DisconnectCause disconnectCause) {
             Log.d(TAG, "setting disconnectCause for call " + callId + " to " + disconnectCause);
             this.callTerminationReason = disconnectCause;
@@ -376,6 +389,7 @@
                     + "    direction: " + getCallDirectionString() + '\n'
                     + "    isAdditionalCall: " + isAdditionalCall + '\n'
                     + "    isInterrupted: " + isInterrupted + '\n'
+                    + "    isEmergency: " + isEmergency + '\n'
                     + "    callTechnologies: " + getCallTechnologiesAsString() + '\n'
                     + "    callTerminationReason: " + getCallDisconnectReasonString() + '\n'
                     + "    connectionService: " + connectionService + '\n'
@@ -568,8 +582,11 @@
     public static final long MILLIS_IN_1_SECOND = ParcelableCallAnalytics.MILLIS_IN_1_SECOND;
 
     public static final int MAX_NUM_CALLS_TO_STORE = 100;
+    public static final int MAX_NUM_DUMP_TIMES_TO_STORE = 100;
 
     private static final Object sLock = new Object(); // Coarse lock for all of analytics
+    private static final LinkedBlockingDeque<Long> sDumpTimes =
+            new LinkedBlockingDeque<>(MAX_NUM_DUMP_TIMES_TO_STORE);
     private static final Map<String, CallInfoImpl> sCallIdToInfo = new HashMap<>();
     private static final LinkedList<String> sActiveCallIds = new LinkedList<>();
     private static final List<SessionTiming> sSessionTimings = new LinkedList<>();
@@ -615,6 +632,7 @@
         TelecomLogClass.TelecomLog result = new TelecomLogClass.TelecomLog();
 
         synchronized (sLock) {
+            noteDumpTime();
             result.callLogs = sCallIdToInfo.values().stream()
                     .map(CallInfoImpl::toProto)
                     .toArray(TelecomLogClass.CallLog[]::new);
@@ -670,6 +688,12 @@
                     .forEach(e -> writer.printf("%s: %.2f\n",
                             sSessionIdToLogSession.get(e.getKey()), e.getValue()));
             writer.println("Hardware Version: " + SystemProperties.get("ro.boot.revision", ""));
+            writer.println("Past analytics dumps: ");
+            writer.increaseIndent();
+            for (long time : sDumpTimes) {
+                writer.println(Instant.ofEpochMilli(time).atZone(ZoneOffset.UTC));
+            }
+            writer.decreaseIndent();
         }
     }
 
@@ -679,6 +703,17 @@
         }
     }
 
+    public static void noteDumpTime() {
+        if (sDumpTimes.remainingCapacity() == 0) {
+            sDumpTimes.removeLast();
+        }
+        try {
+            sDumpTimes.addFirst(System.currentTimeMillis());
+        } catch (IllegalStateException e) {
+            Log.w(TAG, "Failed to note dump time -- full");
+        }
+    }
+
     /**
      * Returns a copy of callIdToInfo. Use only for testing.
      */
diff --git a/src/com/android/server/telecom/AsyncRingtonePlayer.java b/src/com/android/server/telecom/AsyncRingtonePlayer.java
index 0940429..439eb63 100644
--- a/src/com/android/server/telecom/AsyncRingtonePlayer.java
+++ b/src/com/android/server/telecom/AsyncRingtonePlayer.java
@@ -170,6 +170,10 @@
             handleRepeat();
         } else {
             mRingtone.setLooping(true);
+            if (mRingtone.isPlaying()) {
+                Log.d(this, "Ringtone already playing.");
+                return;
+            }
             mRingtone.play();
             Log.i(this, "Play ringtone, looping.");
         }
diff --git a/src/com/android/server/telecom/BluetoothHeadsetProxy.java b/src/com/android/server/telecom/BluetoothHeadsetProxy.java
index 0f492df..a43b3cd 100644
--- a/src/com/android/server/telecom/BluetoothHeadsetProxy.java
+++ b/src/com/android/server/telecom/BluetoothHeadsetProxy.java
@@ -43,9 +43,10 @@
     }
 
     public void phoneStateChanged(int numActive, int numHeld, int callState, String number,
-            int type) {
+            int type, String name) {
 
-        mBluetoothHeadset.phoneStateChanged(numActive, numHeld, callState, number, type);
+        mBluetoothHeadset.phoneStateChanged(numActive, numHeld, callState, number, type,
+            name);
     }
 
     public List<BluetoothDevice> getConnectedDevices() {
@@ -83,4 +84,4 @@
     public boolean isInbandRingingEnabled() {
         return mBluetoothHeadset.isInbandRingingEnabled();
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java b/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
index 804909c..ff358d5 100644
--- a/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
+++ b/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
@@ -514,8 +514,6 @@
                 mCallsManager.disconnectCall(activeCall);
                 if (ringingCall != null) {
                     mCallsManager.answerCall(ringingCall, VideoProfile.STATE_AUDIO_ONLY);
-                } else if (heldCall != null) {
-                    mCallsManager.unholdCall(heldCall);
                 }
                 return true;
             }
@@ -708,11 +706,16 @@
 
         String ringingAddress = null;
         int ringingAddressType = 128;
+        String ringingName = null;
         if (ringingCall != null && ringingCall.getHandle() != null) {
             ringingAddress = ringingCall.getHandle().getSchemeSpecificPart();
             if (ringingAddress != null) {
                 ringingAddressType = PhoneNumberUtils.toaFromString(ringingAddress);
             }
+            ringingName = ringingCall.getCallerDisplayName();
+            if (TextUtils.isEmpty(ringingName)) {
+                ringingName = ringingCall.getName();
+            }
         }
         if (ringingAddress == null) {
             ringingAddress = "";
@@ -784,18 +787,21 @@
                         "numHeld %s, " +
                         "callState %s, " +
                         "ringing number %s, " +
-                        "ringing type %s",
+                        "ringing type %s, " +
+                        "ringing name %s",
                         mNumActiveCalls,
                         mNumHeldCalls,
                         CALL_STATE_DIALING,
                         Log.pii(mRingingAddress),
-                        mRingingAddressType);
+                        mRingingAddressType,
+                        Log.pii(ringingName));
                 mBluetoothHeadset.phoneStateChanged(
                         mNumActiveCalls,
                         mNumHeldCalls,
                         CALL_STATE_DIALING,
                         mRingingAddress,
-                        mRingingAddressType);
+                        mRingingAddressType,
+                        ringingName);
             }
 
             Log.i(TAG, "updateHeadsetWithCallState " +
@@ -803,19 +809,22 @@
                     "numHeld %s, " +
                     "callState %s, " +
                     "ringing number %s, " +
-                    "ringing type %s",
+                    "ringing type %s, " +
+                    "ringing name %s",
                     mNumActiveCalls,
                     mNumHeldCalls,
                     mBluetoothCallState,
                     Log.pii(mRingingAddress),
-                    mRingingAddressType);
+                    mRingingAddressType,
+                    Log.pii(ringingName));
 
             mBluetoothHeadset.phoneStateChanged(
                     mNumActiveCalls,
                     mNumHeldCalls,
                     mBluetoothCallState,
                     mRingingAddress,
-                    mRingingAddressType);
+                    mRingingAddressType,
+                    ringingName);
 
             mHeadsetUpdatedRecently = true;
         }
@@ -875,6 +884,7 @@
                 return CALL_STATE_HELD;
 
             case CallState.RINGING:
+            case CallState.ANSWERED:
                 if (isForegroundCall) {
                     return CALL_STATE_INCOMING;
                 } else {
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index bc20d1c..e4f2f44 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -50,6 +50,7 @@
 import android.text.TextUtils;
 import android.util.StatsLog;
 import android.os.UserHandle;
+import android.widget.Toast;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telecom.IVideoProvider;
@@ -130,8 +131,10 @@
         void onConnectionManagerPhoneAccountChanged(Call call);
         void onPhoneAccountChanged(Call call);
         void onConferenceableCallsChanged(Call call);
+        void onConferenceStateChanged(Call call, boolean isConference);
         boolean onCanceledViaNewOutgoingCallBroadcast(Call call, long disconnectionTimeout);
         void onHoldToneRequested(Call call);
+        void onCallHoldFailed(Call call);
         void onConnectionEvent(Call call, String event, Bundle extras);
         void onExternalCallChanged(Call call, boolean isExternalCall);
         void onRttInitiationFailure(Call call, int reason);
@@ -198,12 +201,16 @@
         @Override
         public void onConferenceableCallsChanged(Call call) {}
         @Override
+        public void onConferenceStateChanged(Call call, boolean isConference) {}
+        @Override
         public boolean onCanceledViaNewOutgoingCallBroadcast(Call call, long disconnectionTimeout) {
             return false;
         }
         @Override
         public void onHoldToneRequested(Call call) {}
         @Override
+        public void onCallHoldFailed(Call call) {}
+        @Override
         public void onConnectionEvent(Call call, String event, Bundle extras) {}
         @Override
         public void onExternalCallChanged(Call call, boolean isExternalCall) {}
@@ -246,7 +253,7 @@
     /**
      * The post-dial digits that were dialed after the network portion of the number
      */
-    private final String mPostDialDigits;
+    private String mPostDialDigits;
 
     /**
      * The secondary line number that an incoming call has been received on if the SIM subscription
@@ -414,7 +421,7 @@
     private final TelecomSystem.SyncRoot mLock;
     private final String mId;
     private String mConnectionId;
-    private Analytics.CallInfo mAnalytics;
+    private Analytics.CallInfo mAnalytics = new Analytics.CallInfo();
     private char mPlayingDtmfTone;
 
     private boolean mWasConferencePreviouslyMerged = false;
@@ -461,7 +468,7 @@
      * Indicates whether the {@link PhoneAccount} associated with this call supports video calling.
      * {@code True} if the phone account supports video calling, {@code false} otherwise.
      */
-    private boolean mIsVideoCallingSupported = false;
+    private boolean mIsVideoCallingSupportedByPhoneAccount = false;
 
     private PhoneNumberUtilsAdapter mPhoneNumberUtilsAdapter;
 
@@ -523,18 +530,24 @@
     private int mHandoverState = HandoverState.HANDOVER_NONE;
 
     /**
+     * Indicates whether this call is using one of the
+     * {@link com.android.server.telecom.callfiltering.IncomingCallFilter.CallFilter} modules.
+     */
+    private boolean mIsUsingCallFiltering = false;
+
+    /**
      * Persists the specified parameters and initializes the new instance.
-     *  @param context The context.
+     * @param context The context.
      * @param repository The connection service repository.
      * @param handle The handle to dial.
      * @param gatewayInfo Gateway information to use for the call.
      * @param connectionManagerPhoneAccountHandle Account to use for the service managing the call.
-*         This account must be one that was registered with the
-*         {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} flag.
+     *         This account must be one that was registered with the
+     *           {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} flag.
      * @param targetPhoneAccountHandle Account information to use for the call. This account must be
-*         one that was registered with the {@link PhoneAccount#CAPABILITY_CALL_PROVIDER} flag.
+     *         one that was registered with the {@link PhoneAccount#CAPABILITY_CALL_PROVIDER} flag.
      * @param callDirection one of CALL_DIRECTION_INCOMING, CALL_DIRECTION_OUTGOING,
-*         or CALL_DIRECTION_UNKNOWN.
+     *         or CALL_DIRECTION_UNKNOWN.
      * @param shouldAttachToExistingConnection Set to true to attach the call to an existing
      * @param clockProxy
      */
@@ -544,8 +557,6 @@
             CallsManager callsManager,
             TelecomSystem.SyncRoot lock,
             ConnectionServiceRepository repository,
-            ContactsAsyncHelper contactsAsyncHelper,
-            CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory,
             PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
             Uri handle,
             GatewayInfo gatewayInfo,
@@ -574,14 +585,13 @@
         mShouldAttachToExistingConnection = shouldAttachToExistingConnection
                 || callDirection == CALL_DIRECTION_INCOMING;
         maybeLoadCannedSmsResponses();
-        mAnalytics = new Analytics.CallInfo();
         mClockProxy = clockProxy;
         mCreationTimeMillis = mClockProxy.currentTimeMillis();
     }
 
     /**
      * Persists the specified parameters and initializes the new instance.
-     *  @param context The context.
+     * @param context The context.
      * @param repository The connection service repository.
      * @param handle The handle to dial.
      * @param gatewayInfo Gateway information to use for the call.
@@ -603,8 +613,6 @@
             CallsManager callsManager,
             TelecomSystem.SyncRoot lock,
             ConnectionServiceRepository repository,
-            ContactsAsyncHelper contactsAsyncHelper,
-            CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory,
             PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
             Uri handle,
             GatewayInfo gatewayInfo,
@@ -616,8 +624,8 @@
             long connectTimeMillis,
             long connectElapsedTimeMillis,
             ClockProxy clockProxy) {
-        this(callId, context, callsManager, lock, repository, contactsAsyncHelper,
-                callerInfoAsyncQueryFactory, phoneNumberUtilsAdapter, handle, gatewayInfo,
+        this(callId, context, callsManager, lock, repository,
+                phoneNumberUtilsAdapter, handle, gatewayInfo,
                 connectionManagerPhoneAccountHandle, targetPhoneAccountHandle, callDirection,
                 shouldAttachToExistingConnection, isConference, clockProxy);
 
@@ -637,6 +645,10 @@
     }
 
     public void initAnalytics() {
+        initAnalytics(null);
+    }
+
+    public void initAnalytics(String callingPackage) {
         int analyticsDirection;
         switch (mCallDirection) {
             case CALL_DIRECTION_OUTGOING:
@@ -651,7 +663,8 @@
                 analyticsDirection = Analytics.UNKNOWN_DIRECTION;
         }
         mAnalytics = Analytics.initiateCallAnalytics(mId, analyticsDirection);
-        Log.addEvent(this, LogUtils.Events.CREATED);
+        mAnalytics.setCallIsEmergency(mIsEmergencyCall);
+        Log.addEvent(this, LogUtils.Events.CREATED, callingPackage);
     }
 
     public Analytics.CallInfo getAnalytics() {
@@ -666,6 +679,7 @@
             mCallerInfo.cachedPhotoIcon = null;
             mCallerInfo.cachedPhoto = null;
         }
+        closeRttStreams();
 
         Log.addEvent(this, LogUtils.Events.DESTROYED);
     }
@@ -869,15 +883,17 @@
      * (see {@link CallState}), in practice those expectations break down when cellular systems
      * misbehave and they do this very often. The result is that we do not enforce state transitions
      * and instead keep the code resilient to unexpected state changes.
+     * @return true indicates if setState succeeded in setting the state to newState,
+     * else it is failed, and the call is still in its original state.
      */
-    public void setState(int newState, String tag) {
+    public boolean setState(int newState, String tag) {
         if (mState != newState) {
             Log.v(this, "setState %s -> %s", mState, newState);
 
             if (newState == CallState.DISCONNECTED && shouldContinueProcessingAfterDisconnect()) {
                 Log.w(this, "continuing processing disconnected call with another service");
                 mCreateConnectionProcessor.continueProcessingIfPossible(this, mDisconnectCause);
-                return;
+                return false;
             }
 
             updateVideoHistoryViaState(mState, newState);
@@ -938,6 +954,9 @@
                 case CallState.RINGING:
                     event = LogUtils.Events.SET_RINGING;
                     break;
+                case CallState.ANSWERED:
+                    event = LogUtils.Events.SET_ANSWERED;
+                    break;
             }
             if (event != null) {
                 // The string data should be just the tag.
@@ -953,6 +972,7 @@
             StatsLog.write(StatsLog.CALL_STATE_CHANGED, newState, statsdDisconnectCause,
                     isSelfManaged(), isExternalCall());
         }
+        return true;
     }
 
     void setRingbackRequested(boolean ringbackRequested) {
@@ -979,6 +999,10 @@
         return mPostDialDigits;
     }
 
+    public void clearPostDialDigits() {
+        mPostDialDigits = null;
+    }
+
     public String getViaNumber() {
         return mViaNumber;
     }
@@ -1021,6 +1045,7 @@
                 mIsEmergencyCall = mHandle != null &&
                         mPhoneNumberUtilsAdapter.isLocalEmergencyNumber(mContext,
                                 mHandle.getSchemeSpecificPart());
+                mAnalytics.setCallIsEmergency(mIsEmergencyCall);
             }
             startCallerInfoLookup();
             for (Listener l : mListeners) {
@@ -1079,12 +1104,23 @@
         return mDisconnectCause;
     }
 
+    /**
+     * @return {@code true} if this is an outgoing call to emergency services. An outgoing call is
+     * identified as an emergency call by the dialer phone number.
+     */
     @VisibleForTesting
     public boolean isEmergencyCall() {
         return mIsEmergencyCall;
     }
 
     /**
+     * @return {@code true} if the network has identified this call as an emergency call.
+     */
+    public boolean isNetworkIdentifiedEmergencyCall() {
+        return hasProperty(Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL);
+    }
+
+    /**
      * @return The original handle this call is associated with. In-call services should use this
      * handle when indicating in their UI the handle that is being called.
      */
@@ -1205,8 +1241,36 @@
         return mUseCallRecordingTone;
     }
 
-    public boolean isVideoCallingSupported() {
-        return mIsVideoCallingSupported;
+    /**
+     * @return {@code true} if the {@link Call}'s {@link #getTargetPhoneAccount()} supports video.
+     */
+    public boolean isVideoCallingSupportedByPhoneAccount() {
+        return mIsVideoCallingSupportedByPhoneAccount;
+    }
+
+    /**
+     * Sets whether video calling is supported by the current phone account. Since video support
+     * can change during a call, this method facilitates updating call video state.
+     * @param isVideoCallingSupported Sets whether video calling is supported.
+     */
+    public void setVideoCallingSupportedByPhoneAccount(boolean isVideoCallingSupported) {
+        if (mIsVideoCallingSupportedByPhoneAccount == isVideoCallingSupported) {
+            return;
+        }
+        Log.i(this, "setVideoCallingSupportedByPhoneAccount: isSupp=%b", isVideoCallingSupported);
+        mIsVideoCallingSupportedByPhoneAccount = isVideoCallingSupported;
+
+        // Force an update of the connection capabilities so that the dialer is informed of the new
+        // video capabilities based on the phone account's support for video.
+        setConnectionCapabilities(getConnectionCapabilities(), true /* force */);
+    }
+
+    /**
+     * @return {@code true} if the {@link Call} locally supports video.
+     */
+    public boolean isLocallyVideoCapable() {
+        return (getConnectionCapabilities() & Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)
+                == Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL;
     }
 
     public boolean isSelfManaged() {
@@ -1308,16 +1372,16 @@
         if (mTargetPhoneAccountHandle == null) {
             // If no target phone account handle is specified, assume we can potentially perform a
             // video call; once the phone account is set, we can confirm that it is video capable.
-            mIsVideoCallingSupported = true;
+            mIsVideoCallingSupportedByPhoneAccount = true;
             Log.d(this, "checkIfVideoCapable: no phone account selected; assume video capable.");
             return;
         }
         PhoneAccount phoneAccount =
                 phoneAccountRegistrar.getPhoneAccountUnchecked(mTargetPhoneAccountHandle);
-        mIsVideoCallingSupported = phoneAccount != null && phoneAccount.hasCapabilities(
-                    PhoneAccount.CAPABILITY_VIDEO_CALLING);
+        mIsVideoCallingSupportedByPhoneAccount = phoneAccount != null &&
+                phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING);
 
-        if (!mIsVideoCallingSupported && VideoProfile.isVideo(getVideoState())) {
+        if (!mIsVideoCallingSupportedByPhoneAccount && VideoProfile.isVideo(getVideoState())) {
             // The PhoneAccount for the Call was set to one which does not support video calling,
             // and the current call is configured to be a video call; downgrade to audio-only.
             setVideoState(VideoProfile.STATE_AUDIO_ONLY);
@@ -1398,7 +1462,15 @@
         return mConnectTimeMillis;
     }
 
-    int getConnectionCapabilities() {
+    public void setConnectTimeMillis(long connectTimeMillis) {
+        mConnectTimeMillis = connectTimeMillis;
+    }
+
+    public void setConnectElapsedTimeMillis(long connectElapsedTimeMillis) {
+        mConnectElapsedTimeMillis = connectElapsedTimeMillis;
+    }
+
+    public int getConnectionCapabilities() {
         return mConnectionCapabilities;
     }
 
@@ -1406,7 +1478,7 @@
         return mConnectionProperties;
     }
 
-    void setConnectionCapabilities(int connectionCapabilities) {
+    public void setConnectionCapabilities(int connectionCapabilities) {
         setConnectionCapabilities(connectionCapabilities, false /* forceUpdate */);
     }
 
@@ -1416,12 +1488,12 @@
         if (forceUpdate || mConnectionCapabilities != connectionCapabilities) {
             // If the phone account does not support video calling, and the connection capabilities
             // passed in indicate that the call supports video, remove those video capabilities.
-            if (!isVideoCallingSupported() && doesCallSupportVideo(connectionCapabilities)) {
+            if (!isVideoCallingSupportedByPhoneAccount()
+                    && doesCallSupportVideo(connectionCapabilities)) {
                 Log.w(this, "setConnectionCapabilities: attempt to set connection as video " +
                         "capable when not supported by the phone account.");
                 connectionCapabilities = removeVideoCapabilities(connectionCapabilities);
             }
-
             int previousCapabilities = mConnectionCapabilities;
             mConnectionCapabilities = connectionCapabilities;
             for (Listener l : mListeners) {
@@ -1437,7 +1509,7 @@
         }
     }
 
-    void setConnectionProperties(int connectionProperties) {
+    public void setConnectionProperties(int connectionProperties) {
         Log.v(this, "setConnectionProperties: %s", Connection.propertiesToString(
                 connectionProperties));
 
@@ -1852,7 +1924,7 @@
         // Check to verify that the call is still in the ringing state. A call can change states
         // between the time the user hits 'answer' and Telecom receives the command.
         if (isRinging("answer")) {
-            if (!isVideoCallingSupported() && VideoProfile.isVideo(videoState)) {
+            if (!isVideoCallingSupportedByPhoneAccount() && VideoProfile.isVideo(videoState)) {
                 // Video calling is not supported, yet the InCallService is attempting to answer as
                 // video.  We will simply answer as audio-only.
                 videoState = VideoProfile.STATE_AUDIO_ONLY;
@@ -1979,6 +2051,7 @@
         switch (mState) {
             case CallState.NEW:
             case CallState.RINGING:
+            case CallState.ANSWERED:
             case CallState.DISCONNECTED:
             case CallState.ABORTED:
                 return false;
@@ -2007,7 +2080,7 @@
      * @param source The source of the extras addition.
      * @param extras The extras.
      */
-    void putExtras(int source, Bundle extras) {
+    public void putExtras(int source, Bundle extras) {
         if (extras == null) {
             return;
         }
@@ -2231,10 +2304,20 @@
     public void sendCallEvent(String event, int targetSdkVer, Bundle extras) {
         if (mConnectionService != null) {
             if (android.telecom.Call.EVENT_REQUEST_HANDOVER.equals(event)) {
-                if (targetSdkVer > Build.VERSION_CODES.O_MR1) {
+                if (targetSdkVer > Build.VERSION_CODES.P) {
                     Log.e(this, new Exception(), "sendCallEvent failed. Use public api handoverTo" +
-                            " for API > 27(O-MR1)");
-                    // TODO: Add "return" after DUO team adds new API support for handover
+                            " for API > 28(P)");
+                    // Event-based Handover APIs are deprecated, so inform the user.
+                    mHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            Toast.makeText(mContext, "WARNING: Event-based handover APIs are deprecated "
+                                            + "and will no longer function in Android Q.",
+                                    Toast.LENGTH_LONG).show();
+                        }
+                    });
+
+                    // Uncomment and remove toast at feature complete: return;
                 }
 
                 // Handover requests are targeted at Telecom, not the ConnectionService.
@@ -2415,7 +2498,7 @@
      * networks at least), so we still enable this feature even though
      * SMSes to that number will silently fail.
      */
-    boolean isRespondViaSmsCapable() {
+    public boolean isRespondViaSmsCapable() {
         if (mState != CallState.RINGING) {
             return false;
         }
@@ -2755,7 +2838,7 @@
     public void setVideoState(int videoState) {
         // If the phone account associated with this call does not support video calling, then we
         // will automatically set the video state to audio-only.
-        if (!isVideoCallingSupported()) {
+        if (!isVideoCallingSupportedByPhoneAccount()) {
             Log.d(this, "setVideoState: videoState=%s defaulted to audio (video not supported)",
                     VideoProfile.videoStateToString(videoState));
             videoState = VideoProfile.STATE_AUDIO_ONLY;
@@ -2954,6 +3037,10 @@
             for (Listener l : mListeners) {
                 l.onHoldToneRequested(this);
             }
+        } else if (Connection.EVENT_CALL_HOLD_FAILED.equals(event)) {
+            for (Listener l : mListeners) {
+                l.onCallHoldFailed(this);
+            }
         } else {
             for (Listener l : mListeners) {
                 l.onConnectionEvent(this, event, extras);
@@ -3046,15 +3133,29 @@
     }
 
     /**
+     * Sets whether this {@link Call} is a conference or not.
+     * @param isConference
+     */
+    public void setConferenceState(boolean isConference) {
+        mIsConference = isConference;
+        Log.addEvent(this, LogUtils.Events.CONF_STATE_CHANGED, "isConference=" + isConference);
+        // Ultimately CallsManager needs to know so it can update the "add call" state and inform
+        // the UI to update itself.
+        for (Listener l : mListeners) {
+            l.onConferenceStateChanged(this, isConference);
+        }
+    }
+
+    /**
      * Sets the video history based on the state and state transitions of the call. Always add the
      * current video state to the video state history during a call transition except for the
-     * transitions DIALING->ACTIVE and RINGING->ACTIVE. In these cases, clear the history. If a
+     * transitions DIALING->ACTIVE and RINGING->ANSWERED. In these cases, clear the history. If a
      * call starts dialing/ringing as a VT call and gets downgraded to audio, we need to record
      * the history as an audio call.
      */
     private void updateVideoHistoryViaState(int oldState, int newState) {
-        if ((oldState == CallState.DIALING || oldState == CallState.RINGING)
-                && newState == CallState.ACTIVE) {
+        if ((oldState == CallState.DIALING && newState == CallState.ACTIVE)
+                || (oldState == CallState.RINGING && newState == CallState.ANSWERED)) {
             mVideoStateHistory = mVideoState;
         }
 
@@ -3069,4 +3170,22 @@
     boolean wasHighDefAudio() {
         return mWasHighDefAudio;
     }
+
+    public void setIsUsingCallFiltering(boolean isUsingCallFiltering) {
+        mIsUsingCallFiltering = isUsingCallFiltering;
+    }
+
+    /**
+     * When upgrading a call to video via
+     * {@link VideoProviderProxy#onSendSessionModifyRequest(VideoProfile, VideoProfile)}, if the
+     * upgrade is from audio to video, potentially auto-engage the speakerphone.
+     * @param newVideoState The proposed new video state for the call.
+     */
+    public void maybeEnableSpeakerForVideoUpgrade(@VideoProfile.VideoState int newVideoState) {
+        if (mCallsManager.isSpeakerphoneAutoEnabledForVideoCalls(newVideoState)) {
+            Log.i(this, "maybeEnableSpeakerForVideoCall; callId=%s, auto-enable speaker for call"
+                            + " upgraded to video.");
+            mCallsManager.setAudioRoute(CallAudioState.ROUTE_SPEAKER, null);
+        }
+    }
 }
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index 56f8db9..7e4c3ba 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -105,11 +105,10 @@
         Log.d(LOG_TAG, "Call state changed for TC@%s: %s -> %s", call.getId(),
                 CallState.toString(oldState), CallState.toString(newState));
 
-        for (int i = 0; i < mCallStateToCalls.size(); i++) {
-            mCallStateToCalls.valueAt(i).remove(call);
-        }
-        if (mCallStateToCalls.get(newState) != null) {
-            mCallStateToCalls.get(newState).add(call);
+        removeCallFromAllBins(call);
+        HashSet<Call> newBinForCall = getBinForCall(call);
+        if (newBinForCall != null) {
+            newBinForCall.add(call);
         }
 
         updateForegroundCall();
@@ -148,8 +147,9 @@
         Log.d(LOG_TAG, "Call added with id TC@%s in state %s", call.getId(),
                 CallState.toString(call.getState()));
 
-        if (mCallStateToCalls.get(call.getState()) != null) {
-            mCallStateToCalls.get(call.getState()).add(call);
+        HashSet<Call> newBinForCall = getBinForCall(call);
+        if (newBinForCall != null) {
+            newBinForCall.add(call);
         }
         updateForegroundCall();
         mCalls.add(call);
@@ -168,9 +168,7 @@
         Log.d(LOG_TAG, "Call removed with id TC@%s in state %s", call.getId(),
                 CallState.toString(call.getState()));
 
-        for (int i = 0; i < mCallStateToCalls.size(); i++) {
-            mCallStateToCalls.valueAt(i).remove(call);
-        }
+        removeCallFromAllBins(call);
 
         updateForegroundCall();
         mCalls.remove(call);
@@ -226,24 +224,6 @@
             return;
         }
 
-        // This is called after the UI answers the call, but before the connection service
-        // sets the call to active. Only thing to handle for mode here is the audio speedup thing.
-
-        if (call.can(android.telecom.Call.Details.CAPABILITY_SPEED_UP_MT_AUDIO)) {
-            if (mForegroundCall == call) {
-                Log.i(LOG_TAG, "Invoking the MT_AUDIO_SPEEDUP mechanism. Transitioning into " +
-                        "an active in-call audio state before connection service has " +
-                        "connected the call.");
-                if (mCallStateToCalls.get(call.getState()) != null) {
-                    mCallStateToCalls.get(call.getState()).remove(call);
-                }
-                mActiveDialingOrConnectingCalls.add(call);
-                mCallAudioModeStateMachine.sendMessageWithArgs(
-                        CallAudioModeStateMachine.MT_AUDIO_SPEEDUP_FOR_RINGING_CALL,
-                        makeArgsForModeStateMachine());
-            }
-        }
-
         // Turn off mute when a new incoming call is answered iff it's not a handover.
         if (!call.isHandoverInProgress()) {
             mute(false /* shouldMute */);
@@ -325,10 +305,7 @@
             onCallAdded(call);
         } else {
             // The call joined a conference, so stop tracking it.
-            if (mCallStateToCalls.get(call.getState()) != null) {
-                mCallStateToCalls.get(call.getState()).remove(call);
-            }
-
+            removeCallFromAllBins(call);
             updateForegroundCall();
             mCalls.remove(call);
         }
@@ -469,9 +446,9 @@
     }
 
     @VisibleForTesting
-    public void startCallWaiting() {
+    public void startCallWaiting(String reason) {
         if (mRingingCalls.size() == 1) {
-            mRinger.startCallWaiting(mRingingCalls.iterator().next());
+            mRinger.startCallWaiting(mRingingCalls.iterator().next(), reason);
         }
     }
 
@@ -557,6 +534,7 @@
                 onCallLeavingActiveDialingOrConnecting();
                 break;
             case CallState.RINGING:
+            case CallState.ANSWERED:
                 onCallLeavingRinging();
                 break;
             case CallState.ON_HOLD:
@@ -591,6 +569,11 @@
                 onCallEnteringActiveDialingOrConnecting();
                 playRingbackForCall(call);
                 break;
+            case CallState.ANSWERED:
+                if (call.can(android.telecom.Call.Details.CAPABILITY_SPEED_UP_MT_AUDIO)) {
+                    onCallEnteringActiveDialingOrConnecting();
+                }
+                break;
         }
     }
 
@@ -681,6 +664,24 @@
                 Log.createSubsession());
     }
 
+    private HashSet<Call> getBinForCall(Call call) {
+        if (call.getState() == CallState.ANSWERED) {
+            // If the call has the speed-up-mt-audio capability, treat answered state as active
+            // for audio purposes.
+            if (call.can(android.telecom.Call.Details.CAPABILITY_SPEED_UP_MT_AUDIO)) {
+                return mActiveDialingOrConnectingCalls;
+            }
+            return mRingingCalls;
+        }
+        return mCallStateToCalls.get(call.getState());
+    }
+
+    private void removeCallFromAllBins(Call call) {
+        for (int i = 0; i < mCallStateToCalls.size(); i++) {
+            mCallStateToCalls.valueAt(i).remove(call);
+        }
+    }
+
     private void playToneForDisconnectedCall(Call call) {
         // If this call is being disconnected as a result of being handed over to another call,
         // we will not play a disconnect tone.
@@ -727,9 +728,11 @@
             Log.d(this, "Found a disconnected call with tone to play %d.", toneToPlay);
 
             if (toneToPlay != InCallTonePlayer.TONE_INVALID) {
-                mPlayerFactory.createPlayer(toneToPlay).startTone();
-                mCallsManager.onDisconnectedTonePlaying(true);
-                mIsDisconnectedTonePlaying = true;
+                boolean didToneStart = mPlayerFactory.createPlayer(toneToPlay).startTone();
+                if (didToneStart) {
+                    mCallsManager.onDisconnectedTonePlaying(true);
+                    mIsDisconnectedTonePlaying = true;
+                }
             }
         }
     }
diff --git a/src/com/android/server/telecom/CallAudioModeStateMachine.java b/src/com/android/server/telecom/CallAudioModeStateMachine.java
index 716f23a..42a1d36 100644
--- a/src/com/android/server/telecom/CallAudioModeStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioModeStateMachine.java
@@ -29,6 +29,13 @@
 import com.android.internal.util.StateMachine;
 
 public class CallAudioModeStateMachine extends StateMachine {
+    public static class Factory {
+        public CallAudioModeStateMachine create(SystemStateHelper systemStateHelper,
+                AudioManager am) {
+            return new CallAudioModeStateMachine(systemStateHelper, am);
+        }
+    }
+
     public static class MessageArgs {
         public boolean hasActiveOrDialingCalls;
         public boolean hasRingingCalls;
@@ -80,7 +87,6 @@
     public static final int NEW_ACTIVE_OR_DIALING_CALL = 2001;
     public static final int NEW_RINGING_CALL = 2002;
     public static final int NEW_HOLDING_CALL = 2003;
-    public static final int MT_AUDIO_SPEEDUP_FOR_RINGING_CALL = 2004;
 
     public static final int TONE_STARTED_PLAYING = 3001;
     public static final int TONE_STOPPED_PLAYING = 3002;
@@ -103,7 +109,6 @@
         put(NEW_ACTIVE_OR_DIALING_CALL, "NEW_ACTIVE_OR_DIALING_CALL");
         put(NEW_RINGING_CALL, "NEW_RINGING_CALL");
         put(NEW_HOLDING_CALL, "NEW_HOLDING_CALL");
-        put(MT_AUDIO_SPEEDUP_FOR_RINGING_CALL, "MT_AUDIO_SPEEDUP_FOR_RINGING_CALL");
         put(TONE_STARTED_PLAYING, "TONE_STARTED_PLAYING");
         put(TONE_STOPPED_PLAYING, "TONE_STOPPED_PLAYING");
         put(FOREGROUND_VOIP_MODE_CHANGE, "FOREGROUND_VOIP_MODE_CHANGE");
@@ -273,15 +278,6 @@
                             " Args are: " + args.toString());
                     transitionTo(mOtherFocusState);
                     return HANDLED;
-                case MT_AUDIO_SPEEDUP_FOR_RINGING_CALL:
-                    // This happens when an IMS call is answered by the in-call UI. Special case
-                    // that we have to deal with for some reason.
-
-                    // The IMS audio routing may be via modem or via RTP stream. In case via RTP
-                    // stream, the state machine should transit to mVoipCallFocusState.
-                    transitionTo(args.foregroundCallIsVoip
-                            ? mVoipCallFocusState : mSimCallFocusState);
-                    return HANDLED;
                 case RINGER_MODE_CHANGE: {
                     Log.i(LOG_TAG, "RINGING state, received RINGER_MODE_CHANGE");
                     tryStartRinging();
@@ -338,7 +334,7 @@
                     return HANDLED;
                 case NEW_RINGING_CALL:
                     // Don't make a call ring over an active call, but do play a call waiting tone.
-                    mCallAudioManager.startCallWaiting();
+                    mCallAudioManager.startCallWaiting("call already active");
                     return HANDLED;
                 case NEW_HOLDING_CALL:
                     // Don't do anything now. Putting an active call on hold will be handled when
@@ -393,7 +389,7 @@
                     return HANDLED;
                 case NEW_RINGING_CALL:
                     // Don't make a call ring over an active call, but do play a call waiting tone.
-                    mCallAudioManager.startCallWaiting();
+                    mCallAudioManager.startCallWaiting("call already active");
                     return HANDLED;
                 case NEW_HOLDING_CALL:
                     // Don't do anything now. Putting an active call on hold will be handled when
@@ -447,8 +443,14 @@
                             ? mVoipCallFocusState : mSimCallFocusState);
                     return HANDLED;
                 case NEW_RINGING_CALL:
-                    // Apparently this is current behavior. Should this be the case?
-                    transitionTo(mRingingFocusState);
+                    // TODO: consider whether to move this into MessageArgs if more things start
+                    // to use it.
+                    if (args.hasHoldingCalls && mSystemStateHelper.isDeviceAtEar()) {
+                        mCallAudioManager.startCallWaiting(
+                                "Device is at ear with held call");
+                    } else {
+                        transitionTo(mRingingFocusState);
+                    }
                     return HANDLED;
                 case NEW_HOLDING_CALL:
                     // Do nothing.
@@ -475,14 +477,17 @@
     private final BaseState mOtherFocusState = new OtherFocusState();
 
     private final AudioManager mAudioManager;
+    private final SystemStateHelper mSystemStateHelper;
     private CallAudioManager mCallAudioManager;
 
     private int mMostRecentMode;
     private boolean mIsInitialized = false;
 
-    public CallAudioModeStateMachine(AudioManager audioManager) {
+    public CallAudioModeStateMachine(SystemStateHelper systemStateHelper,
+            AudioManager audioManager) {
         super(CallAudioModeStateMachine.class.getSimpleName());
         mAudioManager = audioManager;
+        mSystemStateHelper = systemStateHelper;
         mMostRecentMode = AudioManager.MODE_NORMAL;
 
         addState(mUnfocusedState);
diff --git a/src/com/android/server/telecom/CallAudioRoutePeripheralAdapter.java b/src/com/android/server/telecom/CallAudioRoutePeripheralAdapter.java
index a871dfc..2b6ba64 100644
--- a/src/com/android/server/telecom/CallAudioRoutePeripheralAdapter.java
+++ b/src/com/android/server/telecom/CallAudioRoutePeripheralAdapter.java
@@ -75,6 +75,12 @@
                 CallAudioRouteStateMachine.BT_AUDIO_DISCONNECTED);
     }
 
+    @Override
+    public void onUnexpectedBluetoothStateChange() {
+        mCallAudioRouteStateMachine.sendMessageWithSessionInfo(
+                CallAudioRouteStateMachine.UPDATE_SYSTEM_AUDIO_ROUTE);
+    }
+
     /**
       * Updates the audio route when the headset plugged in state changes. For example, if audio is
       * being routed over speakerphone and a headset is plugged in then switch to wired headset.
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index 4274017..dcf1b27 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -71,6 +71,24 @@
  */
 public class CallAudioRouteStateMachine extends StateMachine {
 
+    public static class Factory {
+        public CallAudioRouteStateMachine create(
+                Context context,
+                CallsManager callsManager,
+                BluetoothRouteManager bluetoothManager,
+                WiredHeadsetManager wiredHeadsetManager,
+                StatusBarNotifier statusBarNotifier,
+                CallAudioManager.AudioServiceFactory audioServiceFactory,
+                int earpieceControl) {
+            return new CallAudioRouteStateMachine(context,
+                    callsManager,
+                    bluetoothManager,
+                    wiredHeadsetManager,
+                    statusBarNotifier,
+                    audioServiceFactory,
+                    earpieceControl);
+        }
+    }
     /** Values for CallAudioRouteStateMachine constructor's earPieceRouting arg. */
     public static final int EARPIECE_FORCE_DISABLED = 0;
     public static final int EARPIECE_FORCE_ENABLED  = 1;
@@ -136,7 +154,7 @@
     public static final int ACTIVE_FOCUS = 2;
     public static final int RINGING_FOCUS = 3;
 
-    /** Valid values for the argument for SWITCH_BASELINE_ROUTE */
+    /** Valid values for the first argument for SWITCH_BASELINE_ROUTE */
     public static final int NO_INCLUDE_BLUETOOTH_IN_BASELINE = 0;
     public static final int INCLUDE_BLUETOOTH_IN_BASELINE = 1;
 
@@ -290,6 +308,12 @@
                     mHasUserExplicitlyLeftBluetooth = false;
                     return NOT_HANDLED;
                 case SWITCH_FOCUS:
+                    // Perform BT hearing aid active device caching/restoration
+                    if (mAudioFocusType != NO_FOCUS && msg.arg1 == NO_FOCUS) {
+                        mBluetoothRouteManager.restoreHearingAidDevice();
+                    } else if (mAudioFocusType == NO_FOCUS && msg.arg1 != NO_FOCUS) {
+                        mBluetoothRouteManager.cacheHearingAidDevice();
+                    }
                     mAudioFocusType = msg.arg1;
                     return NOT_HANDLED;
                 default:
@@ -328,7 +352,6 @@
         public void enter() {
             super.enter();
             setSpeakerphoneOn(false);
-            setBluetoothOff();
             CallAudioState newState = new CallAudioState(mIsMuted, ROUTE_EARPIECE,
                     mAvailableRoutes, null,
                     mBluetoothRouteManager.getConnectedDevices());
@@ -523,7 +546,6 @@
         public void enter() {
             super.enter();
             setSpeakerphoneOn(false);
-            setBluetoothOff();
             CallAudioState newState = new CallAudioState(mIsMuted, ROUTE_WIRED_HEADSET,
                     mAvailableRoutes, null, mBluetoothRouteManager.getConnectedDevices());
             setSystemAudioState(newState, true);
@@ -742,6 +764,32 @@
         }
 
         @Override
+        public void handleBtInitiatedDisconnect() {
+            // There's special-case state transitioning here -- if BT tells us that
+            // something got disconnected, we don't want to disconnect BT before
+            // transitioning, since BT might be trying to connect another device in the
+            // meantime.
+            int command = calculateBaselineRouteMessage(false, false);
+            switch (command) {
+                case SWITCH_EARPIECE:
+                    transitionTo(mActiveEarpieceRoute);
+                    break;
+                case SWITCH_HEADSET:
+                    transitionTo(mActiveHeadsetRoute);
+                    break;
+                case SWITCH_SPEAKER:
+                    transitionTo(mActiveSpeakerRoute);
+                    break;
+                default:
+                    Log.w(this, "Got unexpected code " + command + " when processing a"
+                            + " BT-initiated audio disconnect");
+                    // Some fallback logic to make sure we make it off the bluetooth route.
+                    super.handleBtInitiatedDisconnect();
+                    break;
+            }
+        }
+
+        @Override
         public boolean processMessage(Message msg) {
             if (super.processMessage(msg) == HANDLED) {
                 return HANDLED;
@@ -752,6 +800,7 @@
                     // fall through
                 case SWITCH_EARPIECE:
                     if ((mAvailableRoutes & ROUTE_EARPIECE) != 0) {
+                        setBluetoothOff();
                         transitionTo(mActiveEarpieceRoute);
                     } else {
                         Log.w(this, "Ignoring switch to earpiece command. Not available.");
@@ -775,6 +824,7 @@
                     // fall through
                 case SWITCH_HEADSET:
                     if ((mAvailableRoutes & ROUTE_WIRED_HEADSET) != 0) {
+                        setBluetoothOff();
                         transitionTo(mActiveHeadsetRoute);
                     } else {
                         Log.w(this, "Ignoring switch to headset command. Not available.");
@@ -784,11 +834,13 @@
                     mHasUserExplicitlyLeftBluetooth = true;
                     // fall through
                 case SWITCH_SPEAKER:
+                    setBluetoothOff();
                     transitionTo(mActiveSpeakerRoute);
                     return HANDLED;
                 case SWITCH_FOCUS:
                     if (msg.arg1 == NO_FOCUS) {
-                        setBluetoothOff();
+                        // Only disconnect SCO audio here instead of routing away from BT entirely.
+                        mBluetoothRouteManager.disconnectSco();
                         reinitialize();
                     } else if (msg.arg1 == RINGING_FOCUS
                             && !mBluetoothRouteManager.isInbandRingingEnabled()) {
@@ -797,7 +849,7 @@
                     }
                     return HANDLED;
                 case BT_AUDIO_DISCONNECTED:
-                    sendInternalMessage(SWITCH_BASELINE_ROUTE, NO_INCLUDE_BLUETOOTH_IN_BASELINE);
+                    handleBtInitiatedDisconnect();
                     return HANDLED;
                 default:
                     return NOT_HANDLED;
@@ -975,6 +1027,10 @@
             return CallAudioState.ROUTE_BLUETOOTH;
         }
 
+        public void handleBtInitiatedDisconnect() {
+            sendInternalMessage(SWITCH_BASELINE_ROUTE, NO_INCLUDE_BLUETOOTH_IN_BASELINE);
+        }
+
         @Override
         public boolean processMessage(Message msg) {
             if (super.processMessage(msg) == HANDLED) {
@@ -989,7 +1045,7 @@
                             + " have been null while we were in BT route.");
                     return HANDLED;
                 case BT_ACTIVE_DEVICE_GONE:
-                    sendInternalMessage(SWITCH_BASELINE_ROUTE, NO_INCLUDE_BLUETOOTH_IN_BASELINE);
+                    handleBtInitiatedDisconnect();
                     mWasOnSpeaker = false;
                     return HANDLED;
                 case DISCONNECT_WIRED_HEADSET:
@@ -1023,7 +1079,6 @@
             super.enter();
             mWasOnSpeaker = true;
             setSpeakerphoneOn(true);
-            setBluetoothOff();
             CallAudioState newState = new CallAudioState(mIsMuted, ROUTE_SPEAKER,
                     mAvailableRoutes, null, mBluetoothRouteManager.getConnectedDevices());
             setSystemAudioState(newState, true);
@@ -1250,7 +1305,7 @@
      */
     private int mDeviceSupportedRoutes;
     private int mAvailableRoutes;
-    private int mAudioFocusType;
+    private int mAudioFocusType = NO_FOCUS;
     private boolean mWasOnSpeaker;
     private boolean mIsMuted;
 
@@ -1417,6 +1472,7 @@
                 }
                 return;
             case UPDATE_SYSTEM_AUDIO_ROUTE:
+                updateInternalCallAudioState();
                 updateRouteForForegroundCall();
                 resendSystemAudioState();
                 return;
@@ -1606,7 +1662,8 @@
         int supportedRouteMask = calculateSupportedRoutes() & getCurrentCallSupportedRoutes();
         final int route;
 
-        if ((supportedRouteMask & ROUTE_BLUETOOTH) != 0) {
+        if ((supportedRouteMask & ROUTE_BLUETOOTH) != 0
+                && mBluetoothRouteManager.hasBtActiveDevice()) {
             route = ROUTE_BLUETOOTH;
         } else if ((supportedRouteMask & ROUTE_WIRED_HEADSET) != 0) {
             route = ROUTE_WIRED_HEADSET;
diff --git a/src/com/android/server/telecom/CallIntentProcessor.java b/src/com/android/server/telecom/CallIntentProcessor.java
index ff3b7b2..4afa645 100644
--- a/src/com/android/server/telecom/CallIntentProcessor.java
+++ b/src/com/android/server/telecom/CallIntentProcessor.java
@@ -6,11 +6,13 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Looper;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.telecom.DefaultDialerManager;
 import android.telecom.Log;
+import android.telecom.Logging.Session;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
@@ -19,6 +21,8 @@
 import android.telephony.PhoneNumberUtils;
 import android.widget.Toast;
 
+import java.util.concurrent.CompletableFuture;
+
 /**
  * Single point of entry for all outgoing and incoming calls.
  * {@link com.android.server.telecom.components.UserCallIntentProcessor} serves as a trampoline that
@@ -28,7 +32,7 @@
 public class CallIntentProcessor {
     public interface Adapter {
         void processOutgoingCallIntent(Context context, CallsManager callsManager,
-                Intent intent);
+                Intent intent, String callingPackage);
         void processIncomingCallIntent(CallsManager callsManager, Intent intent);
         void processUnknownCallIntent(CallsManager callsManager, Intent intent);
     }
@@ -36,8 +40,9 @@
     public static class AdapterImpl implements Adapter {
         @Override
         public void processOutgoingCallIntent(Context context, CallsManager callsManager,
-                Intent intent) {
-            CallIntentProcessor.processOutgoingCallIntent(context, callsManager, intent);
+                Intent intent, String callingPackage) {
+            CallIntentProcessor.processOutgoingCallIntent(context, callsManager, intent,
+                    callingPackage);
         }
 
         @Override
@@ -73,7 +78,7 @@
         this.mCallsManager = callsManager;
     }
 
-    public void processIntent(Intent intent) {
+    public void processIntent(Intent intent, String callingPackage) {
         final boolean isUnknownCall = intent.getBooleanExtra(KEY_IS_UNKNOWN_CALL, false);
         Log.i(this, "onReceive - isUnknownCall: %s", isUnknownCall);
 
@@ -81,7 +86,7 @@
         if (isUnknownCall) {
             processUnknownCallIntent(mCallsManager, intent);
         } else {
-            processOutgoingCallIntent(mContext, mCallsManager, intent);
+            processOutgoingCallIntent(mContext, mCallsManager, intent, callingPackage);
         }
         Trace.endSection();
     }
@@ -91,11 +96,13 @@
      * Processes CALL, CALL_PRIVILEGED, and CALL_EMERGENCY intents.
      *
      * @param intent Call intent containing data about the handle to call.
+     * @param callingPackage The package which initiated the outgoing call (if known).
      */
     static void processOutgoingCallIntent(
             Context context,
             CallsManager callsManager,
-            Intent intent) {
+            Intent intent,
+            String callingPackage) {
 
         Uri handle = intent.getData();
         String scheme = handle.getScheme();
@@ -117,6 +124,12 @@
             clientExtras = new Bundle();
         }
 
+        if (intent.hasExtra(TelecomManager.EXTRA_IS_USER_INTENT_EMERGENCY_CALL)) {
+            clientExtras.putBoolean(TelecomManager.EXTRA_IS_USER_INTENT_EMERGENCY_CALL,
+                    intent.getBooleanExtra(TelecomManager.EXTRA_IS_USER_INTENT_EMERGENCY_CALL,
+                            false));
+        }
+
         // Ensure call subject is passed on to the connection service.
         if (intent.hasExtra(TelecomManager.EXTRA_CALL_SUBJECT)) {
             String callsubject = intent.getStringExtra(TelecomManager.EXTRA_CALL_SUBJECT);
@@ -133,7 +146,9 @@
             // Show the toast to warn user that it is a personal call though initiated in work
             // profile.
             if (fixedInitiatingUser) {
-                Toast.makeText(context, R.string.toast_personal_call_msg, Toast.LENGTH_LONG).show();
+                Toast.makeText(context, Looper.getMainLooper(),
+                        context.getString(R.string.toast_personal_call_msg),
+                        Toast.LENGTH_LONG).show();
             }
         } else {
             Log.i(CallIntentProcessor.class,
@@ -143,13 +158,21 @@
         UserHandle initiatingUser = intent.getParcelableExtra(KEY_INITIATING_USER);
 
         // Send to CallsManager to ensure the InCallUI gets kicked off before the broadcast returns
-        Call call = callsManager
+        CompletableFuture<Call> callFuture = callsManager
                 .startOutgoingCall(handle, phoneAccountHandle, clientExtras, initiatingUser,
-                        intent);
+                        intent, callingPackage);
 
-        if (call != null) {
-            sendNewOutgoingCallIntent(context, call, callsManager, intent);
-        }
+        final Session logSubsession = Log.createSubsession();
+        callFuture.thenAccept((call) -> {
+            if (call != null) {
+                Log.continueSession(logSubsession, "CIP.sNOCI");
+                try {
+                    sendNewOutgoingCallIntent(context, call, callsManager, intent);
+                } finally {
+                    Log.endSession();
+                }
+            }
+        });
     }
 
     static void sendNewOutgoingCallIntent(Context context, Call call, CallsManager callsManager,
@@ -164,12 +187,15 @@
         NewOutgoingCallIntentBroadcaster broadcaster = new NewOutgoingCallIntentBroadcaster(
                 context, callsManager, call, intent, callsManager.getPhoneNumberUtilsAdapter(),
                 isPrivilegedDialer);
-        final int result = broadcaster.processIntent();
-        final boolean success = result == DisconnectCause.NOT_DISCONNECTED;
 
-        if (!success && call != null) {
-            disconnectCallAndShowErrorDialog(context, call, result);
+        // If the broadcaster comes back with an immediate error, disconnect and show a dialog.
+        NewOutgoingCallIntentBroadcaster.CallDisposition disposition = broadcaster.evaluateCall();
+        if (disposition.disconnectCause != DisconnectCause.NOT_DISCONNECTED) {
+            disconnectCallAndShowErrorDialog(context, call, disposition.disconnectCause);
+            return;
         }
+
+        broadcaster.processCall(disposition);
     }
 
     /**
diff --git a/src/com/android/server/telecom/CallLogManager.java b/src/com/android/server/telecom/CallLogManager.java
index 6e71b73..23e354c 100755
--- a/src/com/android/server/telecom/CallLogManager.java
+++ b/src/com/android/server/telecom/CallLogManager.java
@@ -39,14 +39,11 @@
 // TODO: Needed for move to system service: import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.CallerInfo;
+import com.android.server.telecom.callfiltering.CallFilteringResult;
 
 import java.util.Arrays;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
 import java.util.Locale;
 import java.util.Objects;
-import java.util.Set;
-import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 /**
@@ -83,7 +80,8 @@
                 String postDialDigits, String viaNumber, int presentation, int callType,
                 int features, PhoneAccountHandle accountHandle, long creationDate,
                 long durationInMillis, Long dataUsage, UserHandle initiatingUser, boolean isRead,
-                @Nullable LogCallCompletedListener logCallCompletedListener) {
+                @Nullable LogCallCompletedListener logCallCompletedListener, int callBlockReason,
+                CharSequence callScreeningAppName, String callScreeningComponentName) {
             this.context = context;
             this.callerInfo = callerInfo;
             this.number = number;
@@ -99,6 +97,9 @@
             this.initiatingUser = initiatingUser;
             this.isRead = isRead;
             this.logCallCompletedListener = logCallCompletedListener;
+            this.callBockReason = callBlockReason;
+            this.callScreeningAppName = callScreeningAppName;
+            this.callScreeningComponentName = callScreeningComponentName;
         }
         // Since the members are accessed directly, we don't use the
         // mXxxx notation.
@@ -119,6 +120,10 @@
 
         @Nullable
         public final LogCallCompletedListener logCallCompletedListener;
+
+        public final int callBockReason;
+        public final CharSequence callScreeningAppName;
+        public final String callScreeningComponentName;
     }
 
     private static final String TAG = CallLogManager.class.getSimpleName();
@@ -151,22 +156,11 @@
                 newState == CallState.DISCONNECTED || newState == CallState.ABORTED;
         boolean isCallCanceled = isNewlyDisconnected && disconnectCause == DisconnectCause.CANCELED;
 
-        // Log newly disconnected calls only if:
-        // 1) It was not in the "choose account" phase when disconnected
-        // 2) It is a conference call
-        // 3) Call was not explicitly canceled
-        // 4) Call is not an external call
-        // 5) Call is not a self-managed call OR call is a self-managed call which has indicated it
-        //    should be logged in its PhoneAccount
-        if (isNewlyDisconnected &&
-                (oldState != CallState.SELECT_PHONE_ACCOUNT &&
-                        !call.isConference() &&
-                        !isCallCanceled) &&
-                !call.isExternalCall() &&
-                (!call.isSelfManaged() ||
-                        (call.isLoggedSelfManaged() &&
-                                (call.getHandoverState() == HandoverState.HANDOVER_NONE ||
-                                call.getHandoverState() == HandoverState.HANDOVER_COMPLETE)))) {
+        if (!isNewlyDisconnected) {
+            return;
+        }
+
+        if (shouldLogDisconnectedCall(call, oldState, isCallCanceled)) {
             int type;
             if (!call.isIncoming()) {
                 type = Calls.OUTGOING_TYPE;
@@ -182,22 +176,77 @@
             // Always show the notification for managed calls. For self-managed calls, it is up to
             // the app to show the notification, so suppress the notification when logging the call.
             boolean showNotification = !call.isSelfManaged();
-            logCall(call, type, showNotification);
+            logCall(call, type, showNotification, null /*result*/);
         }
     }
 
-    void logCall(Call call, int type, boolean showNotificationForMissedCall) {
-        if (type == Calls.MISSED_TYPE && showNotificationForMissedCall) {
-            logCall(call, Calls.MISSED_TYPE,
-                    new LogCallCompletedListener() {
-                        @Override
-                        public void onLogCompleted(@Nullable Uri uri) {
-                            mMissedCallNotifier.showMissedCallNotification(
-                                    new MissedCallNotifier.CallInfo(call));
-                        }
-                    });
+    /**
+     * Log newly disconnected calls only if all of below conditions are met:
+     * 1) Call was NOT in the "choose account" phase when disconnected
+     * 2) Call is NOT a conference call
+     * 3) Call is NOT simulating a single party conference.
+     * 4) Call was NOT explicitly canceled, except for disconnecting from a conference.
+     * 5) Call is NOT an external call
+     * 6) Call is NOT disconnected because of merging into a conference.
+     * 7) Call is NOT a self-managed call OR call is a self-managed call which has indicated it
+     *    should be logged in its PhoneAccount
+     */
+    private boolean shouldLogDisconnectedCall(Call call, int oldState, boolean isCallCanceled) {
+        // 1) "Choose account" phase when disconnected
+        if (oldState == CallState.SELECT_PHONE_ACCOUNT) {
+            return false;
+        }
+        // 2) A conference call
+        if (call.isConference()) {
+            return false;
+        }
+
+        DisconnectCause cause = call.getDisconnectCause();
+        if (isCallCanceled) {
+            // 3) No log when disconnecting to simulate a single party conference.
+            if (cause != null
+                    && DisconnectCause.REASON_EMULATING_SINGLE_CALL.equals(cause.getReason())) {
+                return false;
+            }
+            // 4) Explicitly canceled
+            // Conference children connections only have CAPABILITY_DISCONNECT_FROM_CONFERENCE.
+            // Log them when they are disconnected from conference.
+            return Connection.can(call.getConnectionCapabilities(),
+                    Connection.CAPABILITY_DISCONNECT_FROM_CONFERENCE);
+        }
+        // 5) An external call
+        if (call.isExternalCall()) {
+            return false;
+        }
+
+        // 6) Call merged into conferences.
+        if (cause != null && android.telephony.DisconnectCause.toString(
+                android.telephony.DisconnectCause.IMS_MERGED_SUCCESSFULLY)
+                .equals(cause.getReason())) {
+            return false;
+        }
+
+        boolean shouldCallSelfManagedLogged = call.isLoggedSelfManaged()
+                && (call.getHandoverState() == HandoverState.HANDOVER_NONE
+                || call.getHandoverState() == HandoverState.HANDOVER_COMPLETE);
+        // 7) Call is NOT a self-managed call OR call is a self-managed call which has indicated it
+        //    should be logged in its PhoneAccount
+        return !call.isSelfManaged() || shouldCallSelfManagedLogged;
+    }
+
+    void logCall(Call call, int type, boolean showNotificationForMissedCall, CallFilteringResult
+            result) {
+        if ((type == Calls.MISSED_TYPE || type == Calls.BLOCKED_TYPE) &&
+                showNotificationForMissedCall) {
+            logCall(call, type, new LogCallCompletedListener() {
+                @Override
+                public void onLogCompleted(@Nullable Uri uri) {
+                    mMissedCallNotifier.showMissedCallNotification(
+                            new MissedCallNotifier.CallInfo(call));
+                }
+            }, result);
         } else {
-            logCall(call, type, null);
+            logCall(call, type, null, result);
         }
     }
 
@@ -209,10 +258,13 @@
      *     {@link android.provider.CallLog.Calls#INCOMING_TYPE}
      *     {@link android.provider.CallLog.Calls#OUTGOING_TYPE}
      *     {@link android.provider.CallLog.Calls#MISSED_TYPE}
+     *     {@link android.provider.CallLog.Calls#BLOCKED_TYPE}
      * @param logCallCompletedListener optional callback called after the call is logged.
+     * @param result is generated when call type is
+     *     {@link android.provider.CallLog.Calls#BLOCKED_TYPE}.
      */
     void logCall(Call call, int callLogType,
-        @Nullable LogCallCompletedListener logCallCompletedListener) {
+        @Nullable LogCallCompletedListener logCallCompletedListener, CallFilteringResult result) {
         final long creationTime = call.getCreationTimeMillis();
         final long age = call.getAgeMillis();
 
@@ -242,10 +294,22 @@
                 (call.getConnectionProperties() & Connection.PROPERTY_ASSISTED_DIALING_USED) ==
                         Connection.PROPERTY_ASSISTED_DIALING_USED,
                 call.wasEverRttCall());
-        logCall(call.getCallerInfo(), logNumber, call.getPostDialDigits(), formattedViaNumber,
-                call.getHandlePresentation(), callLogType, callFeatures, accountHandle,
-                creationTime, age, callDataUsage, call.isEmergencyCall(), call.getInitiatingUser(),
-                call.isSelfManaged(), logCallCompletedListener);
+
+        if (callLogType == Calls.BLOCKED_TYPE) {
+            logCall(call.getCallerInfo(), logNumber, call.getPostDialDigits(), formattedViaNumber,
+                    call.getHandlePresentation(), callLogType, callFeatures, accountHandle,
+                    creationTime, age, callDataUsage, call.isEmergencyCall(),
+                    call.getInitiatingUser(), call.isSelfManaged(), logCallCompletedListener,
+                    result.mCallBlockReason, result.mCallScreeningAppName,
+                    result.mCallScreeningComponentName);
+        } else {
+            logCall(call.getCallerInfo(), logNumber, call.getPostDialDigits(), formattedViaNumber,
+                    call.getHandlePresentation(), callLogType, callFeatures, accountHandle,
+                    creationTime, age, callDataUsage, call.isEmergencyCall(),
+                    call.getInitiatingUser(), call.isSelfManaged(), logCallCompletedListener,
+                    Calls.BLOCK_REASON_NOT_BLOCKED, null /*callScreeningAppName*/,
+                    null /*callScreeningComponentName*/);
+        }
     }
 
     /**
@@ -265,6 +329,9 @@
      * @param logCallCompletedListener optional callback called after the call is logged.
      * @param initiatingUser The user the call was initiated under.
      * @param isSelfManaged {@code true} if this is a self-managed call, {@code false} otherwise.
+     * @param callBlockReason The reason why the call is blocked.
+     * @param callScreeningAppName The call screening application name which block the call.
+     * @param callScreeningComponentName The call screening component name which block the call.
      */
     private void logCall(
             CallerInfo callerInfo,
@@ -281,7 +348,10 @@
             boolean isEmergency,
             UserHandle initiatingUser,
             boolean isSelfManaged,
-            @Nullable LogCallCompletedListener logCallCompletedListener) {
+            @Nullable LogCallCompletedListener logCallCompletedListener,
+            int callBlockReason,
+            CharSequence callScreeningAppName,
+            String callScreeningComponentName) {
 
         // On some devices, to avoid accidental redialing of emergency numbers, we *never* log
         // emergency calls to the Call Log.  (This behavior is set on a per-product basis, based
@@ -314,7 +384,8 @@
             }
             AddCallArgs args = new AddCallArgs(mContext, callerInfo, number, postDialDigits,
                     viaNumber, presentation, callType, features, accountHandle, start, duration,
-                    dataUsage, initiatingUser, isRead, logCallCompletedListener);
+                    dataUsage, initiatingUser, isRead, logCallCompletedListener, callBlockReason,
+                    callScreeningAppName, callScreeningComponentName);
             logCallAsync(args);
         } else {
           Log.d(TAG, "Not adding emergency call to call log.");
@@ -475,7 +546,8 @@
             return Calls.addCall(c.callerInfo, c.context, c.number, c.postDialDigits, c.viaNumber,
                     c.presentation, c.callType, c.features, c.accountHandle, c.timestamp,
                     c.durationInSec, c.dataUsage, userToBeInserted == null,
-                    userToBeInserted, c.isRead);
+                    userToBeInserted, c.isRead, c.callBockReason, c.callScreeningAppName,
+                    c.callScreeningComponentName);
         }
 
 
diff --git a/src/com/android/server/telecom/CallScreeningServiceHelper.java b/src/com/android/server/telecom/CallScreeningServiceHelper.java
new file mode 100644
index 0000000..87c3939
--- /dev/null
+++ b/src/com/android/server/telecom/CallScreeningServiceHelper.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2018 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.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.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.telecom.CallScreeningService;
+import android.telecom.Log;
+import android.telecom.Logging.Session;
+import android.text.TextUtils;
+
+import com.android.internal.telecom.ICallScreeningAdapter;
+import com.android.internal.telecom.ICallScreeningService;
+
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Helper class for performing operations with {@link CallScreeningService}s.
+ */
+public class CallScreeningServiceHelper {
+    private static final String TAG = CallScreeningServiceHelper.class.getSimpleName();
+
+    /**
+     * Abstracts away dependency on the {@link PackageManager} required to fetch the label for an
+     * app.
+     */
+    public interface AppLabelProxy {
+        CharSequence getAppLabel(String packageName);
+    }
+
+    /**
+     * Implementation of {@link CallScreeningService} adapter AIDL; provides a means for responses
+     * from the call screening service to be handled.
+     */
+    private class CallScreeningAdapter extends ICallScreeningAdapter.Stub {
+        @Override
+        public void allowCall(String s) throws RemoteException {
+            // no-op; we don't allow this on outgoing calls.
+        }
+
+        @Override
+        public void disallowCall(String s, boolean b, boolean b1, boolean b2,
+                ComponentName componentName) throws RemoteException {
+            // no-op; we don't allow this on outgoing calls.
+        }
+    }
+
+    private final ParcelableCallUtils.Converter mParcelableCallUtilsConverter;
+    private final TelecomSystem.SyncRoot mTelecomLock;
+    private final Call mCall;
+    private final UserHandle mUserHandle;
+    private final Context mContext;
+    private final AppLabelProxy mAppLabelProxy;
+    private final Session mLoggingSession;
+    private CompletableFuture mFuture;
+    private String mPackageName;
+
+    public CallScreeningServiceHelper(Context context, TelecomSystem.SyncRoot telecomLock,
+            String packageName, ParcelableCallUtils.Converter converter,
+            UserHandle userHandle, Call call, AppLabelProxy appLabelProxy) {
+        mContext = context;
+        mTelecomLock = telecomLock;
+        mParcelableCallUtilsConverter = converter;
+        mCall = call;
+        mUserHandle = userHandle;
+        mPackageName = packageName;
+        mAppLabelProxy = appLabelProxy;
+        mLoggingSession = Log.createSubsession();
+    }
+
+    /**
+     * Builds a {@link CompletableFuture} which performs a bind to a {@link CallScreeningService}
+     * @return
+     */
+    public CompletableFuture process() {
+        Log.d(this, "process");
+        return bindAndGetCallIdentification();
+    }
+
+    public CompletableFuture bindAndGetCallIdentification() {
+        Log.d(this, "bindAndGetCallIdentification");
+        if (mPackageName == null) {
+            return CompletableFuture.completedFuture(null);
+        }
+
+        mFuture = new CompletableFuture();
+
+        ServiceConnection serviceConnection = new ServiceConnection() {
+            @Override
+            public void onServiceConnected(ComponentName name, IBinder service) {
+                ICallScreeningService screeningService =
+                        ICallScreeningService.Stub.asInterface(service);
+                Log.continueSession(mLoggingSession, "CSSH.oSC");
+                try {
+                    try {
+                        screeningService.screenCall(new CallScreeningAdapter(),
+                                mParcelableCallUtilsConverter.toParcelableCallForScreening(mCall));
+                    } catch (RemoteException e) {
+                        Log.w(CallScreeningServiceHelper.this,
+                                "Cancelling call id due to remote exception");
+                        mFuture.complete(null);
+                    }
+                } finally {
+                    Log.endSession();
+                }
+            }
+
+            @Override
+            public void onServiceDisconnected(ComponentName name) {
+                // No locking needed -- CompletableFuture only lets one thread call complete.
+                Log.continueSession(mLoggingSession, "CSSH.oSD");
+                try {
+                    if (!mFuture.isDone()) {
+                        Log.w(CallScreeningServiceHelper.this,
+                                "Cancelling outgoing call screen due to service disconnect.");
+                    }
+                    mFuture.complete(null);
+                } finally {
+                    Log.endSession();
+                }
+            }
+        };
+
+        if (!bindCallScreeningService(mContext, mUserHandle, mPackageName, serviceConnection)) {
+            Log.i(this, "bindAndGetCallIdentification - bind failed");
+            Log.addEvent(mCall, LogUtils.Events.BIND_SCREENING, mPackageName);
+            mFuture.complete(null);
+        }
+
+        // Set up a timeout so that we're not waiting forever for the caller ID information.
+        Handler handler = new Handler();
+        handler.postDelayed(() -> {
+                    // No locking needed -- CompletableFuture only lets one thread call complete.
+                    Log.continueSession(mLoggingSession, "CSSH.timeout");
+                    try {
+                        if (!mFuture.isDone()) {
+                            Log.w(TAG, "Cancelling call id process due to timeout");
+                        }
+                        mFuture.complete(null);
+                    } finally {
+                        Log.endSession();
+                    }
+                },
+                Timeouts.getCallScreeningTimeoutMillis(mContext.getContentResolver()));
+        return mFuture;
+    }
+
+    /**
+     * Binds to a {@link CallScreeningService}.
+     * @param context The current context.
+     * @param userHandle User to bind as.
+     * @param packageName Package name of the {@link CallScreeningService}.
+     * @param serviceConnection The {@link ServiceConnection} to be notified of binding.
+     * @return {@code true} if binding succeeds, {@code false} otherwise.
+     */
+    public static boolean bindCallScreeningService(Context context, UserHandle userHandle,
+            String packageName, ServiceConnection serviceConnection) {
+        if (TextUtils.isEmpty(packageName)) {
+            Log.i(TAG, "PackageName is empty. Not performing call screening.");
+            return false;
+        }
+
+        Intent intent = new Intent(CallScreeningService.SERVICE_INTERFACE)
+                .setPackage(packageName);
+        List<ResolveInfo> entries = context.getPackageManager().queryIntentServicesAsUser(
+                intent, 0, userHandle.getIdentifier());
+        if (entries.isEmpty()) {
+            Log.i(TAG, packageName + " has no call screening service defined.");
+            return false;
+        }
+
+        ResolveInfo entry = entries.get(0);
+        if (entry.serviceInfo == null) {
+            Log.w(TAG, packageName + " call screening service has invalid service info");
+            return false;
+        }
+
+        if (entry.serviceInfo.permission == null || !entry.serviceInfo.permission.equals(
+                Manifest.permission.BIND_SCREENING_SERVICE)) {
+            Log.w(TAG, "CallScreeningService must require BIND_SCREENING_SERVICE permission: " +
+                    entry.serviceInfo.packageName);
+            return false;
+        }
+
+        ComponentName componentName =
+                new ComponentName(entry.serviceInfo.packageName, entry.serviceInfo.name);
+        intent.setComponent(componentName);
+        if (context.bindServiceAsUser(
+                intent,
+                serviceConnection,
+                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+                UserHandle.CURRENT)) {
+            Log.d(TAG, "bindService, found service, waiting for it to connect");
+            return true;
+        }
+
+        return false;
+    }
+}
diff --git a/src/com/android/server/telecom/CallState.java b/src/com/android/server/telecom/CallState.java
index 05ac38e..1e31732 100644
--- a/src/com/android/server/telecom/CallState.java
+++ b/src/com/android/server/telecom/CallState.java
@@ -114,6 +114,12 @@
      */
     public static final int PULLING = TelecomProtoEnums.PULLING; // = 10
 
+    /**
+     * Indicates that an incoming call has been answered by the in-call UI, but Telephony hasn't yet
+     * set the call to active.
+     */
+    public static final int ANSWERED = 11;
+
     public static String toString(int callState) {
         switch (callState) {
             case NEW:
@@ -138,6 +144,8 @@
                 return "DISCONNECTING";
             case PULLING:
                 return "PULLING";
+            case ANSWERED:
+                return "ANSWERED";
             default:
                 return "UNKNOWN";
         }
diff --git a/src/com/android/server/telecom/CallerInfoLookupHelper.java b/src/com/android/server/telecom/CallerInfoLookupHelper.java
index f67a7f7..a919921 100644
--- a/src/com/android/server/telecom/CallerInfoLookupHelper.java
+++ b/src/com/android/server/telecom/CallerInfoLookupHelper.java
@@ -27,6 +27,7 @@
 import android.telecom.Logging.Runnable;
 import android.telecom.Logging.Session;
 import android.text.TextUtils;
+import android.util.Pair;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.CallerInfo;
@@ -37,6 +38,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.CompletableFuture;
 
 public class CallerInfoLookupHelper {
     public interface OnQueryCompleteListener {
@@ -77,6 +79,47 @@
         mLock = lock;
     }
 
+    /**
+     * Generates a CompletableFuture which performs a contacts lookup asynchronously.  The future
+     * returns a {@link Pair} containing the original handle which is being looked up and any
+     * {@link CallerInfo} which was found.
+     * @param handle
+     * @return {@link CompletableFuture} to perform the contacts lookup.
+     */
+    public CompletableFuture<Pair<Uri, CallerInfo>> startLookup(final Uri handle) {
+        // Create the returned future and
+        final CompletableFuture<Pair<Uri, CallerInfo>> callerInfoFuture = new CompletableFuture<>();
+
+        final String number = handle.getSchemeSpecificPart();
+        if (TextUtils.isEmpty(number)) {
+            // Nothing to do here, just finish.
+            Log.d(CallerInfoLookupHelper.this, "onCallerInfoQueryComplete - no number; end early");
+            callerInfoFuture.complete(new Pair<>(handle, null));
+            return callerInfoFuture;
+        }
+
+        // Setup a query complete listener which will get the results of the contacts lookup.
+        OnQueryCompleteListener listener = new OnQueryCompleteListener() {
+            @Override
+            public void onCallerInfoQueryComplete(Uri handle, CallerInfo info) {
+                Log.d(CallerInfoLookupHelper.this, "onCallerInfoQueryComplete - found info for %s",
+                        Log.piiHandle(handle));
+                // Got something, so complete the future.
+                callerInfoFuture.complete(new Pair<>(handle, info));
+            }
+
+            @Override
+            public void onContactPhotoQueryComplete(Uri handle, CallerInfo info) {
+                // No-op for now; not something this future cares about.
+            }
+        };
+
+        // Start async lookup.
+        startLookup(handle, listener);
+
+        return callerInfoFuture;
+    }
+
     public void startLookup(final Uri handle, OnQueryCompleteListener listener) {
         if (handle == null) {
             listener.onCallerInfoQueryComplete(handle, null);
@@ -108,8 +151,9 @@
                     Log.i(this, "There is a previously incomplete query for handle %s. Adding to " +
                             "listeners for this query.", Log.piiHandle(handle));
                     info.listeners.add(listener);
-                    return;
                 }
+                // Since we have a pending query for this handle already, don't re-query it.
+                return;
             } else {
                 CallerInfoQueryInfo info = new CallerInfoQueryInfo();
                 info.listeners.add(listener);
@@ -117,7 +161,7 @@
             }
         }
 
-        mHandler.post(new Runnable("CILH.sL", mLock) {
+        mHandler.post(new Runnable("CILH.sL", null) {
             @Override
             public void loggedRun() {
                 Session continuedSession = Log.createSubsession();
@@ -171,7 +215,7 @@
     }
 
     private void startPhotoLookup(final Uri handle, final Uri contactPhotoUri) {
-        mHandler.post(new Runnable("CILH.sPL", mLock) {
+        mHandler.post(new Runnable("CILH.sPL", null) {
             @Override
             public void loggedRun() {
                 Session continuedSession = Log.createSubsession();
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index ad7c03d..62f9f99 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -16,16 +16,22 @@
 
 package com.android.server.telecom;
 
+import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.KeyguardManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.pm.UserInfo;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
 import android.media.AudioManager;
 import android.media.AudioSystem;
+import android.media.ToneGenerator;
+import android.media.MediaPlayer;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -45,20 +51,25 @@
 import android.telecom.DisconnectCause;
 import android.telecom.GatewayInfo;
 import android.telecom.Log;
+import android.telecom.Logging.Runnable;
+import android.telecom.Logging.Session;
 import android.telecom.ParcelableConference;
 import android.telecom.ParcelableConnection;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
-import android.telecom.Logging.Runnable;
+import android.telecom.PhoneAccountSuggestion;
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
 import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import android.util.Pair;
+import android.widget.Toast;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.AsyncEmergencyContactNotifier;
+import com.android.internal.telephony.CallerInfo;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.util.IndentingPrintWriter;
@@ -68,11 +79,14 @@
 import com.android.server.telecom.callfiltering.BlockCheckerAdapter;
 import com.android.server.telecom.callfiltering.CallFilterResultCallback;
 import com.android.server.telecom.callfiltering.CallFilteringResult;
-import com.android.server.telecom.callfiltering.CallScreeningServiceFilter;
+import com.android.server.telecom.callfiltering.CallScreeningServiceController;
 import com.android.server.telecom.callfiltering.DirectToVoicemailCallFilter;
 import com.android.server.telecom.callfiltering.IncomingCallFilter;
+import com.android.server.telecom.callredirection.CallRedirectionProcessor;
 import com.android.server.telecom.components.ErrorDialogActivity;
 import com.android.server.telecom.settings.BlockedNumbersUtil;
+import com.android.server.telecom.ui.CallRedirectionConfirmDialogActivity;
+import com.android.server.telecom.ui.CallRedirectionTimeoutDialogActivity;
 import com.android.server.telecom.ui.ConfirmCallDialogActivity;
 import com.android.server.telecom.ui.IncomingCallNotifier;
 
@@ -88,6 +102,7 @@
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -128,6 +143,8 @@
         void onHoldToneRequested(Call call);
         void onExternalCallChanged(Call call, boolean isExternalCall);
         void onDisconnectedTonePlaying(boolean isTonePlaying);
+        void onConnectionTimeChanged(Call call);
+        void onConferenceStateChanged(Call call, boolean isConference);
     }
 
     /** Interface used to define the action which is executed delay under some condition. */
@@ -191,12 +208,13 @@
      */
     public static final int[] ONGOING_CALL_STATES =
             {CallState.SELECT_PHONE_ACCOUNT, CallState.DIALING, CallState.PULLING, CallState.ACTIVE,
-                    CallState.ON_HOLD, CallState.RINGING};
+                    CallState.ON_HOLD, CallState.RINGING, CallState.ANSWERED};
 
     private static final int[] ANY_CALL_STATE =
             {CallState.NEW, CallState.CONNECTING, CallState.SELECT_PHONE_ACCOUNT, CallState.DIALING,
                     CallState.RINGING, CallState.ACTIVE, CallState.ON_HOLD, CallState.DISCONNECTED,
-                    CallState.ABORTED, CallState.DISCONNECTING, CallState.PULLING};
+                    CallState.ABORTED, CallState.DISCONNECTING, CallState.PULLING,
+                    CallState.ANSWERED};
 
     public static final String TELECOM_CALL_ID_PREFIX = "TC@";
 
@@ -225,9 +243,35 @@
 
     /**
      * A pending call is one which requires user-intervention in order to be placed.
-     * Used by {@link #startCallConfirmation(Call)}.
+     * Used by {@link #startCallConfirmation}.
      */
     private Call mPendingCall;
+    /**
+     * Cached latest pending redirected call which requires user-intervention in order to be placed.
+     * Used by {@link #onCallRedirectionComplete}.
+     */
+    private Call mPendingRedirectedOutgoingCall;
+    /**
+     * Cached latest pending redirected call information which require user-intervention in order
+     * to be placed. Used by {@link #onCallRedirectionComplete}.
+     */
+    private final Map<String, Runnable> mPendingRedirectedOutgoingCallInfo =
+            new ConcurrentHashMap<>();
+    /**
+     * Cached latest pending Unredirected call information which require user-intervention in order
+     * to be placed. Used by {@link #onCallRedirectionComplete}.
+     */
+    private final Map<String, Runnable> mPendingUnredirectedOutgoingCallInfo =
+            new ConcurrentHashMap<>();
+
+    private CompletableFuture<Call> mPendingCallConfirm;
+    private CompletableFuture<Pair<Call, PhoneAccountHandle>> mPendingAccountSelection;
+
+    // Instance variables for testing -- we keep the latest copy of the outgoing call futures
+    // here so that we can wait on them in tests
+    private CompletableFuture<Call> mLatestPostSelectionProcessingFuture;
+    private CompletableFuture<Pair<Call, List<PhoneAccountSuggestion>>>
+            mLatestPreAccountSelectionFuture;
 
     /**
      * The current telecom call ID.  Used when creating new instances of {@link Call}.  Should
@@ -256,6 +300,7 @@
             new ConcurrentHashMap<CallsManagerListener, Boolean>(16, 0.9f, 1));
     private final HeadsetMediaButton mHeadsetMediaButton;
     private final WiredHeadsetManager mWiredHeadsetManager;
+    private final SystemStateHelper mSystemStateHelper;
     private final BluetoothRouteManager mBluetoothRouteManager;
     private final DockManager mDockManager;
     private final TtyManager mTtyManager;
@@ -264,8 +309,6 @@
     private final CallLogManager mCallLogManager;
     private final Context mContext;
     private final TelecomSystem.SyncRoot mLock;
-    private final ContactsAsyncHelper mContactsAsyncHelper;
-    private final CallerInfoAsyncQueryFactory mCallerInfoAsyncQueryFactory;
     private final PhoneAccountRegistrar mPhoneAccountRegistrar;
     private final MissedCallNotifier mMissedCallNotifier;
     private IncomingCallNotifier mIncomingCallNotifier;
@@ -280,6 +323,7 @@
     /* Handler tied to thread in which CallManager was initialized. */
     private final Handler mHandler = new Handler(Looper.getMainLooper());
     private final EmergencyCallHelper mEmergencyCallHelper;
+    private final RoleManagerAdapter mRoleManagerAdapter;
 
     private final ConnectionServiceFocusManager.CallsManagerRequester mRequester =
             new ConnectionServiceFocusManager.CallsManagerRequester() {
@@ -317,6 +361,12 @@
                                                PhoneAccountHandle handle) {
             broadcastUnregisterIntent(handle);
         }
+
+        @Override
+        public void onPhoneAccountChanged(PhoneAccountRegistrar registrar,
+                PhoneAccount phoneAccount) {
+            handlePhoneAccountChanged(registrar, phoneAccount);
+        }
     };
 
     /**
@@ -328,15 +378,33 @@
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
+            Log.startSession("CM.CCCR");
             String action = intent.getAction();
             if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action)
                     || SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED.equals(action)) {
-                BlockedNumbersUtil.updateEmergencyCallNotification(context,
-                        SystemContract.shouldShowEmergencyCallNotification(context));
-             }
+                new UpdateEmergencyCallNotificationTask().doInBackground(
+                        Pair.create(context, Log.createSubsession()));
+            }
         }
     };
 
+    private static class UpdateEmergencyCallNotificationTask
+            extends AsyncTask<Pair<Context, Session>, Void, Void> {
+        @SafeVarargs
+        @Override
+        protected final Void doInBackground(Pair<Context, Session>... args) {
+            if (args == null || args.length != 1 || args[0] == null) {
+                Log.e(this, new IllegalArgumentException(), "Incorrect invocation");
+                return null;
+            }
+            Log.continueSession(args[0].second, "CM.UECNT");
+            Context context = args[0].first;
+            BlockedNumbersUtil.updateEmergencyCallNotification(context,
+                    SystemContract.shouldShowEmergencyCallNotification(context));
+            return null;
+        }
+    }
+
     /**
      * Initializes the required Telecom components.
      */
@@ -344,8 +412,7 @@
     public CallsManager(
             Context context,
             TelecomSystem.SyncRoot lock,
-            ContactsAsyncHelper contactsAsyncHelper,
-            CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory,
+            CallerInfoLookupHelper callerInfoLookupHelper,
             MissedCallNotifier missedCallNotifier,
             PhoneAccountRegistrar phoneAccountRegistrar,
             HeadsetMediaButtonFactory headsetMediaButtonFactory,
@@ -356,7 +423,7 @@
             CallAudioManager.AudioServiceFactory audioServiceFactory,
             BluetoothRouteManager bluetoothManager,
             WiredHeadsetManager wiredHeadsetManager,
-            SystemStateProvider systemStateProvider,
+            SystemStateHelper systemStateHelper,
             DefaultDialerCache defaultDialerCache,
             Timeouts.Adapter timeoutsAdapter,
             AsyncRingtonePlayer asyncRingtonePlayer,
@@ -365,36 +432,38 @@
             InCallTonePlayer.ToneGeneratorFactory toneGeneratorFactory,
             ClockProxy clockProxy,
             BluetoothStateReceiver bluetoothStateReceiver,
-            InCallControllerFactory inCallControllerFactory) {
+            CallAudioRouteStateMachine.Factory callAudioRouteStateMachineFactory,
+            CallAudioModeStateMachine.Factory callAudioModeStateMachineFactory,
+            InCallControllerFactory inCallControllerFactory,
+            RoleManagerAdapter roleManagerAdapter) {
         mContext = context;
         mLock = lock;
         mPhoneNumberUtilsAdapter = phoneNumberUtilsAdapter;
-        mContactsAsyncHelper = contactsAsyncHelper;
-        mCallerInfoAsyncQueryFactory = callerInfoAsyncQueryFactory;
         mPhoneAccountRegistrar = phoneAccountRegistrar;
         mPhoneAccountRegistrar.addListener(mPhoneAccountListener);
         mMissedCallNotifier = missedCallNotifier;
         StatusBarNotifier statusBarNotifier = new StatusBarNotifier(context, this);
         mWiredHeadsetManager = wiredHeadsetManager;
+        mSystemStateHelper = systemStateHelper;
         mDefaultDialerCache = defaultDialerCache;
         mBluetoothRouteManager = bluetoothManager;
         mDockManager = new DockManager(context);
         mTimeoutsAdapter = timeoutsAdapter;
         mEmergencyCallHelper = emergencyCallHelper;
-        mCallerInfoLookupHelper = new CallerInfoLookupHelper(context, mCallerInfoAsyncQueryFactory,
-                mContactsAsyncHelper, mLock);
+        mCallerInfoLookupHelper = callerInfoLookupHelper;
 
         mDtmfLocalTonePlayer =
                 new DtmfLocalTonePlayer(new DtmfLocalTonePlayer.ToneGeneratorProxy());
-        CallAudioRouteStateMachine callAudioRouteStateMachine = new CallAudioRouteStateMachine(
-                context,
-                this,
-                bluetoothManager,
-                wiredHeadsetManager,
-                statusBarNotifier,
-                audioServiceFactory,
-                CallAudioRouteStateMachine.EARPIECE_AUTO_DETECT
-        );
+        CallAudioRouteStateMachine callAudioRouteStateMachine =
+                callAudioRouteStateMachineFactory.create(
+                        context,
+                        this,
+                        bluetoothManager,
+                        wiredHeadsetManager,
+                        statusBarNotifier,
+                        audioServiceFactory,
+                        CallAudioRouteStateMachine.EARPIECE_AUTO_DETECT
+                );
         callAudioRouteStateMachine.initialize();
 
         CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter =
@@ -404,27 +473,34 @@
                         wiredHeadsetManager,
                         mDockManager);
 
+        AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        InCallTonePlayer.MediaPlayerFactory mediaPlayerFactory =
+                (resourceId, attributes) ->
+                        new InCallTonePlayer.MediaPlayerAdapterImpl(
+                                MediaPlayer.create(mContext, resourceId, attributes,
+                                        audioManager.generateAudioSessionId()));
         InCallTonePlayer.Factory playerFactory = new InCallTonePlayer.Factory(
-                callAudioRoutePeripheralAdapter, lock, toneGeneratorFactory);
+                callAudioRoutePeripheralAdapter, lock, toneGeneratorFactory, mediaPlayerFactory,
+                () -> audioManager.getStreamVolume(AudioManager.STREAM_RING) > 0);
 
         SystemSettingsUtil systemSettingsUtil = new SystemSettingsUtil();
         RingtoneFactory ringtoneFactory = new RingtoneFactory(this, context);
         SystemVibrator systemVibrator = new SystemVibrator(context);
         mInCallController = inCallControllerFactory.create(context, mLock, this,
-                systemStateProvider, defaultDialerCache, mTimeoutsAdapter,
+                systemStateHelper, defaultDialerCache, mTimeoutsAdapter,
                 emergencyCallHelper);
         mRinger = new Ringer(playerFactory, context, systemSettingsUtil, asyncRingtonePlayer,
-                ringtoneFactory, systemVibrator, mInCallController);
+                ringtoneFactory, systemVibrator,
+                new Ringer.VibrationEffectProxy(), mInCallController);
         mCallRecordingTonePlayer = new CallRecordingTonePlayer(mContext,
                 (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE), mLock);
         mCallAudioManager = new CallAudioManager(callAudioRouteStateMachine,
-                this,new CallAudioModeStateMachine((AudioManager)
-                        mContext.getSystemService(Context.AUDIO_SERVICE)),
+                this, callAudioModeStateMachineFactory.create(systemStateHelper,
+                (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE)),
                 playerFactory, mRinger, new RingbackPlayer(playerFactory),
                 bluetoothStateReceiver, mDtmfLocalTonePlayer);
 
-        mConnectionSvrFocusMgr = connectionServiceFocusManagerFactory.create(
-                mRequester, Looper.getMainLooper());
+        mConnectionSvrFocusMgr = connectionServiceFocusManagerFactory.create(mRequester);
         mHeadsetMediaButton = headsetMediaButtonFactory.create(context, this, mLock);
         mTtyManager = new TtyManager(context, mWiredHeadsetManager);
         mProximitySensorManager = proximitySensorManagerFactory.create(context, this);
@@ -434,6 +510,7 @@
                 new ConnectionServiceRepository(mPhoneAccountRegistrar, mContext, mLock, this);
         mInCallWakeLockController = inCallWakeLockControllerFactory.create(context, this);
         mClockProxy = clockProxy;
+        mRoleManagerAdapter = roleManagerAdapter;
 
         mListeners.add(mInCallWakeLockController);
         mListeners.add(statusBarNotifier);
@@ -483,6 +560,10 @@
         return mCallerInfoLookupHelper;
     }
 
+    public RoleManagerAdapter getRoleManagerAdapter() {
+        return mRoleManagerAdapter;
+    }
+
     @Override
     public void onSuccessfulOutgoingCall(Call call, int callState) {
         Log.v(this, "onSuccessfulOutgoingCall, %s", call);
@@ -512,18 +593,47 @@
     @Override
     public void onSuccessfulIncomingCall(Call incomingCall) {
         Log.d(this, "onSuccessfulIncomingCall");
-        if (incomingCall.hasProperty(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE)) {
-            Log.i(this, "Skipping call filtering due to ECBM");
+        PhoneAccount phoneAccount = mPhoneAccountRegistrar.getPhoneAccountUnchecked(
+                incomingCall.getTargetPhoneAccount());
+        Bundle extras =
+            phoneAccount == null || phoneAccount.getExtras() == null
+                ? new Bundle()
+                : phoneAccount.getExtras();
+        if (incomingCall.hasProperty(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE) ||
+                incomingCall.isSelfManaged() ||
+                extras.getBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING)) {
+            Log.i(this, "Skipping call filtering for %s (ecm=%b, selfMgd=%b, skipExtra=%b)",
+                    incomingCall.getId(),
+                    incomingCall.hasProperty(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE),
+                    incomingCall.isSelfManaged(),
+                    extras.getBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING));
             onCallFilteringComplete(incomingCall, new CallFilteringResult(true, false, true, true));
+            incomingCall.setIsUsingCallFiltering(false);
             return;
         }
 
+        incomingCall.setIsUsingCallFiltering(true);
         List<IncomingCallFilter.CallFilter> filters = new ArrayList<>();
         filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper));
         filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter(),
-                mCallerInfoLookupHelper));
-        filters.add(new CallScreeningServiceFilter(mContext, this, mPhoneAccountRegistrar,
-                mDefaultDialerCache, new ParcelableCallUtils.Converter(), mLock));
+                mCallerInfoLookupHelper, null));
+        filters.add(new CallScreeningServiceController(mContext, this, mPhoneAccountRegistrar,
+                new ParcelableCallUtils.Converter(), mLock,
+                new TelecomServiceImpl.SettingsSecureAdapterImpl(), mCallerInfoLookupHelper,
+                new CallScreeningServiceHelper.AppLabelProxy() {
+                    @Override
+                    public CharSequence getAppLabel(String packageName) {
+                        PackageManager pm = mContext.getPackageManager();
+                        try {
+                            ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
+                            return pm.getApplicationLabel(info);
+                        } catch (PackageManager.NameNotFoundException nnfe) {
+                            Log.w(this, "Could not determine package name.");
+                        }
+
+                        return null;
+                    }
+                }));
         new IncomingCallFilter(mContext, this, incomingCall, mLock,
                 mTimeoutsAdapter, filters).performFiltering();
     }
@@ -549,12 +659,17 @@
                 } else {
                     Log.i(this, "onCallFilteringCompleted: Call rejected! " +
                             "Exceeds maximum number of ringing calls.");
-                    rejectCallAndLog(incomingCall);
+                    rejectCallAndLog(incomingCall, result);
                 }
             } else if (hasMaximumManagedDialingCalls(incomingCall)) {
-                Log.i(this, "onCallFilteringCompleted: Call rejected! Exceeds maximum number of " +
-                        "dialing calls.");
-                rejectCallAndLog(incomingCall);
+                if (shouldSilenceInsteadOfReject(incomingCall)) {
+                    incomingCall.silence();
+                } else {
+
+                    Log.i(this, "onCallFilteringCompleted: Call rejected! Exceeds maximum number of " +
+                            "dialing calls.");
+                    rejectCallAndLog(incomingCall, result);
+                }
             } else {
                 addCall(incomingCall);
             }
@@ -568,8 +683,8 @@
                 if (result.shouldShowNotification) {
                     Log.w(this, "onCallScreeningCompleted: blocked call, showing notification.");
                 }
-                mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE,
-                        result.shouldShowNotification);
+                mCallLogManager.logCall(incomingCall, Calls.BLOCKED_TYPE,
+                        result.shouldShowNotification, result);
             } else if (result.shouldShowNotification) {
                 Log.i(this, "onCallScreeningCompleted: blocked call, showing notification.");
                 mMissedCallNotifier.showMissedCallNotification(
@@ -579,8 +694,10 @@
     }
 
     /**
-     * Whether allow (silence rather than reject) the incoming call if it has a different source
-     * (connection service) from the existing ringing call when reaching maximum ringing calls.
+     * In the event that the maximum supported calls of a given type is reached, the
+     * default behavior is to reject any additional calls of that type.  This checks
+     * if the device is configured to silence instead of reject the call, provided
+     * that the incoming call is from a different source (connection service).
      */
     private boolean shouldSilenceInsteadOfReject(Call incomingCall) {
         if (!mContext.getResources().getBoolean(
@@ -588,8 +705,6 @@
             return false;
         }
 
-        Call ringingCall = null;
-
         for (Call call : mCalls) {
             // Only operate on top-level calls
             if (call.getParentCall() != null) {
@@ -600,8 +715,7 @@
                 continue;
             }
 
-            if (CallState.RINGING == call.getState() &&
-                    call.getConnectionService() == incomingCall.getConnectionService()) {
+            if (call.getConnectionService() == incomingCall.getConnectionService()) {
                 return false;
             }
         }
@@ -696,6 +810,15 @@
     }
 
     @Override
+    public void onConferenceStateChanged(Call call, boolean isConference) {
+        // Conference changed whether it is treated as a conference or not.
+        updateCanAddCall();
+        for (CallsManagerListener listener : mListeners) {
+            listener.onConferenceStateChanged(call, isConference);
+        }
+    }
+
+    @Override
     public void onIsVoipAudioModeChanged(Call call) {
         for (CallsManagerListener listener : mListeners) {
             listener.onIsVoipAudioModeChanged(call);
@@ -812,6 +935,18 @@
     }
 
     @Override
+    public void onCallHoldFailed(Call call) {
+        // Normally, we don't care whether a call hold has failed. However, if a call was held in
+        // order to answer an incoming call, that incoming call needs to be brought out of the
+        // ANSWERED state so that the user can try the operation again.
+        for (Call call1 : mCalls) {
+            if (call1 != call && call1.getState() == CallState.ANSWERED) {
+                setCallState(call1, CallState.RINGING, "hold failed on other call");
+            }
+        }
+    }
+
+    @Override
     public UserHandle getCurrentUserHandle() {
         return mCurrentUserHandle;
     }
@@ -829,6 +964,11 @@
     }
 
     @VisibleForTesting
+    public PhoneAccountRegistrar.Listener getPhoneAccountListener() {
+        return mPhoneAccountListener;
+    }
+
+    @VisibleForTesting
     public boolean hasEmergencyCall() {
         for (Call call : mCalls) {
             if (call.isEmergencyCall()) {
@@ -912,8 +1052,6 @@
                 this,
                 mLock,
                 mConnectionServiceRepository,
-                mContactsAsyncHelper,
-                mCallerInfoAsyncQueryFactory,
                 mPhoneNumberUtilsAdapter,
                 handle,
                 null /* gatewayInfo */,
@@ -1047,8 +1185,6 @@
                 this,
                 mLock,
                 mConnectionServiceRepository,
-                mContactsAsyncHelper,
-                mCallerInfoAsyncQueryFactory,
                 mPhoneNumberUtilsAdapter,
                 handle,
                 null /* gatewayInfo */,
@@ -1108,20 +1244,24 @@
      * For self-managed connections, we don't expect the Incall UI to launch, but this is still a
      * first step in getting the self-managed ConnectionService to create the connection.
      * @param handle Handle to connect the call with.
-     * @param phoneAccountHandle The phone account which contains the component name of the
+     * @param requestedAccountHandle The phone account which contains the component name of the
      *        connection service to use for this call.
      * @param extras The optional extras Bundle passed with the intent used for the incoming call.
      * @param initiatingUser {@link UserHandle} of user that place the outgoing call.
      * @param originalIntent
+     * @param callingPackage the package name of the app which initiated the outgoing call.
      */
     @VisibleForTesting
-    public Call startOutgoingCall(Uri handle, PhoneAccountHandle phoneAccountHandle, Bundle extras,
-            UserHandle initiatingUser, Intent originalIntent) {
-        boolean isReusedCall = true;
+    public @NonNull
+    CompletableFuture<Call> startOutgoingCall(Uri handle,
+            PhoneAccountHandle requestedAccountHandle,
+            Bundle extras, UserHandle initiatingUser, Intent originalIntent,
+            String callingPackage) {
+        boolean isReusedCall;
         Call call = reuseOutgoingCall(handle);
 
         PhoneAccount account =
-                mPhoneAccountRegistrar.getPhoneAccount(phoneAccountHandle, initiatingUser);
+                mPhoneAccountRegistrar.getPhoneAccount(requestedAccountHandle, initiatingUser);
         boolean isSelfManaged = account != null && account.isSelfManaged();
 
         // Create a call with original handle. The handle may be changed when the call is attached
@@ -1131,18 +1271,16 @@
                     this,
                     mLock,
                     mConnectionServiceRepository,
-                    mContactsAsyncHelper,
-                    mCallerInfoAsyncQueryFactory,
                     mPhoneNumberUtilsAdapter,
                     handle,
                     null /* gatewayInfo */,
                     null /* connectionManagerPhoneAccount */,
-                    null /* phoneAccountHandle */,
+                    null /* requestedAccountHandle */,
                     Call.CALL_DIRECTION_OUTGOING /* callDirection */,
                     false /* forceAttachToExistingConnection */,
                     false, /* isConference */
                     mClockProxy);
-            call.initAnalytics();
+            call.initAnalytics(callingPackage);
 
             // Ensure new calls related to self-managed calls/connections are set as such.  This
             // will be overridden when the actual connection is returned in startCreateConnection,
@@ -1155,6 +1293,8 @@
             }
             call.setInitiatingUser(initiatingUser);
             isReusedCall = false;
+        } else {
+            isReusedCall = true;
         }
 
         int videoState = VideoProfile.STATE_AUDIO_ONLY;
@@ -1189,96 +1329,274 @@
             call.setVideoState(videoState);
         }
 
-        List<PhoneAccountHandle> potentialPhoneAccounts = findOutgoingCallPhoneAccount(
-                phoneAccountHandle, handle, VideoProfile.isVideo(videoState), initiatingUser);
-        if (potentialPhoneAccounts.size() == 1) {
-            phoneAccountHandle = potentialPhoneAccounts.get(0);
-        } else {
-            phoneAccountHandle = null;
+        final int finalVideoState = videoState;
+        final Call finalCall = call;
+        Handler outgoingCallHandler = new Handler(Looper.getMainLooper());
+        // Create a empty CompletableFuture and compose it with findOutgoingPhoneAccount to get
+        // a first guess at the list of suitable outgoing PhoneAccounts.
+        // findOutgoingPhoneAccount returns a CompletableFuture which is either already complete
+        // (in the case where we don't need to do the per-contact lookup) or a CompletableFuture
+        // that completes once the contact lookup via CallerInfoLookupHelper is complete.
+        CompletableFuture<List<PhoneAccountHandle>> accountsForCall =
+                CompletableFuture.completedFuture((Void) null).thenComposeAsync((x) ->
+                                findOutgoingCallPhoneAccount(requestedAccountHandle, handle,
+                                        VideoProfile.isVideo(finalVideoState), initiatingUser),
+                        new LoggedHandlerExecutor(outgoingCallHandler, "CM.fOCP", mLock));
+
+        // This is a block of code that executes after the list of potential phone accts has been
+        // retrieved.
+        CompletableFuture<List<PhoneAccountHandle>> setAccountHandle =
+                accountsForCall.whenCompleteAsync((potentialPhoneAccounts, exception) -> {
+                    Log.i(CallsManager.this, "set outgoing call phone acct stage");
+                    PhoneAccountHandle phoneAccountHandle;
+                    if (potentialPhoneAccounts.size() == 1) {
+                        phoneAccountHandle = potentialPhoneAccounts.get(0);
+                    } else {
+                        phoneAccountHandle = null;
+                    }
+                    finalCall.setTargetPhoneAccount(phoneAccountHandle);
+                }, new LoggedHandlerExecutor(outgoingCallHandler, "CM.sOCPA", mLock));
+
+
+        // This composes the future containing the potential phone accounts with code that queries
+        // the suggestion service if necessary (i.e. if the list is longer than 1).
+        // If the suggestion service is queried, the inner lambda will return a future that
+        // completes when the suggestion service calls the callback.
+        CompletableFuture<List<PhoneAccountSuggestion>> suggestionFuture = accountsForCall.
+                thenComposeAsync(potentialPhoneAccounts -> {
+                    Log.i(CallsManager.this, "call outgoing call suggestion service stage");
+                    if (potentialPhoneAccounts.size() == 1) {
+                        PhoneAccountSuggestion suggestion =
+                                new PhoneAccountSuggestion(potentialPhoneAccounts.get(0),
+                                        PhoneAccountSuggestion.REASON_NONE, true);
+                        return CompletableFuture.completedFuture(
+                                Collections.singletonList(suggestion));
+                    }
+                    return PhoneAccountSuggestionHelper.bindAndGetSuggestions(mContext,
+                            finalCall.getHandle(), potentialPhoneAccounts);
+                }, new LoggedHandlerExecutor(outgoingCallHandler, "CM.cOCSS", mLock));
+
+
+        // This future checks the status of existing calls and attempts to make room for the
+        // outgoing call. The future returned by the inner method will usually be pre-completed --
+        // we only pause here if user interaction is required to disconnect a self-managed call.
+        // It runs after the account handle is set, independently of the phone account suggestion
+        // future.
+        CompletableFuture<Call> makeRoomForCall = setAccountHandle.thenComposeAsync(
+                potentialPhoneAccounts -> {
+                    Log.i(CallsManager.this, "make room for outgoing call stage");
+                    boolean isPotentialInCallMMICode =
+                            isPotentialInCallMMICode(handle) && !isSelfManaged;
+                    // Do not support any more live calls.  Our options are to move a call to hold,
+                    // disconnect a call, or cancel this call altogether. If a call is being reused,
+                    // then it has already passed the makeRoomForOutgoingCall check once and will
+                    // fail the second time due to the call transitioning into the CONNECTING state.
+                    if (!isPotentialInCallMMICode && (!isReusedCall
+                            && !makeRoomForOutgoingCall(finalCall, finalCall.isEmergencyCall()))) {
+                        Call foregroundCall = getForegroundCall();
+                        Log.d(CallsManager.this, "No more room for outgoing call %s ", finalCall);
+                        if (foregroundCall.isSelfManaged()) {
+                            // If the ongoing call is a self-managed call, then prompt the user to
+                            // ask if they'd like to disconnect their ongoing call and place the
+                            // outgoing call.
+                            Log.i(CallsManager.this, "Prompting user to disconnect "
+                                    + "self-managed call");
+                            finalCall.setOriginalCallIntent(originalIntent);
+                            CompletableFuture<Call> completionFuture = new CompletableFuture<>();
+                            startCallConfirmation(finalCall, completionFuture);
+                            return completionFuture;
+                        } else {
+                            // If the ongoing call is a managed call, we will prevent the outgoing
+                            // call from dialing.
+                            notifyCreateConnectionFailed(
+                                    finalCall.getTargetPhoneAccount(), finalCall);
+                        }
+                        Log.i(CallsManager.this, "Aborting call since there's no room");
+                        return CompletableFuture.completedFuture(null);
+                    }
+                    return CompletableFuture.completedFuture(finalCall);
+        }, new LoggedHandlerExecutor(outgoingCallHandler, "CM.dSMCP", mLock));
+
+        // The outgoing call can be placed, go forward. This future glues together the results of
+        // the account suggestion stage and the make room for call stage.
+        CompletableFuture<Pair<Call, List<PhoneAccountSuggestion>>> preSelectStage =
+                makeRoomForCall.thenCombine(suggestionFuture, Pair::create);
+        mLatestPreAccountSelectionFuture = preSelectStage;
+
+        // This future takes the list of suggested accounts and the call and determines if more
+        // user interaction in the form of a phone account selection screen is needed. If so, it
+        // will set the call to SELECT_PHONE_ACCOUNT, add it to our internal list/send it to dialer,
+        // and then execution will pause pending the dialer calling phoneAccountSelected.
+        CompletableFuture<Pair<Call, PhoneAccountHandle>> dialerSelectPhoneAccountFuture =
+                preSelectStage.thenComposeAsync(
+                        (args) -> {
+                            Log.i(CallsManager.this, "dialer phone acct select stage");
+                            Call callToPlace = args.first;
+                            List<PhoneAccountSuggestion> accountSuggestions = args.second;
+                            if (callToPlace == null) {
+                                return CompletableFuture.completedFuture(null);
+                            }
+                            if (accountSuggestions == null || accountSuggestions.isEmpty()) {
+                                Log.i(CallsManager.this, "Aborting call since there are no"
+                                        + " available accounts.");
+                                showErrorMessage(R.string.cant_call_due_to_no_supported_service);
+                                return CompletableFuture.completedFuture(null);
+                            }
+                            boolean needsAccountSelection = accountSuggestions.size() > 1
+                                    && !callToPlace.isEmergencyCall() && !isSelfManaged;
+                            if (!needsAccountSelection) {
+                                return CompletableFuture.completedFuture(Pair.create(callToPlace,
+                                        accountSuggestions.get(0).getPhoneAccountHandle()));
+                            }
+                            // This is the state where the user is expected to select an account
+                            callToPlace.setState(CallState.SELECT_PHONE_ACCOUNT,
+                                    "needs account selection");
+                            // Create our own instance to modify (since extras may be Bundle.EMPTY)
+                            Bundle newExtras = new Bundle(extras);
+                            List<PhoneAccountHandle> accountsFromSuggestions = accountSuggestions
+                                    .stream()
+                                    .map(PhoneAccountSuggestion::getPhoneAccountHandle)
+                                    .collect(Collectors.toList());
+                            newExtras.putParcelableList(
+                                    android.telecom.Call.AVAILABLE_PHONE_ACCOUNTS,
+                                    accountsFromSuggestions);
+                            newExtras.putParcelableList(
+                                    android.telecom.Call.EXTRA_SUGGESTED_PHONE_ACCOUNTS,
+                                    accountSuggestions);
+                            // Set a future in place so that we can proceed once the dialer replies.
+                            mPendingAccountSelection = new CompletableFuture<>();
+                            callToPlace.setIntentExtras(newExtras);
+
+                            addCall(callToPlace);
+                            return mPendingAccountSelection;
+                        }, new LoggedHandlerExecutor(outgoingCallHandler, "CM.dSPA", mLock));
+
+        // Potentially perform call identification for dialed TEL scheme numbers.
+        if (PhoneAccount.SCHEME_TEL.equals(handle.getScheme())) {
+            // Perform an asynchronous contacts lookup in this stage; ensure post-dial digits are
+            // not included.
+            CompletableFuture<Pair<Uri, CallerInfo>> contactLookupFuture =
+                    mCallerInfoLookupHelper.startLookup(Uri.fromParts(handle.getScheme(),
+                            PhoneNumberUtils.extractNetworkPortion(handle.getSchemeSpecificPart()),
+                            null));
+
+            // Once the phone account selection stage has completed, we can handle the results from
+            // that with the contacts lookup in order to determine if we should lookup bind to the
+            // CallScreeningService in order for it to potentially provide caller ID.
+            dialerSelectPhoneAccountFuture.thenAcceptBothAsync(contactLookupFuture,
+                    (callPhoneAccountHandlePair, uriCallerInfoPair) -> {
+                        Call theCall = callPhoneAccountHandlePair.first;
+                        boolean isInContacts = uriCallerInfoPair.second != null
+                                && uriCallerInfoPair.second.contactExists;
+                        Log.d(CallsManager.this, "outgoingCallIdStage: isInContacts=%s",
+                                isInContacts);
+
+                        // We only want to provide a CallScreeningService with a call if its not in
+                        // contacts.
+                        if (!isInContacts) {
+                            bindForOutgoingCallerId(theCall);
+                        }
+            }, new LoggedHandlerExecutor(outgoingCallHandler, "CM.pCSB", mLock));
         }
-        call.setTargetPhoneAccount(phoneAccountHandle);
 
-        boolean isPotentialInCallMMICode = isPotentialInCallMMICode(handle) && !isSelfManaged;
+        // Finally, after all user interaction is complete, we execute this code to finish setting
+        // up the outgoing call. The inner method always returns a completed future containing the
+        // call that we've finished setting up.
+        mLatestPostSelectionProcessingFuture = dialerSelectPhoneAccountFuture
+                .thenComposeAsync(args -> {
+                    if (args == null) {
+                        return CompletableFuture.completedFuture(null);
+                    }
+                    Log.i(CallsManager.this, "post acct selection stage");
+                    Call callToUse = args.first;
+                    PhoneAccountHandle phoneAccountHandle = args.second;
+                    PhoneAccount accountToUse = mPhoneAccountRegistrar
+                            .getPhoneAccount(phoneAccountHandle, initiatingUser);
+                    callToUse.setTargetPhoneAccount(phoneAccountHandle);
+                    if (accountToUse != null && accountToUse.getExtras() != null) {
+                        if (accountToUse.getExtras()
+                                .getBoolean(PhoneAccount.EXTRA_ALWAYS_USE_VOIP_AUDIO_MODE)) {
+                            Log.d(this, "startOutgoingCall: defaulting to voip mode for call %s",
+                                    callToUse.getId());
+                            callToUse.setIsVoipAudioMode(true);
+                        }
+                    }
 
-        // Do not support any more live calls.  Our options are to move a call to hold, disconnect
-        // a call, or cancel this call altogether. If a call is being reused, then it has already
-        // passed the makeRoomForOutgoingCall check once and will fail the second time due to the
-        // call transitioning into the CONNECTING state.
-        if (!isPotentialInCallMMICode && (!isReusedCall
-                && !makeRoomForOutgoingCall(call, call.isEmergencyCall()))) {
-            Call foregroundCall = getForegroundCall();
-            Log.d(this, "No more room for outgoing call %s ", call);
-            if (foregroundCall.isSelfManaged()) {
-                // If the ongoing call is a self-managed call, then prompt the user to ask if they'd
-                // like to disconnect their ongoing call and place the outgoing call.
-                call.setOriginalCallIntent(originalIntent);
-                startCallConfirmation(call);
-            } else {
-                // If the ongoing call is a managed call, we will prevent the outgoing call from
-                // dialing.
-                notifyCreateConnectionFailed(call.getTargetPhoneAccount(), call);
-            }
+                    callToUse.setState(
+                            CallState.CONNECTING,
+                            phoneAccountHandle == null ? "no-handle"
+                                    : phoneAccountHandle.toString());
+
+                    boolean isVoicemail = isVoicemail(callToUse.getHandle(), accountToUse);
+
+                    if (!isVoicemail && (isRttSettingOn() || (extras != null
+                            && extras.getBoolean(TelecomManager.EXTRA_START_CALL_WITH_RTT,
+                            false)))) {
+                        Log.d(this, "Outgoing call requesting RTT, rtt setting is %b",
+                                isRttSettingOn());
+                        if (callToUse.isEmergencyCall() || (accountToUse != null
+                                && accountToUse.hasCapabilities(PhoneAccount.CAPABILITY_RTT))) {
+                            // If the call requested RTT and it's an emergency call, ignore the
+                            // capability and hope that the modem will deal with it somehow.
+                            callToUse.createRttStreams();
+                        }
+                        // Even if the phone account doesn't support RTT yet,
+                        // the connection manager might change that. Set this to check it later.
+                        callToUse.setRequestedToStartWithRtt();
+                    }
+
+                    setIntentExtrasAndStartTime(callToUse, extras);
+                    setCallSourceToAnalytics(callToUse, originalIntent);
+
+                    if (isPotentialMMICode(handle) && !isSelfManaged) {
+                        // Do not add the call if it is a potential MMI code.
+                        callToUse.addListener(this);
+                    } else if (!mCalls.contains(callToUse)) {
+                        // We check if mCalls already contains the call because we could
+                        // potentially be reusing
+                        // a call which was previously added (See {@link #reuseOutgoingCall}).
+                        addCall(callToUse);
+                    }
+                    return CompletableFuture.completedFuture(callToUse);
+                }, new LoggedHandlerExecutor(outgoingCallHandler, "CM.pASP", mLock));
+        return mLatestPostSelectionProcessingFuture;
+    }
+
+    /**
+     * Performs call identification for an outgoing phone call.
+     * @param theCall The outgoing call to perform identification.
+     */
+    private void bindForOutgoingCallerId(Call theCall) {
+        // Find the user chosen call screening app.
+        String callScreeningApp =
+                mRoleManagerAdapter.getDefaultCallScreeningApp();
+
+        CompletableFuture future =
+                new CallScreeningServiceHelper(mContext,
+                mLock,
+                callScreeningApp,
+                new ParcelableCallUtils.Converter(),
+                mCurrentUserHandle,
+                theCall,
+                new CallScreeningServiceHelper.AppLabelProxy() {
+                    @Override
+                    public CharSequence getAppLabel(String packageName) {
+                        PackageManager pm = mContext.getPackageManager();
+                        try {
+                            ApplicationInfo info = pm.getApplicationInfo(
+                                    packageName, 0);
+                            return pm.getApplicationLabel(info);
+                        } catch (PackageManager.NameNotFoundException nnfe) {
+                            Log.w(this, "Could not determine package name.");
+                        }
+
+                        return null;
+                    }
+                }).process();
+        future.thenApply( v -> {
+            Log.i(this, "Outgoing caller ID complete");
             return null;
-        }
-
-        // The outgoing call can be placed, go forward.
-
-        boolean needsAccountSelection =
-                phoneAccountHandle == null && potentialPhoneAccounts.size() > 1
-                        && !call.isEmergencyCall() && !isSelfManaged;
-        if (needsAccountSelection) {
-            // This is the state where the user is expected to select an account
-            call.setState(CallState.SELECT_PHONE_ACCOUNT, "needs account selection");
-            // Create our own instance to modify (since extras may be Bundle.EMPTY)
-            extras = new Bundle(extras);
-            extras.putParcelableList(android.telecom.Call.AVAILABLE_PHONE_ACCOUNTS,
-                    potentialPhoneAccounts);
-        } else {
-            PhoneAccount accountToUse =
-                    mPhoneAccountRegistrar.getPhoneAccount(phoneAccountHandle, initiatingUser);
-            if (accountToUse != null && accountToUse.getExtras() != null) {
-                if (accountToUse.getExtras()
-                        .getBoolean(PhoneAccount.EXTRA_ALWAYS_USE_VOIP_AUDIO_MODE)) {
-                    Log.d(this, "startOutgoingCall: defaulting to voip mode for call %s",
-                            call.getId());
-                    call.setIsVoipAudioMode(true);
-                }
-            }
-
-            call.setState(
-                    CallState.CONNECTING,
-                    phoneAccountHandle == null ? "no-handle" : phoneAccountHandle.toString());
-
-            boolean isVoicemail = (call.getHandle() != null)
-                    && (PhoneAccount.SCHEME_VOICEMAIL.equals(call.getHandle().getScheme())
-                    || (accountToUse != null && mPhoneAccountRegistrar.isVoiceMailNumber(
-                    accountToUse.getAccountHandle(), call.getHandle().getSchemeSpecificPart())));
-
-            if (!isVoicemail && (isRttSettingOn() || (extras != null
-                    && extras.getBoolean(TelecomManager.EXTRA_START_CALL_WITH_RTT, false)))) {
-                Log.d(this, "Outgoing call requesting RTT, rtt setting is %b", isRttSettingOn());
-                if (accountToUse != null
-                        && accountToUse.hasCapabilities(PhoneAccount.CAPABILITY_RTT)) {
-                    call.createRttStreams();
-                }
-                // Even if the phone account doesn't support RTT yet, the connection manager might
-                // change that. Set this to check it later.
-                call.setRequestedToStartWithRtt();
-            }
-        }
-        setIntentExtrasAndStartTime(call, extras);
-        setCallSourceToAnalytics(call, originalIntent);
-
-        if ((isPotentialMMICode(handle) || isPotentialInCallMMICode) && !needsAccountSelection) {
-            // Do not add the call if it is a potential MMI code.
-            call.addListener(this);
-        } else if (!mCalls.contains(call)) {
-            // We check if mCalls already contains the call because we could potentially be reusing
-            // a call which was previously added (See {@link #reuseOutgoingCall}).
-            addCall(call);
-        }
-
-        return call;
+        });
     }
 
     /**
@@ -1302,55 +1620,80 @@
      * @return
      */
     @VisibleForTesting
-    public List<PhoneAccountHandle> findOutgoingCallPhoneAccount(
+    public CompletableFuture<List<PhoneAccountHandle>> findOutgoingCallPhoneAccount(
             PhoneAccountHandle targetPhoneAccountHandle, Uri handle, boolean isVideo,
             UserHandle initiatingUser) {
-        boolean isSelfManaged = isSelfManaged(targetPhoneAccountHandle, initiatingUser);
+        if (isSelfManaged(targetPhoneAccountHandle, initiatingUser)) {
+            return CompletableFuture.completedFuture(Arrays.asList(targetPhoneAccountHandle));
+        }
 
         List<PhoneAccountHandle> accounts;
-        if (!isSelfManaged) {
-            // Try to find a potential phone account, taking into account whether this is a video
-            // call.
-            accounts = constructPossiblePhoneAccounts(handle, initiatingUser, isVideo);
-            if (isVideo && accounts.size() == 0) {
-                // Placing a video call but no video capable accounts were found, so consider any
-                // call capable accounts (we can fallback to audio).
-                accounts = constructPossiblePhoneAccounts(handle, initiatingUser,
-                        false /* isVideo */);
-            }
-            Log.v(this, "findOutgoingCallPhoneAccount: accounts = " + accounts);
-
-            // Only dial with the requested phoneAccount if it is still valid. Otherwise treat this
-            // call as if a phoneAccount was not specified (does the default behavior instead).
-            // Note: We will not attempt to dial with a requested phoneAccount if it is disabled.
-            if (targetPhoneAccountHandle != null) {
-                if (!accounts.contains(targetPhoneAccountHandle)) {
-                    targetPhoneAccountHandle = null;
-                } else {
-                    // The target phone account is valid and was found.
-                    return Arrays.asList(targetPhoneAccountHandle);
-                }
-            }
-
-            if (targetPhoneAccountHandle == null && accounts.size() > 0) {
-                // No preset account, check if default exists that supports the URI scheme for the
-                // handle and verify it can be used.
-                if (accounts.size() > 1) {
-                    PhoneAccountHandle defaultPhoneAccountHandle =
-                            mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(
-                                    handle.getScheme(), initiatingUser);
-                    if (defaultPhoneAccountHandle != null &&
-                            accounts.contains(defaultPhoneAccountHandle)) {
-                        accounts.clear();
-                        accounts.add(defaultPhoneAccountHandle);
-                    }
-                }
-            }
-        } else {
-            // Self-managed ConnectionServices can only have a single potential account.
-            accounts = Arrays.asList(targetPhoneAccountHandle);
+        // Try to find a potential phone account, taking into account whether this is a video
+        // call.
+        accounts = constructPossiblePhoneAccounts(handle, initiatingUser, isVideo);
+        if (isVideo && accounts.size() == 0) {
+            // Placing a video call but no video capable accounts were found, so consider any
+            // call capable accounts (we can fallback to audio).
+            accounts = constructPossiblePhoneAccounts(handle, initiatingUser,
+                    false /* isVideo */);
         }
-        return accounts;
+        Log.v(this, "findOutgoingCallPhoneAccount: accounts = " + accounts);
+
+        // Only dial with the requested phoneAccount if it is still valid. Otherwise treat this
+        // call as if a phoneAccount was not specified (does the default behavior instead).
+        // Note: We will not attempt to dial with a requested phoneAccount if it is disabled.
+        if (targetPhoneAccountHandle != null) {
+            if (accounts.contains(targetPhoneAccountHandle)) {
+                // The target phone account is valid and was found.
+                return CompletableFuture.completedFuture(Arrays.asList(targetPhoneAccountHandle));
+            }
+        }
+        if (accounts.isEmpty() || accounts.size() == 1) {
+            return CompletableFuture.completedFuture(accounts);
+        }
+
+        // Do the query for whether there's a preferred contact
+        final CompletableFuture<PhoneAccountHandle> userPreferredAccountForContact =
+                new CompletableFuture<>();
+        final List<PhoneAccountHandle> possibleAccounts = accounts;
+        mCallerInfoLookupHelper.startLookup(handle,
+                new CallerInfoLookupHelper.OnQueryCompleteListener() {
+                    @Override
+                    public void onCallerInfoQueryComplete(Uri handle, CallerInfo info) {
+                        if (info.preferredPhoneAccountComponent != null &&
+                                info.preferredPhoneAccountId != null &&
+                                !info.preferredPhoneAccountId.isEmpty()) {
+                            PhoneAccountHandle contactDefaultHandle = new PhoneAccountHandle(
+                                    info.preferredPhoneAccountComponent,
+                                    info.preferredPhoneAccountId,
+                                    initiatingUser);
+                            userPreferredAccountForContact.complete(contactDefaultHandle);
+                        } else {
+                            userPreferredAccountForContact.complete(null);
+                        }
+                    }
+
+                    @Override
+                    public void onContactPhotoQueryComplete(Uri handle, CallerInfo info) {
+                        // ignore this
+                    }
+                });
+
+        return userPreferredAccountForContact.thenApply(phoneAccountHandle -> {
+            if (phoneAccountHandle != null) {
+                return Collections.singletonList(phoneAccountHandle);
+            }
+            // No preset account, check if default exists that supports the URI scheme for the
+            // handle and verify it can be used.
+            PhoneAccountHandle defaultPhoneAccountHandle =
+                    mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(
+                            handle.getScheme(), initiatingUser);
+            if (defaultPhoneAccountHandle != null &&
+                    possibleAccounts.contains(defaultPhoneAccountHandle)) {
+                return Collections.singletonList(defaultPhoneAccountHandle);
+            }
+            return possibleAccounts;
+        });
     }
 
     /**
@@ -1366,6 +1709,132 @@
         return targetPhoneAccount != null && targetPhoneAccount.isSelfManaged();
     }
 
+    public void onCallRedirectionComplete(Call call, Uri handle,
+                                          PhoneAccountHandle phoneAccountHandle,
+                                          GatewayInfo gatewayInfo, boolean speakerphoneOn,
+                                          int videoState, boolean shouldCancelCall,
+                                          String uiAction) {
+        Log.i(this, "onCallRedirectionComplete for Call %s with handle %s" +
+                " and phoneAccountHandle %s", call, handle, phoneAccountHandle);
+
+        boolean endEarly = false;
+        String disconnectReason = "";
+
+        String callRedirectionApp = mRoleManagerAdapter.getDefaultCallRedirectionApp();
+
+        if (shouldCancelCall) {
+            Log.w(this, "onCallRedirectionComplete: call is canceled");
+            endEarly = true;
+            disconnectReason = "Canceled from Call Redirection Service";
+            // Show UX when user-defined call redirection service does not response; the UX
+            // is not needed to show if the call is disconnected (e.g. by the user)
+            if (uiAction.equals(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT)
+                    && !call.isDisconnected()) {
+                Intent timeoutIntent = new Intent(mContext,
+                        CallRedirectionTimeoutDialogActivity.class);
+                timeoutIntent.putExtra(
+                        CallRedirectionTimeoutDialogActivity.EXTRA_REDIRECTION_APP_NAME,
+                        mRoleManagerAdapter.getApplicationLabelForPackageName(callRedirectionApp));
+                timeoutIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                mContext.startActivityAsUser(timeoutIntent, UserHandle.CURRENT);
+            }
+        } else if (handle == null) {
+            Log.w(this, "onCallRedirectionComplete: handle is null");
+            endEarly = true;
+            disconnectReason = "Null handle from Call Redirection Service";
+        } else if (phoneAccountHandle == null) {
+            Log.w(this, "onCallRedirectionComplete: phoneAccountHandle is null");
+            endEarly = true;
+            disconnectReason = "Null phoneAccountHandle from Call Redirection Service";
+        } else if (mPhoneNumberUtilsAdapter.isPotentialLocalEmergencyNumber(mContext,
+                handle.getSchemeSpecificPart())) {
+            Log.w(this, "onCallRedirectionComplete: emergency number %s is redirected from Call"
+                    + " Redirection Service", handle.getSchemeSpecificPart());
+            endEarly = true;
+            disconnectReason = "Emergency number is redirected from Call Redirection Service";
+        }
+        if (endEarly) {
+            if (call != null) {
+                call.disconnect(disconnectReason);
+            }
+            return;
+        }
+
+        // If this call is already disconnected then we have nothing more to do.
+        if (call.isDisconnected()) {
+            Log.w(this, "onCallRedirectionComplete: Call has already been disconnected,"
+                    + " ignore the call redirection %s", call);
+            return;
+        }
+
+        if (uiAction.equals(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_ASK_FOR_CONFIRM)) {
+            Log.addEvent(call, LogUtils.Events.REDIRECTION_USER_CONFIRMATION);
+            mPendingRedirectedOutgoingCall = call;
+
+            mPendingRedirectedOutgoingCallInfo.put(call.getId(),
+                    new Runnable("CM.oCRC", mLock) {
+                        @Override
+                        public void loggedRun() {
+                            Log.addEvent(call, LogUtils.Events.REDIRECTION_USER_CONFIRMED);
+                            call.setTargetPhoneAccount(phoneAccountHandle);
+                            placeOutgoingCall(call, handle, gatewayInfo, speakerphoneOn,
+                                    videoState);
+                        }
+                    });
+
+            mPendingUnredirectedOutgoingCallInfo.put(call.getId(),
+                    new Runnable("CM.oCRC", mLock) {
+                        @Override
+                        public void loggedRun() {
+                            call.setTargetPhoneAccount(phoneAccountHandle);
+                            placeOutgoingCall(call, handle, null, speakerphoneOn,
+                                    videoState);
+                        }
+                    });
+
+            Log.i(this, "onCallRedirectionComplete: UI_TYPE_USER_DEFINED_ASK_FOR_CONFIRM "
+                            + "callId=%s, callRedirectionAppName=%s",
+                    call.getId(), callRedirectionApp);
+
+            Intent confirmIntent = new Intent(mContext,
+                    CallRedirectionConfirmDialogActivity.class);
+            confirmIntent.putExtra(
+                    CallRedirectionConfirmDialogActivity.EXTRA_REDIRECTION_OUTGOING_CALL_ID,
+                    call.getId());
+            confirmIntent.putExtra(CallRedirectionConfirmDialogActivity.EXTRA_REDIRECTION_APP_NAME,
+                    mRoleManagerAdapter.getApplicationLabelForPackageName(callRedirectionApp));
+            confirmIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            mContext.startActivityAsUser(confirmIntent, UserHandle.CURRENT);
+        } else {
+            call.setTargetPhoneAccount(phoneAccountHandle);
+            placeOutgoingCall(call, handle, gatewayInfo, speakerphoneOn, videoState);
+        }
+    }
+
+    public void processRedirectedOutgoingCallAfterUserInteraction(String callId, String action) {
+        Log.i(this, "processRedirectedOutgoingCallAfterUserInteraction for Call ID %s", callId);
+        if (mPendingRedirectedOutgoingCall != null && mPendingRedirectedOutgoingCall.getId()
+                .equals(callId)) {
+            if (action.equals(TelecomBroadcastIntentProcessor.ACTION_PLACE_REDIRECTED_CALL)) {
+                mHandler.post(mPendingRedirectedOutgoingCallInfo.get(callId).prepare());
+            } else if (action.equals(
+                    TelecomBroadcastIntentProcessor.ACTION_PLACE_UNREDIRECTED_CALL)) {
+                mHandler.post(mPendingUnredirectedOutgoingCallInfo.get(callId).prepare());
+            } else if (action.equals(
+                    TelecomBroadcastIntentProcessor.ACTION_CANCEL_REDIRECTED_CALL)) {
+                Log.addEvent(mPendingRedirectedOutgoingCall,
+                        LogUtils.Events.REDIRECTION_USER_CANCELLED);
+                mPendingRedirectedOutgoingCall.disconnect("User canceled the redirected call.");
+            }
+            mPendingRedirectedOutgoingCall = null;
+            mPendingRedirectedOutgoingCallInfo.remove(callId);
+            mPendingUnredirectedOutgoingCallInfo.remove(callId);
+        } else {
+            Log.w(this, "processRedirectedOutgoingCallAfterUserInteraction for non-matched Call ID"
+                    + " %s with handle %s and phoneAccountHandle %s", callId);
+        }
+    }
+
     /**
      * Attempts to issue/connect the specified call.
      *
@@ -1474,7 +1943,7 @@
         } else {
             // Hold or disconnect the active call and request call focus for the incoming call.
             Call activeCall = (Call) mConnectionSvrFocusMgr.getCurrentFocusCall();
-            Log.d(this, "Incoming call = %s Ongoing call %s", call, activeCall);
+            Log.d(this, "answerCall: Incoming call = %s Ongoing call %s", call, activeCall);
             holdActiveCallForNewCall(call);
             mConnectionSvrFocusMgr.requestFocus(
                     call,
@@ -1609,6 +2078,15 @@
         } else {
             mLocallyDisconnectingCalls.add(call);
             call.disconnect();
+            // Cancel any of the outgoing call futures if they're still around.
+            if (mPendingCallConfirm != null && !mPendingCallConfirm.isDone()) {
+                mPendingCallConfirm.complete(null);
+                mPendingCallConfirm = null;
+            }
+            if (mPendingAccountSelection != null && !mPendingAccountSelection.isDone()) {
+                mPendingAccountSelection.complete(null);
+                mPendingAccountSelection = null;
+            }
         }
     }
 
@@ -1664,7 +2142,7 @@
         } else {
             Call activeCall = (Call) mConnectionSvrFocusMgr.getCurrentFocusCall();
             String activeCallId = null;
-            if (activeCall != null) {
+            if (activeCall != null && !activeCall.isLocallyDisconnecting()) {
                 activeCallId = activeCall.getId();
                 if (canHold(activeCall)) {
                     activeCall.hold("Swap to " + call.getId());
@@ -1674,8 +2152,17 @@
                     // This call does not support hold. If it is from a different connection
                     // service, then disconnect it, otherwise invoke call.hold() and allow the
                     // connection service to handle the situation.
-                    if (activeCall.getConnectionService() != call.getConnectionService()) {
-                        activeCall.disconnect("Swap to " + call.getId());
+                    if (!PhoneAccountHandle.areFromSamePackage(activeCall.getTargetPhoneAccount(),
+                            call.getTargetPhoneAccount())) {
+                        if (!activeCall.isEmergencyCall()) {
+                            activeCall.disconnect("Swap to " + call.getId());
+                        } else {
+                            Log.w(this, "unholdCall: % is an emergency call, aborting swap to %s",
+                                    activeCall.getId(), call.getId());
+                            // Don't unhold the call as requested; we don't want to drop an
+                            // emergency call.
+                            return;
+                        }
                     } else {
                         activeCall.hold("Swap to " + call.getId());
                     }
@@ -1830,51 +2317,15 @@
         if (!mCalls.contains(call)) {
             Log.i(this, "Attempted to add account to unknown call %s", call);
         } else {
-            call.setTargetPhoneAccount(account);
-            PhoneAccount realPhoneAccount =
-                    mPhoneAccountRegistrar.getPhoneAccountUnchecked(account);
-            if (realPhoneAccount != null && realPhoneAccount.getExtras() != null
-                    && realPhoneAccount.getExtras()
-                    .getBoolean(PhoneAccount.EXTRA_ALWAYS_USE_VOIP_AUDIO_MODE)) {
-                Log.d("phoneAccountSelected: default to voip mode for call %s", call.getId());
-                call.setIsVoipAudioMode(true);
-            }
-
-            boolean isVoicemail = (call.getHandle() != null)
-                    && (PhoneAccount.SCHEME_VOICEMAIL.equals(call.getHandle().getScheme())
-                    || (realPhoneAccount != null && mPhoneAccountRegistrar.isVoiceMailNumber(
-                    realPhoneAccount.getAccountHandle(),
-                    call.getHandle().getSchemeSpecificPart())));
-
-            if (!isVoicemail && (isRttSettingOn() || call.getIntentExtras()
-                    .getBoolean(TelecomManager.EXTRA_START_CALL_WITH_RTT, false))) {
-                Log.d(this, "Outgoing call after account selection requesting RTT," +
-                        " rtt setting is %b", isRttSettingOn());
-                if (realPhoneAccount != null
-                        && realPhoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_RTT)) {
-                    call.createRttStreams();
-                }
-                // Even if the phone account doesn't support RTT yet, the connection manager might
-                // change that. Set this to check it later.
-                call.setRequestedToStartWithRtt();
-            }
-
-            if (!call.isNewOutgoingCallIntentBroadcastDone()) {
-                return;
-            }
-
-            // Note: emergency calls never go through account selection dialog so they never
-            // arrive here.
-            if (makeRoomForOutgoingCall(call, false /* isEmergencyCall */)) {
-                call.startCreateConnection(mPhoneAccountRegistrar);
-            } else {
-                call.disconnect("no room");
-            }
-
             if (setDefault) {
                 mPhoneAccountRegistrar
                         .setUserSelectedOutgoingPhoneAccount(account, call.getInitiatingUser());
             }
+
+            if (mPendingAccountSelection != null) {
+                mPendingAccountSelection.complete(Pair.create(call, account));
+                mPendingAccountSelection = null;
+            }
         }
     }
 
@@ -1929,7 +2380,8 @@
                 activeCall.hold();
                 return true;
             } else if (supportsHold(activeCall)
-                    && activeCall.getConnectionService() == call.getConnectionService()) {
+                    && PhoneAccountHandle.areFromSamePackage(activeCall.getTargetPhoneAccount(),
+                        call.getTargetPhoneAccount())) {
 
                 // Handle the case where the active call and the new call are from the same CS, and
                 // the currently active call supports hold but cannot currently be held.
@@ -1941,7 +2393,7 @@
                 // Call C - Incoming
                 // Here we need to disconnect A prior to holding B so that C can be answered.
                 // This case is driven by telephony requirements ultimately.
-                Call heldCall = getHeldCallByConnectionService(call.getConnectionService());
+                Call heldCall = getHeldCallByConnectionService(call.getTargetPhoneAccount());
                 if (heldCall != null) {
                     heldCall.disconnect();
                     Log.i(this, "holdActiveCallForNewCall: Disconnect held call %s before "
@@ -1956,10 +2408,21 @@
                 // This call does not support hold. If it is from a different connection
                 // service, then disconnect it, otherwise allow the connection service to
                 // figure out the right states.
-                if (activeCall.getConnectionService() != call.getConnectionService()) {
+                if (!PhoneAccountHandle.areFromSamePackage(activeCall.getTargetPhoneAccount(),
+                        call.getTargetPhoneAccount())) {
                     Log.i(this, "holdActiveCallForNewCall: disconnecting %s so that %s can be "
                             + "made active.", activeCall.getId(), call.getId());
-                    activeCall.disconnect();
+                    if (!activeCall.isEmergencyCall()) {
+                        activeCall.disconnect();
+                    } else {
+                        // It's not possible to hold the active call, and its an emergency call so
+                        // we will silently reject the incoming call instead of answering it.
+                        Log.w(this, "holdActiveCallForNewCall: rejecting incoming call %s as "
+                                + "the active call is an emergency call and it cannot be held.",
+                                call.getId());
+                        call.reject(false /* rejectWithMessage */, "" /* message */,
+                                "active emergency call can't be held");
+                    }
                 }
             }
         }
@@ -2007,31 +2470,33 @@
      * Removes an existing disconnected call, and notifies the in-call app.
      */
     void markCallAsRemoved(Call call) {
-        call.maybeCleanupHandover();
-        removeCall(call);
-        Call foregroundCall = mCallAudioManager.getPossiblyHeldForegroundCall();
-        if (mLocallyDisconnectingCalls.contains(call)) {
-            boolean isDisconnectingChildCall = call.isDisconnectingChildCall();
-            Log.v(this, "markCallAsRemoved: isDisconnectingChildCall = "
-                + isDisconnectingChildCall + "call -> %s", call);
-            mLocallyDisconnectingCalls.remove(call);
-            // Auto-unhold the foreground call due to a locally disconnected call, except if the
-            // call which was disconnected is a member of a conference (don't want to auto un-hold
-            // the conference if we remove a member of the conference).
-            if (!isDisconnectingChildCall && foregroundCall != null
-                    && foregroundCall.getState() == CallState.ON_HOLD) {
+        mInCallController.getBindingFuture().thenRunAsync(() -> {
+            call.maybeCleanupHandover();
+            removeCall(call);
+            Call foregroundCall = mCallAudioManager.getPossiblyHeldForegroundCall();
+            if (mLocallyDisconnectingCalls.contains(call)) {
+                boolean isDisconnectingChildCall = call.isDisconnectingChildCall();
+                Log.v(this, "markCallAsRemoved: isDisconnectingChildCall = "
+                        + isDisconnectingChildCall + "call -> %s", call);
+                mLocallyDisconnectingCalls.remove(call);
+                // Auto-unhold the foreground call due to a locally disconnected call, except if the
+                // call which was disconnected is a member of a conference (don't want to auto
+                // un-hold the conference if we remove a member of the conference).
+                if (!isDisconnectingChildCall && foregroundCall != null
+                        && foregroundCall.getState() == CallState.ON_HOLD) {
+                    foregroundCall.unhold();
+                }
+            } else if (foregroundCall != null &&
+                    !foregroundCall.can(Connection.CAPABILITY_SUPPORT_HOLD) &&
+                    foregroundCall.getState() == CallState.ON_HOLD) {
+
+                // The new foreground call is on hold, however the carrier does not display the hold
+                // button in the UI.  Therefore, we need to auto unhold the held call since the user
+                // has no means of unholding it themselves.
+                Log.i(this, "Auto-unholding held foreground call (call doesn't support hold)");
                 foregroundCall.unhold();
             }
-        } else if (foregroundCall != null &&
-                !foregroundCall.can(Connection.CAPABILITY_SUPPORT_HOLD)  &&
-                foregroundCall.getState() == CallState.ON_HOLD) {
-
-            // The new foreground call is on hold, however the carrier does not display the hold
-            // button in the UI.  Therefore, we need to auto unhold the held call since the user has
-            // no means of unholding it themselves.
-            Log.i(this, "Auto-unholding held foreground call (call doesn't support hold)");
-            foregroundCall.unhold();
-        }
+        }, new LoggedHandlerExecutor(mHandler, "CM.mCAR", mLock));
     }
 
     /**
@@ -2039,7 +2504,7 @@
      * indicate to the user that the call cannot me placed due to an ongoing call in another app.
      *
      * Used when there are ongoing self-managed calls and the user tries to make an outgoing managed
-     * call.  Called by {@link #startCallConfirmation(Call)} when the user is already confirming an
+     * call.  Called by {@link #startCallConfirmation} when the user is already confirming an
      * outgoing call.  Realistically this should almost never be called since in practice the user
      * won't make multiple outgoing calls at the same time.
      *
@@ -2074,7 +2539,8 @@
                 if (call.getConnectionService() == service) {
                     if (call.getState() != CallState.DISCONNECTED) {
                         markCallAsDisconnected(call, new DisconnectCause(DisconnectCause.ERROR,
-                                "CS_DEATH"));
+                                null /* message */, null /* description */, "CS_DEATH",
+                                ToneGenerator.TONE_PROP_PROMPT));
                     }
                     markCallAsRemoved(call);
                 }
@@ -2105,14 +2571,25 @@
     }
 
     boolean hasRingingCall() {
-        return getFirstCallWithState(CallState.RINGING) != null;
+        return getFirstCallWithState(CallState.RINGING, CallState.ANSWERED) != null;
     }
 
-    boolean onMediaButton(int type) {
+    @VisibleForTesting
+    public boolean onMediaButton(int type) {
         if (hasAnyCalls()) {
             Call ringingCall = getFirstCallWithState(CallState.RINGING);
             if (HeadsetMediaButton.SHORT_PRESS == type) {
                 if (ringingCall == null) {
+                    Call activeCall = getFirstCallWithState(CallState.ACTIVE);
+                    Call onHoldCall = getFirstCallWithState(CallState.ON_HOLD);
+                    if (activeCall != null && onHoldCall != null) {
+                        // Two calls, short-press -> switch calls
+                        Log.addEvent(onHoldCall, LogUtils.Events.INFO,
+                                "two calls, media btn short press - switch call.");
+                        unholdCall(onHoldCall);
+                        return true;
+                    }
+
                     Call callToHangup = getFirstCallWithState(CallState.RINGING, CallState.DIALING,
                             CallState.PULLING, CallState.ACTIVE, CallState.ON_HOLD);
                     Log.addEvent(callToHangup, LogUtils.Events.INFO,
@@ -2131,6 +2608,16 @@
                             LogUtils.Events.INFO, "media btn long press - reject");
                     ringingCall.reject(false, null);
                 } else {
+                    Call activeCall = getFirstCallWithState(CallState.ACTIVE);
+                    Call onHoldCall = getFirstCallWithState(CallState.ON_HOLD);
+                    if (activeCall != null && onHoldCall != null) {
+                        // Two calls, long-press -> end current call
+                        Log.addEvent(activeCall, LogUtils.Events.INFO,
+                                "two calls, media btn long press - end current call.");
+                        disconnectCall(activeCall);
+                        return true;
+                    }
+
                     Log.addEvent(getForegroundCall(), LogUtils.Events.INFO,
                             "media btn long press - mute");
                     mCallAudioManager.toggleMute();
@@ -2190,7 +2677,7 @@
 
     @VisibleForTesting
     public Call getRingingCall() {
-        return getFirstCallWithState(CallState.RINGING);
+        return getFirstCallWithState(CallState.RINGING, CallState.ANSWERED);
     }
 
     public Call getActiveCall() {
@@ -2206,9 +2693,11 @@
         return getFirstCallWithState(CallState.ON_HOLD);
     }
 
-    public Call getHeldCallByConnectionService(ConnectionServiceWrapper connSvr) {
+    public Call getHeldCallByConnectionService(PhoneAccountHandle targetPhoneAccount) {
         Optional<Call> heldCall = mCalls.stream()
-                .filter(call -> call.getConnectionService() == connSvr
+                .filter(call -> PhoneAccountHandle.areFromSamePackage(call.getTargetPhoneAccount(),
+                        targetPhoneAccount)
+                        && call.getParentCall() == null
                         && call.getState() == CallState.ON_HOLD)
                 .findFirst();
         return heldCall.isPresent() ? heldCall.get() : null;
@@ -2240,6 +2729,16 @@
         return mPhoneNumberUtilsAdapter;
     }
 
+    @VisibleForTesting
+    public CompletableFuture<Call> getLatestPostSelectionProcessingFuture() {
+        return mLatestPostSelectionProcessingFuture;
+    }
+
+    @VisibleForTesting
+    public CompletableFuture getLatestPreAccountSelectionFuture() {
+        return mLatestPreAccountSelectionFuture;
+    }
+
     /**
      * Returns the first call that it finds with the given states. The states are treated as having
      * priority order so that any call with the first state will be returned before any call with
@@ -2299,8 +2798,6 @@
                 this,
                 mLock,
                 mConnectionServiceRepository,
-                mContactsAsyncHelper,
-                mCallerInfoAsyncQueryFactory,
                 mPhoneNumberUtilsAdapter,
                 null /* handle */,
                 null /* gatewayInfo */,
@@ -2346,7 +2843,8 @@
      *
      * @return The {@link PhoneAccountRegistrar}.
      */
-    PhoneAccountRegistrar getPhoneAccountRegistrar() {
+    @VisibleForTesting
+    public PhoneAccountRegistrar getPhoneAccountRegistrar() {
         return mPhoneAccountRegistrar;
     }
 
@@ -2370,7 +2868,7 @@
      * Reject an incoming call and manually add it to the Call Log.
      * @param incomingCall Incoming call that has been rejected
      */
-    private void rejectCallAndLog(Call incomingCall) {
+    private void rejectCallAndLog(Call incomingCall, CallFilteringResult result) {
         if (incomingCall.getConnectionService() != null) {
             // Only reject the call if it has not already been destroyed.  If a call ends while
             // incoming call filtering is taking place, it is possible that the call has already
@@ -2385,7 +2883,7 @@
         // call notifier and the call logger manually.
         // Do we need missed call notification for direct to Voicemail calls?
         mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE,
-                true /*showNotificationForMissedCall*/);
+                true /*showNotificationForMissedCall*/, result);
     }
 
     /**
@@ -2480,27 +2978,31 @@
             // into a well-defined state machine.
             // TODO: Define expected state transitions here, and log when an
             // unexpected transition occurs.
-            call.setState(newState, tag);
-            maybeShowErrorDialogOnDisconnect(call);
+            if (call.setState(newState, tag)) {
+                maybeShowErrorDialogOnDisconnect(call);
 
-            Trace.beginSection("onCallStateChanged");
+                Trace.beginSection("onCallStateChanged");
 
-            maybeHandleHandover(call, newState);
+                maybeHandleHandover(call, newState);
 
-            // Only broadcast state change for calls that are being tracked.
-            if (mCalls.contains(call)) {
-                updateCanAddCall();
-                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();
+                // Only broadcast state change for calls that are being tracked.
+                if (mCalls.contains(call)) {
+                    updateCanAddCall();
+                    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");
             }
-            Trace.endSection();
         }
     }
 
@@ -2746,13 +3248,13 @@
 
     private boolean hasMaximumManagedRingingCalls(Call exceptCall) {
         return MAXIMUM_RINGING_CALLS <= getNumCallsWithState(false /* isSelfManaged */, exceptCall,
-                null /* phoneAccountHandle */, CallState.RINGING);
+                null /* phoneAccountHandle */, CallState.RINGING, CallState.ANSWERED);
     }
 
     private boolean hasMaximumSelfManagedRingingCalls(Call exceptCall,
                                                       PhoneAccountHandle phoneAccountHandle) {
         return MAXIMUM_RINGING_CALLS <= getNumCallsWithState(true /* isSelfManaged */, exceptCall,
-                phoneAccountHandle, CallState.RINGING);
+                phoneAccountHandle, CallState.RINGING, CallState.ANSWERED);
     }
 
     private boolean hasMaximumOutgoingCalls(Call exceptCall) {
@@ -2912,7 +3414,8 @@
             // First thing, if we are trying to make a call with the same phone account as the live
             // call, then allow it so that the connection service can make its own decision about
             // how to handle the new call relative to the current one.
-            if (Objects.equals(liveCallPhoneAccount, call.getTargetPhoneAccount())) {
+            if (PhoneAccountHandle.areFromSamePackage(liveCallPhoneAccount,
+                    call.getTargetPhoneAccount())) {
                 Log.i(this, "makeRoomForOutgoingCall: phoneAccount matches.");
                 call.getAnalytics().setCallIsAdditional(true);
                 liveCall.getAnalytics().setCallIsInterrupted(true);
@@ -3011,8 +3514,6 @@
                 this,
                 mLock,
                 mConnectionServiceRepository,
-                mContactsAsyncHelper,
-                mCallerInfoAsyncQueryFactory,
                 mPhoneNumberUtilsAdapter,
                 connection.getHandle() /* handle */,
                 null /* gatewayInfo */,
@@ -3030,6 +3531,7 @@
 
         setCallState(call, Call.getStateFromConnectionState(connection.getState()),
                 "existing connection");
+        call.setVideoState(connection.getVideoState());
         call.setConnectionCapabilities(connection.getConnectionCapabilities());
         call.setConnectionProperties(connection.getConnectionProperties());
         call.setHandle(connection.getHandle(), connection.getHandlePresentation());
@@ -3118,6 +3620,7 @@
     public void onUserSwitch(UserHandle userHandle) {
         mCurrentUserHandle = userHandle;
         mMissedCallNotifier.setCurrentUserHandle(userHandle);
+        mRoleManagerAdapter.setCurrentUserHandle(userHandle);
         final UserManager userManager = UserManager.get(mContext);
         List<UserInfo> profiles = userManager.getEnabledProfiles(userHandle.getIdentifier());
         for (UserInfo profile : profiles) {
@@ -3139,6 +3642,14 @@
         return mLock;
     }
 
+    public Timeouts.Adapter getTimeoutsAdapter() {
+        return mTimeoutsAdapter;
+    }
+
+    public SystemStateHelper getSystemStateHelper() {
+        return mSystemStateHelper;
+    }
+
     private void reloadMissedCallsOfUser(UserHandle userHandle) {
         mMissedCallNotifier.reloadFromDatabase(mCallerInfoLookupHelper,
                 new MissedCallNotifier.CallInfoFactory(), userHandle);
@@ -3246,7 +3757,7 @@
 
     /**
      * Used to confirm creation of an outgoing call which was marked as pending confirmation in
-     * {@link #startOutgoingCall(Uri, PhoneAccountHandle, Bundle, UserHandle, Intent)}.
+     * {@link #startOutgoingCall(Uri, PhoneAccountHandle, Bundle, UserHandle, Intent, String)}.
      * Called via {@link TelecomBroadcastIntentProcessor} for a call which was confirmed via
      * {@link ConfirmCallDialogActivity}.
      * @param callId The call ID of the call to confirm.
@@ -3255,23 +3766,20 @@
         Log.i(this, "confirmPendingCall: callId=%s", callId);
         if (mPendingCall != null && mPendingCall.getId().equals(callId)) {
             Log.addEvent(mPendingCall, LogUtils.Events.USER_CONFIRMED);
-            addCall(mPendingCall);
 
             // We are going to place the new outgoing call, so disconnect any ongoing self-managed
             // calls which are ongoing at this time.
             disconnectSelfManagedCalls("outgoing call " + callId);
 
-            // Kick of the new outgoing call intent from where it left off prior to confirming the
-            // call.
-            CallIntentProcessor.sendNewOutgoingCallIntent(mContext, mPendingCall, this,
-                    mPendingCall.getOriginalCallIntent());
+            mPendingCallConfirm.complete(mPendingCall);
+            mPendingCallConfirm = null;
             mPendingCall = null;
         }
     }
 
     /**
      * Used to cancel an outgoing call which was marked as pending confirmation in
-     * {@link #startOutgoingCall(Uri, PhoneAccountHandle, Bundle, UserHandle, Intent)}.
+     * {@link #startOutgoingCall(Uri, PhoneAccountHandle, Bundle, UserHandle, Intent, String)}.
      * Called via {@link TelecomBroadcastIntentProcessor} for a call which was confirmed via
      * {@link ConfirmCallDialogActivity}.
      * @param callId The call ID of the call to cancel.
@@ -3283,25 +3791,29 @@
             markCallAsDisconnected(mPendingCall, new DisconnectCause(DisconnectCause.CANCELED));
             markCallAsRemoved(mPendingCall);
             mPendingCall = null;
+            mPendingCallConfirm.complete(null);
+            mPendingCallConfirm = null;
         }
     }
 
     /**
-     * Called from {@link #startOutgoingCall(Uri, PhoneAccountHandle, Bundle, UserHandle, Intent)} when
+     * Called from {@link #startOutgoingCall(Uri, PhoneAccountHandle, Bundle, UserHandle, Intent, String)} when
      * a managed call is added while there are ongoing self-managed calls.  Starts
      * {@link ConfirmCallDialogActivity} to prompt the user to see if they wish to place the
      * outgoing call or not.
      * @param call The call to confirm.
      */
-    private void startCallConfirmation(Call call) {
+    private void startCallConfirmation(Call call, CompletableFuture<Call> confirmationFuture) {
         if (mPendingCall != null) {
             Log.i(this, "startCallConfirmation: call %s is already pending; disconnecting %s",
                     mPendingCall.getId(), call.getId());
             markCallDisconnectedDueToSelfManagedCall(call);
+            confirmationFuture.complete(null);
             return;
         }
         Log.addEvent(call, LogUtils.Events.USER_CONFIRMATION);
         mPendingCall = call;
+        mPendingCallConfirm = confirmationFuture;
 
         // Figure out the name of the app in charge of the self-managed call(s).
         Call activeCall = (Call) mConnectionSvrFocusMgr.getCurrentFocusCall();
@@ -3392,6 +3904,14 @@
             mConnectionServiceRepository.dump(pw);
             pw.decreaseIndent();
         }
+
+        if (mRoleManagerAdapter != null && mRoleManagerAdapter instanceof RoleManagerAdapterImpl) {
+            RoleManagerAdapterImpl impl = (RoleManagerAdapterImpl) mRoleManagerAdapter;
+            pw.println("mRoleManager:");
+            pw.increaseIndent();
+            impl.dump(pw);
+            pw.decreaseIndent();
+        }
     }
 
     /**
@@ -3442,6 +3962,18 @@
         call.getAnalytics().setCallSource(callSource);
     }
 
+    private boolean isVoicemail(Uri callHandle, PhoneAccount phoneAccount) {
+        if (callHandle == null) {
+            return false;
+        }
+        if (PhoneAccount.SCHEME_VOICEMAIL.equals(callHandle.getScheme())) {
+            return true;
+        }
+        return phoneAccount != null && mPhoneAccountRegistrar.isVoiceMailNumber(
+                phoneAccount.getAccountHandle(),
+                callHandle.getSchemeSpecificPart());
+    }
+
     /**
      * Notifies the {@link android.telecom.ConnectionService} associated with a
      * {@link PhoneAccountHandle} that the attempt to create a new connection has failed.
@@ -3496,41 +4028,114 @@
                                           PhoneAccountHandle handoverToHandle,
                                           int videoState, Bundle initiatingExtras) {
 
-        boolean isHandoverFromSupported = isHandoverFromPhoneAccountSupported(
-                handoverFromCall.getTargetPhoneAccount());
-        boolean isHandoverToSupported = isHandoverToPhoneAccountSupported(handoverToHandle);
-
-        if (!isHandoverFromSupported || !isHandoverToSupported || hasEmergencyCall()) {
-            handoverFromCall.sendCallEvent(android.telecom.Call.EVENT_HANDOVER_FAILED, null);
-            return;
-        }
-
-        Log.addEvent(handoverFromCall, LogUtils.Events.HANDOVER_REQUEST, handoverToHandle);
-
-        Bundle extras = new Bundle();
-        extras.putBoolean(TelecomManager.EXTRA_IS_HANDOVER, true);
-        extras.putParcelable(TelecomManager.EXTRA_HANDOVER_FROM_PHONE_ACCOUNT,
-                handoverFromCall.getTargetPhoneAccount());
-        extras.putInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState);
-        if (initiatingExtras != null) {
-            extras.putAll(initiatingExtras);
-        }
-        extras.putParcelable(TelecomManager.EXTRA_CALL_AUDIO_STATE,
-                mCallAudioManager.getCallAudioState());
-        Call handoverToCall = startOutgoingCall(handoverFromCall.getHandle(), handoverToHandle,
-                extras, getCurrentUserHandle(), null /* originalIntent */);
-        Log.addEvent(handoverFromCall, LogUtils.Events.START_HANDOVER,
-                "handOverFrom=%s, handOverTo=%s", handoverFromCall.getId(), handoverToCall.getId());
-        handoverFromCall.setHandoverDestinationCall(handoverToCall);
-        handoverFromCall.setHandoverState(HandoverState.HANDOVER_FROM_STARTED);
-        handoverToCall.setHandoverState(HandoverState.HANDOVER_TO_STARTED);
-        handoverToCall.setHandoverSourceCall(handoverFromCall);
-        handoverToCall.setNewOutgoingCallIntentBroadcastIsDone();
-        placeOutgoingCall(handoverToCall, handoverToCall.getHandle(), null /* gatewayInfo */,
-                false /* startwithSpeaker */,
-                videoState);
+        handoverFromCall.sendCallEvent(android.telecom.Call.EVENT_HANDOVER_FAILED, null);
+        Log.addEvent(handoverFromCall, LogUtils.Events.HANDOVER_REQUEST, "legacy request denied");
     }
 
+    public Call createHandoverCall(Uri handle, PhoneAccountHandle handoverToHandle,
+            Bundle extras, UserHandle initiatingUser) {
+        boolean isReusedCall = true;
+        Call call = reuseOutgoingCall(handle);
+
+        PhoneAccount account =
+                mPhoneAccountRegistrar.getPhoneAccount(handoverToHandle, initiatingUser);
+        boolean isSelfManaged = account != null && account.isSelfManaged();
+
+        // Create a call with original handle. The handle may be changed when the call is attached
+        // to a connection service, but in most cases will remain the same.
+        if (call == null) {
+            call = new Call(getNextCallId(), mContext,
+                    this,
+                    mLock,
+                    mConnectionServiceRepository,
+                    mPhoneNumberUtilsAdapter,
+                    handle,
+                    null /* gatewayInfo */,
+                    null /* connectionManagerPhoneAccount */,
+                    null /* handoverToHandle */,
+                    Call.CALL_DIRECTION_OUTGOING /* callDirection */,
+                    false /* forceAttachToExistingConnection */,
+                    false, /* isConference */
+                    mClockProxy);
+            call.initAnalytics(null);
+
+            // Ensure new calls related to self-managed calls/connections are set as such.  This
+            // will be overridden when the actual connection is returned in startCreateConnection,
+            // however doing this now ensures the logs and any other logic will treat this call as
+            // self-managed from the moment it is created.
+            call.setIsSelfManaged(isSelfManaged);
+            if (isSelfManaged) {
+                // Self-managed calls will ALWAYS use voip audio mode.
+                call.setIsVoipAudioMode(true);
+            }
+            call.setInitiatingUser(initiatingUser);
+            isReusedCall = false;
+        }
+
+        int videoState = VideoProfile.STATE_AUDIO_ONLY;
+        if (extras != null) {
+            // Set the video state on the call early so that when it is added to the InCall UI the
+            // UI knows to configure itself as a video call immediately.
+            videoState = extras.getInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
+                    VideoProfile.STATE_AUDIO_ONLY);
+
+            // If this is an emergency video call, we need to check if the phone account supports
+            // emergency video calling.
+            // Also, ensure we don't try to place an outgoing call with video if video is not
+            // supported.
+            if (VideoProfile.isVideo(videoState)) {
+                if (call.isEmergencyCall() && account != null &&
+                        !account.hasCapabilities(PhoneAccount.CAPABILITY_EMERGENCY_VIDEO_CALLING)) {
+                    // Phone account doesn't support emergency video calling, so fallback to
+                    // audio-only now to prevent the InCall UI from setting up video surfaces
+                    // needlessly.
+                    Log.i(this, "startOutgoingCall - emergency video calls not supported; " +
+                            "falling back to audio-only");
+                    videoState = VideoProfile.STATE_AUDIO_ONLY;
+                } else if (account != null &&
+                        !account.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING)) {
+                    // Phone account doesn't support video calling, so fallback to audio-only.
+                    Log.i(this, "startOutgoingCall - video calls not supported; fallback to " +
+                            "audio-only.");
+                    videoState = VideoProfile.STATE_AUDIO_ONLY;
+                }
+            }
+
+            call.setVideoState(videoState);
+        }
+
+        call.setTargetPhoneAccount(handoverToHandle);
+
+        // If there's no more room for a handover, just fail.
+        if ((!isReusedCall && !makeRoomForOutgoingCall(call, call.isEmergencyCall()))) {
+            return null;
+        }
+
+        PhoneAccount accountToUse =
+                mPhoneAccountRegistrar.getPhoneAccount(handoverToHandle, initiatingUser);
+        if (accountToUse != null && accountToUse.getExtras() != null) {
+            if (accountToUse.getExtras()
+                    .getBoolean(PhoneAccount.EXTRA_ALWAYS_USE_VOIP_AUDIO_MODE)) {
+                Log.d(this, "startOutgoingCall: defaulting to voip mode for call %s",
+                        call.getId());
+                call.setIsVoipAudioMode(true);
+            }
+        }
+
+        call.setState(
+                CallState.CONNECTING,
+                handoverToHandle == null ? "no-handle" : handoverToHandle.toString());
+
+        setIntentExtrasAndStartTime(call, extras);
+
+        if (!mCalls.contains(call)) {
+            // We check if mCalls already contains the call because we could potentially be reusing
+            // a call which was previously added (See {@link #reuseOutgoingCall}).
+            addCall(call);
+        }
+
+        return call;
+    }
     /**
      * Called in response to a {@link Call} receiving a {@link Call#handoverTo(PhoneAccountHandle,
      * int, Bundle)} indicating the {@link android.telecom.InCallService} has requested a
@@ -3573,7 +4178,7 @@
 
         Call call = new Call(getNextCallId(), mContext,
                 this, mLock, mConnectionServiceRepository,
-                mContactsAsyncHelper, mCallerInfoAsyncQueryFactory, mPhoneNumberUtilsAdapter,
+                mPhoneNumberUtilsAdapter,
                 handoverFromCall.getHandle(), null,
                 null, null,
                 Call.CALL_DIRECTION_OUTGOING, false,
@@ -3773,8 +4378,6 @@
                 this,
                 mLock,
                 mConnectionServiceRepository,
-                mContactsAsyncHelper,
-                mCallerInfoAsyncQueryFactory,
                 mPhoneNumberUtilsAdapter,
                 srcAddr,
                 null /* gatewayInfo */,
@@ -3839,12 +4442,12 @@
         call.startCreateConnection(mPhoneAccountRegistrar);
     }
 
-    ConnectionServiceFocusManager getConnectionServiceFocusManager() {
+    public ConnectionServiceFocusManager getConnectionServiceFocusManager() {
         return mConnectionSvrFocusMgr;
     }
 
     private boolean canHold(Call call) {
-        return call.can(Connection.CAPABILITY_HOLD);
+        return call.can(Connection.CAPABILITY_HOLD) && call.getState() != CallState.DIALING;
     }
 
     private boolean supportsHold(Call call) {
@@ -3905,6 +4508,9 @@
             // We do not update the UI until we get confirmation of the answer() through
             // {@link #markCallAsActive}.
             mCall.answer(mVideoState);
+            if (mCall.getState() == CallState.RINGING) {
+                setCallState(mCall, CallState.ANSWERED, "answered");
+            }
             if (isSpeakerphoneAutoEnabledForVideoCalls(mVideoState)) {
                 mCall.setStartWithSpeakerphoneOn(true);
             }
@@ -3927,4 +4533,55 @@
             }
         }
     }
+
+    public void resetConnectionTime(Call call) {
+        call.setConnectTimeMillis(System.currentTimeMillis());
+        call.setConnectElapsedTimeMillis(SystemClock.elapsedRealtime());
+        if (mCalls.contains(call)) {
+            for (CallsManagerListener listener : mListeners) {
+                listener.onConnectionTimeChanged(call);
+            }
+        }
+    }
+
+    /**
+     * Determines if there is an ongoing emergency call. This can be either an outgoing emergency
+     * call, or a number which has been identified by the number as an emergency call.
+     * @return {@code true} if there is an ongoing emergency call, {@code false} otherwise.
+     */
+    public boolean isInEmergencyCall() {
+        return mCalls.stream().filter(c -> c.isEmergencyCall()
+                || c.isNetworkIdentifiedEmergencyCall()).count() > 0;
+    }
+
+    /**
+     * Trigger display of an error message to the user; we do this outside of dialer for calls which
+     * fail to be created and added to Dialer.
+     * @param messageId The string resource id.
+     */
+    private void showErrorMessage(int messageId) {
+        final Intent errorIntent = new Intent(mContext, ErrorDialogActivity.class);
+        errorIntent.putExtra(ErrorDialogActivity.ERROR_MESSAGE_ID_EXTRA, messageId);
+        errorIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivityAsUser(errorIntent, UserHandle.CURRENT);
+    }
+
+    /**
+     * Handles changes to a {@link PhoneAccount}.
+     *
+     * Checks for changes to video calling availability and updates whether calls for that phone
+     * account are video capable.
+     *
+     * @param registrar The {@link PhoneAccountRegistrar} originating the change.
+     * @param phoneAccount The {@link PhoneAccount} which changed.
+     */
+    private void handlePhoneAccountChanged(PhoneAccountRegistrar registrar,
+            PhoneAccount phoneAccount) {
+        Log.i(this, "handlePhoneAccountChanged: phoneAccount=%s", phoneAccount);
+        boolean isVideoNowSupported = phoneAccount.hasCapabilities(
+                PhoneAccount.CAPABILITY_VIDEO_CALLING);
+        mCalls.stream()
+                .filter(c -> phoneAccount.getAccountHandle().equals(c.getTargetPhoneAccount()))
+                .forEach(c -> c.setVideoCallingSupportedByPhoneAccount(isVideoNowSupported));
+    }
 }
diff --git a/src/com/android/server/telecom/CallsManagerListenerBase.java b/src/com/android/server/telecom/CallsManagerListenerBase.java
index c0a71eb..4fa2ee5 100644
--- a/src/com/android/server/telecom/CallsManagerListenerBase.java
+++ b/src/com/android/server/telecom/CallsManagerListenerBase.java
@@ -92,4 +92,12 @@
     @Override
     public void onDisconnectedTonePlaying(boolean isTonePlaying) {
     }
+
+    @Override
+    public void onConnectionTimeChanged(Call call) {
+    }
+
+    @Override
+    public void onConferenceStateChanged(Call call, boolean isConference) {
+    }
 }
diff --git a/src/com/android/server/telecom/ConnectionServiceFocusManager.java b/src/com/android/server/telecom/ConnectionServiceFocusManager.java
index 92570a0..9c0bfa2 100644
--- a/src/com/android/server/telecom/ConnectionServiceFocusManager.java
+++ b/src/com/android/server/telecom/ConnectionServiceFocusManager.java
@@ -19,6 +19,7 @@
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
 import android.telecom.Log;
@@ -30,14 +31,19 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 public class ConnectionServiceFocusManager {
     private static final String TAG = "ConnectionSvrFocusMgr";
+    private static final int GET_CURRENT_FOCUS_TIMEOUT_MILLIS = 1000;
 
     /** Factory interface used to create the {@link ConnectionServiceFocusManager} instance. */
     public interface ConnectionServiceFocusManagerFactory {
-        ConnectionServiceFocusManager create(CallsManagerRequester requester, Looper looper);
+        ConnectionServiceFocusManager create(CallsManagerRequester requester);
     }
 
     /**
@@ -271,10 +277,12 @@
     private FocusManagerHandler mEventHandler;
 
     public ConnectionServiceFocusManager(
-            CallsManagerRequester callsManagerRequester, Looper looper) {
+            CallsManagerRequester callsManagerRequester) {
         mCallsManagerRequester = callsManagerRequester;
         mCallsManagerRequester.setCallsManagerListener(mCallsManagerListener);
-        mEventHandler = new FocusManagerHandler(looper);
+        HandlerThread handlerThread = new HandlerThread(TAG);
+        handlerThread.start();
+        mEventHandler = new FocusManagerHandler(handlerThread.getLooper());
         mCalls = new ArrayList<>();
     }
 
@@ -298,8 +306,32 @@
      * call is the current connection service focus. Also the state of the focus call must be one
      * of {@link #PRIORITY_FOCUS_CALL_STATE}.
      */
-    public CallFocus getCurrentFocusCall() {
-        return mCurrentFocusCall;
+    public @Nullable CallFocus getCurrentFocusCall() {
+        if (mEventHandler.getLooper().isCurrentThread()) {
+            // return synchronously if we're on the same thread.
+            return mCurrentFocusCall;
+        }
+        final BlockingQueue<Optional<CallFocus>> currentFocusedCallQueue =
+                new LinkedBlockingQueue<>(1);
+        mEventHandler.post(() -> {
+            currentFocusedCallQueue.offer(
+                    mCurrentFocusCall == null ? Optional.empty() : Optional.of(mCurrentFocusCall));
+        });
+        try {
+            Optional<CallFocus> syncCallFocus = currentFocusedCallQueue.poll(
+                    GET_CURRENT_FOCUS_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+            if (syncCallFocus != null) {
+                return syncCallFocus.orElse(null);
+            } else {
+                Log.w(TAG, "Timed out waiting for synchronous current focus. Returning possibly"
+                        + " inaccurate result");
+                return mCurrentFocusCall;
+            }
+        } catch (InterruptedException e) {
+            Log.w(TAG, "Interrupted when waiting for synchronous current focus."
+                    + " Returning possibly inaccurate result.");
+            return mCurrentFocusCall;
+        }
     }
 
     /** Returns the current connection service focus. */
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 6dd9a3a..eb2e233 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -145,6 +145,26 @@
         }
 
         @Override
+        public void resetConnectionTime(String callId, Session.Info sessionInfo) {
+            Log.startSession(sessionInfo, "CSW.rCCT");
+            long token = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    logIncoming("resetConnectionTime %s", callId);
+                    Call call = mCallIdMapper.getCall(callId);
+                    if (call != null) {
+                        mCallsManager.resetConnectionTime(call);
+                    } else {
+                        // Log.w(this, "resetConnectionTime, unknown call id: %s", msg.obj);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+                Log.endSession();
+            }
+        }
+
+        @Override
         public void setVideoProvider(String callId, IVideoProvider videoProvider,
                 Session.Info sessionInfo) {
             Log.startSession(sessionInfo, "CSW.sVP");
@@ -970,6 +990,27 @@
                 Log.endSession();
             }
         }
+
+        @Override
+        public void setConferenceState(String callId, boolean isConference,
+                Session.Info sessionInfo) throws RemoteException {
+            Log.startSession(sessionInfo, "CSW.sCS");
+            long token = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    Call call = mCallIdMapper.getCall(callId);
+                    if (call != null) {
+                        call.setConferenceState(isConference);
+                    }
+                }
+            } catch (Throwable t) {
+                Log.e(ConnectionServiceWrapper.this, t, "");
+                throw t;
+            } finally {
+                Binder.restoreCallingIdentity(token);
+                Log.endSession();
+            }
+        }
     }
 
     private final Adapter mAdapter = new Adapter();
@@ -1621,6 +1662,14 @@
         if (connection.getState() == Connection.STATE_DISCONNECTED) {
             // A connection that begins in the DISCONNECTED state is an indication of
             // failure to connect; we handle all failures uniformly
+            Call foundCall = mCallIdMapper.getCall(callId);
+            if (foundCall != null) {
+                // The post-dial digits are created when the call is first created.  Normally
+                // the ConnectionService is responsible for stripping them from the address, but
+                // since a failed connection will not have done this, we could end up with duplicate
+                // post-dial digits.
+                foundCall.clearPostDialDigits();
+            }
             removeCall(callId, connection.getDisconnectCause());
         } else {
             // Successful connection
diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java
index 7eb3801..d3c74ec 100644
--- a/src/com/android/server/telecom/CreateConnectionProcessor.java
+++ b/src/com/android/server/telecom/CreateConnectionProcessor.java
@@ -311,6 +311,38 @@
         }
     }
 
+    // This function is used after previous attempts to find emergency PSTN connections
+    // do not find any SIM phone accounts with emergency capability.
+    // It attempts to add any accounts with CAPABILITY_PLACE_EMERGENCY_CALLS even if
+    // accounts are not SIM accounts.
+    private void adjustAttemptsForEmergencyNoSimRequired(
+            PhoneAccountHandle preferredPAH,
+            List<PhoneAccount> allAccounts) {
+        // First, possibly add the phone account that the user prefers.
+        PhoneAccount preferredPA = mPhoneAccountRegistrar.getPhoneAccountUnchecked(preferredPAH);
+        if (preferredPA != null
+                && preferredPA.hasCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)) {
+            Log.i(this, "Will try account %s for emergency", preferredPA.getAccountHandle());
+            mAttemptRecords.add(new CallAttemptRecord(preferredPAH, preferredPAH));
+        }
+
+        // Next, add all phone accounts which can place emergency calls.
+        // If preferredPA already has an emergency PhoneAccount, do not add others since the
+        // emergency call be redialed in Telephony.
+        if (mAttemptRecords.isEmpty()) {
+            for (PhoneAccount phoneAccount : allAccounts) {
+                if (phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)) {
+                    PhoneAccountHandle phoneAccountHandle = phoneAccount.getAccountHandle();
+                    Log.i(this, "Will try account %s for emergency", phoneAccountHandle);
+                    mAttemptRecords.add(
+                            new CallAttemptRecord(phoneAccountHandle, phoneAccountHandle));
+                    // Add only one emergency PhoneAccount to the attempt list.
+                    break;
+                }
+            }
+        }
+    }
+
     // If we are possibly attempting to call a local emergency number, ensure that the
     // plain PSTN connection services are listed, and nothing else.
     private void adjustAttemptsForEmergency(PhoneAccountHandle preferredPAH) {
@@ -383,6 +415,12 @@
                     }
                 }
             }
+
+            if (mAttemptRecords.isEmpty()) {
+                // Last best-effort attempt: choose any account with emergency capability even without
+                // sim capability.
+                adjustAttemptsForEmergencyNoSimRequired(preferredPAH, allAccounts);
+            }
         }
     }
 
diff --git a/src/com/android/server/telecom/DialerCodeReceiver.java b/src/com/android/server/telecom/DialerCodeReceiver.java
index 57f84a0..1cd922a 100644
--- a/src/com/android/server/telecom/DialerCodeReceiver.java
+++ b/src/com/android/server/telecom/DialerCodeReceiver.java
@@ -19,9 +19,12 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.os.UserHandle;
 import android.telecom.Log;
 import android.telecom.TelecomManager;
 
+import com.android.server.telecom.ui.TelecomDeveloperMenu;
+
 /**
  * Receiver for "secret codes" broadcast by Dialer.
  */
@@ -38,6 +41,9 @@
     // Writes a MARK to the Telecom log.
     public static final String TELECOM_SECRET_CODE_MARK = "826275";
 
+    // Opens the Telecom developer menu.
+    public static final String TELECOM_SECRET_CODE_MENU = "828282";
+
     private final CallsManager mCallsManager;
 
     DialerCodeReceiver(CallsManager callsManager) {
@@ -61,6 +67,11 @@
                 // add a non-call event.
                 Call currentCall = mCallsManager.getActiveCall();
                 Log.addEvent(currentCall, LogUtils.Events.USER_LOG_MARK);
+            } else if (intent.getData().getHost().equals(TELECOM_SECRET_CODE_MENU)) {
+                Log.i("DialerCodeReceiver", "Secret code used to open developer menu.");
+                Intent confirmIntent = new Intent(context, TelecomDeveloperMenu.class);
+                confirmIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                context.startActivityAsUser(confirmIntent, UserHandle.CURRENT);
             }
         }
     }
diff --git a/src/com/android/server/telecom/HeadsetMediaButton.java b/src/com/android/server/telecom/HeadsetMediaButton.java
index ec77289..ad95c34 100644
--- a/src/com/android/server/telecom/HeadsetMediaButton.java
+++ b/src/com/android/server/telecom/HeadsetMediaButton.java
@@ -26,14 +26,18 @@
 import android.telecom.Log;
 import android.view.KeyEvent;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 /**
  * Static class to handle listening to the headset media buttons.
  */
 public class HeadsetMediaButton extends CallsManagerListenerBase {
 
     // Types of media button presses
-    static final int SHORT_PRESS = 1;
-    static final int LONG_PRESS = 2;
+    @VisibleForTesting
+    public static final int SHORT_PRESS = 1;
+    @VisibleForTesting
+    public static final int LONG_PRESS = 2;
 
     private static final AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
             .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index 9d20d4a..9cbc20e 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -34,7 +34,6 @@
 import android.os.UserHandle;
 import android.telecom.CallAudioState;
 import android.telecom.ConnectionService;
-import android.telecom.DefaultDialerManager;
 import android.telecom.InCallService;
 import android.telecom.Log;
 import android.telecom.Logging.Runnable;
@@ -47,7 +46,7 @@
 // TODO: Needed for move to system service: import com.android.internal.R;
 import com.android.internal.telecom.IInCallService;
 import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.telecom.SystemStateProvider.SystemStateListener;
+import com.android.server.telecom.SystemStateHelper.SystemStateListener;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -55,6 +54,8 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Binds to {@link IInCallService} and provides the service to {@link CallsManager} through which it
@@ -712,15 +713,11 @@
     private static final int IN_CALL_SERVICE_TYPE_SYSTEM_UI = 2;
     private static final int IN_CALL_SERVICE_TYPE_CAR_MODE_UI = 3;
     private static final int IN_CALL_SERVICE_TYPE_NON_UI = 4;
+    private static final int IN_CALL_SERVICE_TYPE_COMPANION = 5;
 
     /** The in-call app implementations, see {@link IInCallService}. */
     private final Map<InCallServiceInfo, IInCallService> mInCallServices = new ArrayMap<>();
 
-    /**
-     * The {@link ComponentName} of the bound In-Call UI Service.
-     */
-    private ComponentName mInCallUIComponentName;
-
     private final CallIdMapper mCallIdMapper = new CallIdMapper(Call::getId);
 
     /** The {@link ComponentName} of the default InCall UI. */
@@ -729,21 +726,25 @@
     private final Context mContext;
     private final TelecomSystem.SyncRoot mLock;
     private final CallsManager mCallsManager;
-    private final SystemStateProvider mSystemStateProvider;
+    private final SystemStateHelper mSystemStateHelper;
     private final Timeouts.Adapter mTimeoutsAdapter;
     private final DefaultDialerCache mDefaultDialerCache;
     private final EmergencyCallHelper mEmergencyCallHelper;
     private CarSwappingInCallServiceConnection mInCallServiceConnection;
     private NonUIInCallServiceConnectionCollection mNonUIInCallServiceConnections;
 
+    // Future that's in a completed state unless we're in the middle of binding to a service.
+    // The future will complete with true if binding succeeds, false if it timed out.
+    private CompletableFuture<Boolean> mBindingFuture = CompletableFuture.completedFuture(true);
+
     public InCallController(Context context, TelecomSystem.SyncRoot lock, CallsManager callsManager,
-            SystemStateProvider systemStateProvider,
+            SystemStateHelper systemStateHelper,
             DefaultDialerCache defaultDialerCache, Timeouts.Adapter timeoutsAdapter,
             EmergencyCallHelper emergencyCallHelper) {
         mContext = context;
         mLock = lock;
         mCallsManager = callsManager;
-        mSystemStateProvider = systemStateProvider;
+        mSystemStateHelper = systemStateHelper;
         mTimeoutsAdapter = timeoutsAdapter;
         mDefaultDialerCache = defaultDialerCache;
         mEmergencyCallHelper = emergencyCallHelper;
@@ -753,7 +754,7 @@
                 resources.getString(R.string.ui_default_package),
                 resources.getString(R.string.incall_default_class));
 
-        mSystemStateProvider.addListener(mSystemStateListener);
+        mSystemStateHelper.addListener(mSystemStateListener);
     }
 
     @Override
@@ -797,7 +798,8 @@
 
                 ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(call,
                         true /* includeVideoProvider */, mCallsManager.getPhoneAccountRegistrar(),
-                        info.isExternalCallsSupported(), includeRttCall);
+                        info.isExternalCallsSupported(), includeRttCall,
+                        info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI);
                 try {
                     inCallService.addCall(parcelableCall);
                 } catch (RemoteException ignored) {
@@ -861,7 +863,8 @@
 
                 ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(call,
                         true /* includeVideoProvider */, mCallsManager.getPhoneAccountRegistrar(),
-                        info.isExternalCallsSupported(), includeRttCall);
+                        info.isExternalCallsSupported(), includeRttCall,
+                        info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI);
                 try {
                     inCallService.addCall(parcelableCall);
                 } catch (RemoteException ignored) {
@@ -872,15 +875,7 @@
             // The call was regular but it is now external.  We must now remove it from any
             // InCallServices which do not support external calls.
             // Remove the call by sending a call update indicating the call was disconnected.
-            ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(
-                    call,
-                    false /* includeVideoProvider */,
-                    mCallsManager.getPhoneAccountRegistrar(),
-                    false /* supportsExternalCalls */,
-                    android.telecom.Call.STATE_DISCONNECTED /* overrideState */,
-                    false /* includeRttCall */);
-
-            Log.i(this, "Removing external call %s ==> %s", call, parcelableCall);
+            Log.i(this, "Removing external call %", call);
             for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.entrySet()) {
                 InCallServiceInfo info = entry.getKey();
                 if (info.isExternalCallsSupported()) {
@@ -892,6 +887,16 @@
                 componentsUpdated.add(info.getComponentName());
                 IInCallService inCallService = entry.getValue();
 
+                ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(
+                        call,
+                        false /* includeVideoProvider */,
+                        mCallsManager.getPhoneAccountRegistrar(),
+                        false /* supportsExternalCalls */,
+                        android.telecom.Call.STATE_DISCONNECTED /* overrideState */,
+                        false /* includeRttCall */,
+                        info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI
+                        );
+
                 try {
                     inCallService.updateCall(parcelableCall);
                 } catch (RemoteException ignored) {
@@ -960,6 +965,24 @@
         updateCall(call);
     }
 
+    @Override
+    public void onConnectionTimeChanged(Call call) {
+        Log.d(this, "onConnectionTimeChanged %s", call);
+        updateCall(call);
+    }
+
+    @Override
+    public void onIsVoipAudioModeChanged(Call call) {
+        Log.d(this, "onIsVoipAudioModeChanged %s", call);
+        updateCall(call);
+    }
+
+    @Override
+    public void onConferenceStateChanged(Call call, boolean isConference) {
+        Log.d(this, "onConferenceStateChanged %s ,isConf=%b", call, isConference);
+        updateCall(call);
+    }
+
     void bringToForeground(boolean showDialpad) {
         if (!mInCallServices.isEmpty()) {
             for (IInCallService inCallService : mInCallServices.values()) {
@@ -1112,6 +1135,10 @@
             // Only connect to the non-ui InCallServices if we actually connected to the main UI
             // one.
             connectToNonUiInCallServices(call);
+            mBindingFuture = new CompletableFuture<Boolean>().completeOnTimeout(false,
+                    mTimeoutsAdapter.getCallRemoveUnbindInCallServicesDelay(
+                            mContext.getContentResolver()),
+                    TimeUnit.MILLISECONDS);
         } else {
             Log.i(this, "bindToServices: current UI doesn't support call; not binding.");
         }
@@ -1124,6 +1151,17 @@
         for (InCallServiceInfo serviceInfo : nonUIInCallComponents) {
             nonUIInCalls.add(new InCallServiceBindingConnection(serviceInfo));
         }
+        List<String> callCompanionApps = mCallsManager
+                .getRoleManagerAdapter().getCallCompanionApps();
+        if (callCompanionApps != null && !callCompanionApps.isEmpty()) {
+            for(String pkg : callCompanionApps) {
+                InCallServiceInfo info = getInCallServiceComponent(pkg,
+                        IN_CALL_SERVICE_TYPE_COMPANION);
+                if (info != null) {
+                    nonUIInCalls.add(new InCallServiceBindingConnection(info));
+                }
+            }
+        }
         mNonUIInCallServiceConnections = new NonUIInCallServiceConnectionCollection(nonUIInCalls);
         mNonUIInCallServiceConnections.connect(call);
     }
@@ -1137,9 +1175,10 @@
     }
 
     private InCallServiceInfo getCarModeComponent() {
-        // Seems strange to cast a String to null, but the signatures of getInCallServiceComponent
-        // differ in the types of the first parameter, and passing in null is inherently ambiguous.
-        return getInCallServiceComponent((String) null, IN_CALL_SERVICE_TYPE_CAR_MODE_UI);
+        // The signatures of getInCallServiceComponent differ in the types of the first parameter,
+        // and passing in null is inherently ambiguous. (If no car mode component found)
+        String defaultCarMode = mCallsManager.getRoleManagerAdapter().getCarModeDialerApp();
+        return getInCallServiceComponent(defaultCarMode, IN_CALL_SERVICE_TYPE_CAR_MODE_UI);
     }
 
     private InCallServiceInfo getInCallServiceComponent(ComponentName componentName, int type) {
@@ -1194,7 +1233,6 @@
                 PackageManager.GET_META_DATA,
                 mCallsManager.getCurrentUserHandle().getIdentifier())) {
             ServiceInfo serviceInfo = entry.serviceInfo;
-
             if (serviceInfo != null) {
                 boolean isExternalCallsSupported = serviceInfo.metaData != null &&
                         serviceInfo.metaData.getBoolean(
@@ -1203,7 +1241,8 @@
                         serviceInfo.metaData.getBoolean(
                                 TelecomManager.METADATA_INCLUDE_SELF_MANAGED_CALLS, false);
 
-                int currentType = getInCallServiceType(entry.serviceInfo, packageManager);
+                int currentType = getInCallServiceType(entry.serviceInfo, packageManager,
+                        packageName);
                 if (requestedType == 0 || requestedType == currentType) {
                     if (requestedType == IN_CALL_SERVICE_TYPE_NON_UI) {
                         // We enforce the rule that self-managed calls are not supported by non-ui
@@ -1221,13 +1260,14 @@
     }
 
     private boolean shouldUseCarModeUI() {
-        return mSystemStateProvider.isCarMode();
+        return mSystemStateHelper.isCarMode();
     }
 
     /**
      * Returns the type of InCallService described by the specified serviceInfo.
      */
-    private int getInCallServiceType(ServiceInfo serviceInfo, PackageManager packageManager) {
+    private int getInCallServiceType(ServiceInfo serviceInfo, PackageManager packageManager,
+            String packageName) {
         // Verify that the InCallService requires the BIND_INCALL_SERVICE permission which
         // enforces that only Telecom can bind to it.
         boolean hasServiceBindPermission = serviceInfo.permission != null &&
@@ -1244,6 +1284,14 @@
             return IN_CALL_SERVICE_TYPE_SYSTEM_UI;
         }
 
+        // Check to see if the service holds permissions or metadata for third party apps.
+        boolean isUIService = serviceInfo.metaData != null &&
+                serviceInfo.metaData.getBoolean(TelecomManager.METADATA_IN_CALL_SERVICE_UI);
+        boolean isThirdPartyCompanionApp = packageManager.checkPermission(
+                Manifest.permission.CALL_COMPANION_APP,
+                serviceInfo.packageName) == PackageManager.PERMISSION_GRANTED &&
+                !isUIService;
+
         // Check to see if the service is a car-mode UI type by checking that it has the
         // CONTROL_INCALL_EXPERIENCE (to verify it is a system app) and that it has the
         // car-mode UI metadata.
@@ -1253,26 +1301,33 @@
         boolean isCarModeUIService = serviceInfo.metaData != null &&
                 serviceInfo.metaData.getBoolean(
                         TelecomManager.METADATA_IN_CALL_SERVICE_CAR_MODE_UI, false) &&
-                hasControlInCallPermission;
+                (hasControlInCallPermission || isThirdPartyCompanionApp);
         if (isCarModeUIService) {
-            return IN_CALL_SERVICE_TYPE_CAR_MODE_UI;
+            // ThirdPartyInCallService shouldn't be used when role manager hasn't assigned any car
+            // mode role holders, i.e. packageName is null.
+            if (isUIService || (isThirdPartyCompanionApp && packageName != null)) {
+                return IN_CALL_SERVICE_TYPE_CAR_MODE_UI;
+            }
         }
 
         // Check to see that it is the default dialer package
         boolean isDefaultDialerPackage = Objects.equals(serviceInfo.packageName,
                 mDefaultDialerCache.getDefaultDialerApplication(
                     mCallsManager.getCurrentUserHandle().getIdentifier()));
-        boolean isUIService = serviceInfo.metaData != null &&
-                serviceInfo.metaData.getBoolean(
-                        TelecomManager.METADATA_IN_CALL_SERVICE_UI, false);
         if (isDefaultDialerPackage && isUIService) {
             return IN_CALL_SERVICE_TYPE_DIALER_UI;
         }
 
         // Also allow any in-call service that has the control-experience permission (to ensure
         // that it is a system app) and doesn't claim to show any UI.
-        if (hasControlInCallPermission && !isUIService) {
-            return IN_CALL_SERVICE_TYPE_NON_UI;
+        if (!isUIService) {
+            if (hasControlInCallPermission && !isThirdPartyCompanionApp) {
+                return IN_CALL_SERVICE_TYPE_NON_UI;
+            }
+            // Third party companion alls without CONTROL_INCALL_EXPERIENCE permission.
+            if (!hasControlInCallPermission && isThirdPartyCompanionApp) {
+                return IN_CALL_SERVICE_TYPE_COMPANION;
+            }
         }
 
         // Anything else that remains, we will not bind to.
@@ -1342,7 +1397,8 @@
                         true /* includeVideoProvider */,
                         mCallsManager.getPhoneAccountRegistrar(),
                         info.isExternalCallsSupported(),
-                        includeRttCall));
+                        includeRttCall,
+                        info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI));
             } catch (RemoteException ignored) {
             }
         }
@@ -1351,6 +1407,7 @@
             inCallService.onCanAddCallChanged(mCallsManager.canAddCall());
         } catch (RemoteException ignored) {
         }
+        mBindingFuture.complete(true);
         Log.i(this, "%s calls sent to InCallService.", numCallsSent);
         Trace.endSection();
         return true;
@@ -1404,7 +1461,8 @@
                         videoProviderChanged /* includeVideoProvider */,
                         mCallsManager.getPhoneAccountRegistrar(),
                         info.isExternalCallsSupported(),
-                        rttInfoChanged && info.equals(mInCallServiceConnection.getInfo()));
+                        rttInfoChanged && info.equals(mInCallServiceConnection.getInfo()),
+                        info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI);
                 ComponentName componentName = info.getComponentName();
                 IInCallService inCallService = entry.getValue();
                 componentsUpdated.add(componentName);
@@ -1437,6 +1495,14 @@
     }
 
     /**
+     * @return A future that is pending whenever we are in the middle of binding to an
+     *         incall service.
+     */
+    public CompletableFuture<Boolean> getBindingFuture() {
+        return mBindingFuture;
+    }
+
+    /**
      * Dumps the state of the {@link InCallController}.
      *
      * @param pw The {@code IndentingPrintWriter} to write the state to.
@@ -1457,18 +1523,42 @@
         pw.decreaseIndent();
     }
 
+    /**
+     * @return The package name of the UI which is currently bound, or null if none.
+     */
+    private ComponentName getConnectedUi() {
+        InCallServiceInfo connectedUi = mInCallServices.keySet().stream().filter(
+                i -> i.getType() == IN_CALL_SERVICE_TYPE_DIALER_UI
+                        || i.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI)
+                .findAny()
+                .orElse(null);
+        if (connectedUi != null) {
+            return connectedUi.mComponentName;
+        }
+        return null;
+    }
+
     public boolean doesConnectedDialerSupportRinging() {
         String ringingPackage =  null;
-        if (mInCallUIComponentName != null) {
-            ringingPackage = mInCallUIComponentName.getPackageName().trim();
+
+        ComponentName connectedPackage = getConnectedUi();
+        if (connectedPackage != null) {
+            ringingPackage = connectedPackage.getPackageName().trim();
+            Log.d(this, "doesConnectedDialerSupportRinging: alreadyConnectedPackage=%s",
+                    ringingPackage);
         }
 
         if (TextUtils.isEmpty(ringingPackage)) {
             // The current in-call UI returned nothing, so lets use the default dialer.
-            ringingPackage = DefaultDialerManager.getDefaultDialerApplication(
-                    mContext, UserHandle.USER_CURRENT);
+            ringingPackage = mDefaultDialerCache.getDefaultDialerApplication(
+                    mCallsManager.getCurrentUserHandle().getIdentifier());
+            if (ringingPackage != null) {
+                Log.d(this, "doesConnectedDialerSupportRinging: notCurentlyConnectedPackage=%s",
+                        ringingPackage);
+            }
         }
         if (TextUtils.isEmpty(ringingPackage)) {
+            Log.w(this, "doesConnectedDialerSupportRinging: no default dialer found; oh no!");
             return false;
         }
 
@@ -1478,11 +1568,15 @@
                 intent, PackageManager.GET_META_DATA,
                 mCallsManager.getCurrentUserHandle().getIdentifier());
         if (entries.isEmpty()) {
+            Log.w(this, "doesConnectedDialerSupportRinging: couldn't find dialer's package info"
+                    + " <sad trombone>");
             return false;
         }
 
         ResolveInfo info = entries.get(0);
         if (info.serviceInfo == null || info.serviceInfo.metaData == null) {
+            Log.w(this, "doesConnectedDialerSupportRinging: couldn't find dialer's metadata"
+                    + " <even sadder trombone>");
             return false;
         }
 
diff --git a/src/com/android/server/telecom/InCallControllerFactory.java b/src/com/android/server/telecom/InCallControllerFactory.java
index e384af7..c3a7831 100644
--- a/src/com/android/server/telecom/InCallControllerFactory.java
+++ b/src/com/android/server/telecom/InCallControllerFactory.java
@@ -23,6 +23,6 @@
  */
 public interface InCallControllerFactory {
     InCallController create(Context context, TelecomSystem.SyncRoot lock, CallsManager callsManager,
-            SystemStateProvider systemStateProvider, DefaultDialerCache defaultDialerCache,
+            SystemStateHelper systemStateHelper, DefaultDialerCache defaultDialerCache,
             Timeouts.Adapter timeoutsAdapter, EmergencyCallHelper emergencyCallHelper);
 }
diff --git a/src/com/android/server/telecom/InCallTonePlayer.java b/src/com/android/server/telecom/InCallTonePlayer.java
index a258aee..5864ce0 100644
--- a/src/com/android/server/telecom/InCallTonePlayer.java
+++ b/src/com/android/server/telecom/InCallTonePlayer.java
@@ -16,8 +16,13 @@
 
 package com.android.server.telecom;
 
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.AudioAttributes;
 import android.media.AudioManager;
+import android.media.MediaPlayer;
 import android.media.ToneGenerator;
+import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
 import android.telecom.Log;
@@ -26,10 +31,15 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 /**
- * Play a call-related tone (ringback, busy signal, etc.) through ToneGenerator. To use, create an
- * instance using InCallTonePlayer.Factory (passing in the TONE_* constant for the tone you want)
- * and start() it. Implemented on top of {@link Thread} so that the tone plays in its own thread.
+ * Play a call-related tone (ringback, busy signal, etc.) either through ToneGenerator, or using a
+ * media resource file.
+ * To use, create an instance using InCallTonePlayer.Factory (passing in the TONE_* constant for
+ * the tone you want) and start() it. Implemented on top of {@link Thread} so that the tone plays in
+ * its own thread.
  */
 public class InCallTonePlayer extends Thread {
 
@@ -41,12 +51,17 @@
         private final CallAudioRoutePeripheralAdapter mCallAudioRoutePeripheralAdapter;
         private final TelecomSystem.SyncRoot mLock;
         private final ToneGeneratorFactory mToneGeneratorFactory;
+        private final MediaPlayerFactory mMediaPlayerFactory;
+        private final AudioManagerAdapter mAudioManagerAdapter;
 
-        Factory(CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter,
-                TelecomSystem.SyncRoot lock, ToneGeneratorFactory toneGeneratorFactory) {
+        public Factory(CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter,
+                TelecomSystem.SyncRoot lock, ToneGeneratorFactory toneGeneratorFactory,
+                MediaPlayerFactory mediaPlayerFactory, AudioManagerAdapter audioManagerAdapter) {
             mCallAudioRoutePeripheralAdapter = callAudioRoutePeripheralAdapter;
             mLock = lock;
             mToneGeneratorFactory = toneGeneratorFactory;
+            mMediaPlayerFactory = mediaPlayerFactory;
+            mAudioManagerAdapter = audioManagerAdapter;
         }
 
         public void setCallAudioManager(CallAudioManager callAudioManager) {
@@ -55,7 +70,8 @@
 
         public InCallTonePlayer createPlayer(int tone) {
             return new InCallTonePlayer(tone, mCallAudioManager,
-                    mCallAudioRoutePeripheralAdapter, mLock, mToneGeneratorFactory);
+                    mCallAudioRoutePeripheralAdapter, mLock, mToneGeneratorFactory,
+                    mMediaPlayerFactory, mAudioManagerAdapter);
         }
     }
 
@@ -63,6 +79,73 @@
         ToneGenerator get (int streamType, int volume);
     }
 
+    public interface MediaPlayerAdapter {
+        void setLooping(boolean isLooping);
+        void setOnCompletionListener(MediaPlayer.OnCompletionListener listener);
+        void start();
+        void release();
+        int getDuration();
+    }
+
+    public static class MediaPlayerAdapterImpl implements MediaPlayerAdapter {
+        private MediaPlayer mMediaPlayer;
+
+        /**
+         * Create new media player adapter backed by a real mediaplayer.
+         * Note: Its possible for the mediaplayer to be null if
+         * {@link MediaPlayer#create(Context, Uri)} fails for some reason; in this case we can
+         * continue but not bother playing the audio.
+         * @param mediaPlayer The media player.
+         */
+        public MediaPlayerAdapterImpl(@Nullable MediaPlayer mediaPlayer) {
+            mMediaPlayer = mediaPlayer;
+        }
+
+        @Override
+        public void setLooping(boolean isLooping) {
+            if (mMediaPlayer != null) {
+                mMediaPlayer.setLooping(isLooping);
+            }
+        }
+
+        @Override
+        public void setOnCompletionListener(MediaPlayer.OnCompletionListener listener) {
+            if (mMediaPlayer != null) {
+                mMediaPlayer.setOnCompletionListener(listener);
+            }
+        }
+
+        @Override
+        public void start() {
+            if (mMediaPlayer != null) {
+                mMediaPlayer.start();
+            }
+        }
+
+        @Override
+        public void release() {
+            if (mMediaPlayer != null) {
+                mMediaPlayer.release();
+            }
+        }
+
+        @Override
+        public int getDuration() {
+            if (mMediaPlayer != null) {
+                return mMediaPlayer.getDuration();
+            }
+            return 0;
+        }
+    }
+
+    public interface MediaPlayerFactory {
+        MediaPlayerAdapter get (int resourceId, AudioAttributes attributes);
+    }
+
+    public interface AudioManagerAdapter {
+        boolean isVolumeOverZero();
+    }
+
     // The possible tones that we can play.
     public static final int TONE_INVALID = 0;
     public static final int TONE_BUSY = 1;
@@ -80,9 +163,12 @@
     public static final int TONE_VOICE_PRIVACY = 13;
     public static final int TONE_VIDEO_UPGRADE = 14;
 
+    private static final int TONE_RESOURCE_ID_UNDEFINED = -1;
+
     private static final int RELATIVE_VOLUME_EMERGENCY = 100;
     private static final int RELATIVE_VOLUME_HIPRI = 80;
     private static final int RELATIVE_VOLUME_LOPRI = 50;
+    private static final int RELATIVE_VOLUME_UNDEFINED = -1;
 
     // Buffer time (in msec) to add on to the tone timeout value. Needed mainly when the timeout
     // value for a tone is exact duration of the tone itself.
@@ -111,6 +197,9 @@
     /** Current state of the tone player. */
     private int mState;
 
+    /** For tones which are not generated using ToneGenerator. */
+    private MediaPlayerAdapter mToneMediaPlayer = null;
+
     /** Telecom lock object. */
     private final TelecomSystem.SyncRoot mLock;
 
@@ -118,6 +207,8 @@
     private final Object mSessionLock = new Object();
 
     private final ToneGeneratorFactory mToneGenerator;
+    private final MediaPlayerFactory mMediaPlayerFactory;
+    private final AudioManagerAdapter mAudioManagerAdapter;
 
     /**
      * Initializes the tone player. Private; use the {@link Factory} to create tone players.
@@ -129,19 +220,22 @@
             CallAudioManager callAudioManager,
             CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter,
             TelecomSystem.SyncRoot lock,
-            ToneGeneratorFactory toneGeneratorFactory) {
+            ToneGeneratorFactory toneGeneratorFactory,
+            MediaPlayerFactory mediaPlayerFactor,
+            AudioManagerAdapter audioManagerAdapter) {
         mState = STATE_OFF;
         mToneId = toneId;
         mCallAudioManager = callAudioManager;
         mCallAudioRoutePeripheralAdapter = callAudioRoutePeripheralAdapter;
         mLock = lock;
         mToneGenerator = toneGeneratorFactory;
+        mMediaPlayerFactory = mediaPlayerFactor;
+        mAudioManagerAdapter = audioManagerAdapter;
     }
 
     /** {@inheritDoc} */
     @Override
     public void run() {
-        ToneGenerator toneGenerator = null;
         try {
             synchronized (mSessionLock) {
                 if (mSession != null) {
@@ -154,6 +248,8 @@
             final int toneType;  // Passed to ToneGenerator.startTone.
             final int toneVolume;  // Passed to the ToneGenerator constructor.
             final int toneLengthMillis;
+            final int mediaResourceId; // The resourceId of the tone to play.  Used for media-based
+                                      // tones.
 
             switch (mToneId) {
                 case TONE_BUSY:
@@ -161,11 +257,16 @@
                     toneType = ToneGenerator.TONE_SUP_BUSY;
                     toneVolume = RELATIVE_VOLUME_HIPRI;
                     toneLengthMillis = 4000;
+                    mediaResourceId = TONE_RESOURCE_ID_UNDEFINED;
                     break;
                 case TONE_CALL_ENDED:
-                    toneType = ToneGenerator.TONE_PROP_PROMPT;
-                    toneVolume = RELATIVE_VOLUME_HIPRI;
-                    toneLengthMillis = 200;
+                    // 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.endcall;
                     break;
                 case TONE_OTA_CALL_ENDED:
                     // TODO: fill in
@@ -174,46 +275,55 @@
                     toneType = ToneGenerator.TONE_SUP_CALL_WAITING;
                     toneVolume = RELATIVE_VOLUME_HIPRI;
                     toneLengthMillis = Integer.MAX_VALUE - TIMEOUT_BUFFER_MILLIS;
+                    mediaResourceId = TONE_RESOURCE_ID_UNDEFINED;
                     break;
                 case TONE_CDMA_DROP:
                     toneType = ToneGenerator.TONE_CDMA_CALLDROP_LITE;
                     toneVolume = RELATIVE_VOLUME_LOPRI;
                     toneLengthMillis = 375;
+                    mediaResourceId = TONE_RESOURCE_ID_UNDEFINED;
                     break;
                 case TONE_CONGESTION:
                     toneType = ToneGenerator.TONE_SUP_CONGESTION;
                     toneVolume = RELATIVE_VOLUME_HIPRI;
                     toneLengthMillis = 4000;
+                    mediaResourceId = TONE_RESOURCE_ID_UNDEFINED;
                     break;
                 case TONE_INTERCEPT:
                     toneType = ToneGenerator.TONE_CDMA_ABBR_INTERCEPT;
                     toneVolume = RELATIVE_VOLUME_LOPRI;
                     toneLengthMillis = 500;
+                    mediaResourceId = TONE_RESOURCE_ID_UNDEFINED;
                     break;
                 case TONE_OUT_OF_SERVICE:
                     toneType = ToneGenerator.TONE_CDMA_CALLDROP_LITE;
                     toneVolume = RELATIVE_VOLUME_LOPRI;
                     toneLengthMillis = 375;
+                    mediaResourceId = TONE_RESOURCE_ID_UNDEFINED;
                     break;
                 case TONE_REDIAL:
                     toneType = ToneGenerator.TONE_CDMA_ALERT_AUTOREDIAL_LITE;
                     toneVolume = RELATIVE_VOLUME_LOPRI;
                     toneLengthMillis = 5000;
+                    mediaResourceId = TONE_RESOURCE_ID_UNDEFINED;
                     break;
                 case TONE_REORDER:
                     toneType = ToneGenerator.TONE_CDMA_REORDER;
                     toneVolume = RELATIVE_VOLUME_HIPRI;
                     toneLengthMillis = 4000;
+                    mediaResourceId = TONE_RESOURCE_ID_UNDEFINED;
                     break;
                 case TONE_RING_BACK:
                     toneType = ToneGenerator.TONE_SUP_RINGTONE;
                     toneVolume = RELATIVE_VOLUME_HIPRI;
                     toneLengthMillis = Integer.MAX_VALUE - TIMEOUT_BUFFER_MILLIS;
+                    mediaResourceId = TONE_RESOURCE_ID_UNDEFINED;
                     break;
                 case TONE_UNOBTAINABLE_NUMBER:
                     toneType = ToneGenerator.TONE_SUP_ERROR;
                     toneVolume = RELATIVE_VOLUME_HIPRI;
                     toneLengthMillis = 4000;
+                    mediaResourceId = TONE_RESOURCE_ID_UNDEFINED;
                     break;
                 case TONE_VOICE_PRIVACY:
                     // TODO: fill in.
@@ -223,6 +333,7 @@
                     toneType = ToneGenerator.TONE_SUP_CALL_WAITING;
                     toneVolume = RELATIVE_VOLUME_HIPRI;
                     toneLengthMillis = 4000;
+                    mediaResourceId = TONE_RESOURCE_ID_UNDEFINED;
                     break;
                 default:
                     throw new IllegalStateException("Bad toneId: " + mToneId);
@@ -233,16 +344,38 @@
                 stream = AudioManager.STREAM_BLUETOOTH_SCO;
             }
 
+            if (toneType != ToneGenerator.TONE_UNKNOWN) {
+                playToneGeneratorTone(stream, toneVolume, toneType, toneLengthMillis);
+            } else if (mediaResourceId != TONE_RESOURCE_ID_UNDEFINED) {
+                playMediaTone(stream, mediaResourceId);
+            }
+        } finally {
+            cleanUpTonePlayer();
+            Log.endSession();
+        }
+    }
+
+    /**
+     * Play a tone generated by the {@link ToneGenerator}.
+     * @param stream The stream on which the tone will be played.
+     * @param toneVolume The volume of the tone.
+     * @param toneType The type of tone to play.
+     * @param toneLengthMillis How long to play the tone.
+     */
+    private void playToneGeneratorTone(int stream, int toneVolume, int toneType,
+            int toneLengthMillis) {
+        ToneGenerator toneGenerator = null;
+        try {
             // If the ToneGenerator creation fails, just continue without it. It is a local audio
             // signal, and is not as important.
             try {
-                Log.v(this, "Creating generator");
                 toneGenerator = mToneGenerator.get(stream, toneVolume);
             } catch (RuntimeException e) {
                 Log.w(this, "Failed to create ToneGenerator.", e);
                 return;
             }
 
+            Log.i(this, "playToneGeneratorTone: toneType=%d", toneType);
             // TODO: Certain CDMA tones need to check the ringer-volume state before
             // playing. See CallNotifier.InCallTonePlayer.
 
@@ -267,13 +400,61 @@
             if (toneGenerator != null) {
                 toneGenerator.release();
             }
-            cleanUpTonePlayer();
-            Log.endSession();
         }
     }
-    
+
+    /**
+     * Plays an audio-file based media tone.
+     * @param stream The audio stream on which to play the tone.
+     * @param toneResourceId The resource ID of the tone to play.
+     */
+    private void playMediaTone(int stream, int toneResourceId) {
+        synchronized (this) {
+            if (mState != STATE_STOPPED) {
+                mState = STATE_ON;
+            }
+            Log.i(this, "playMediaTone: toneResourceId=%d", toneResourceId);
+            AudioAttributes attributes = new AudioAttributes.Builder()
+                    .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
+                    .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
+                    .setLegacyStreamType(stream)
+                    .build();
+            mToneMediaPlayer = mMediaPlayerFactory.get(toneResourceId, attributes);
+            mToneMediaPlayer.setLooping(false);
+            int durationMillis = mToneMediaPlayer.getDuration();
+            final CountDownLatch toneLatch = new CountDownLatch(1);
+            mToneMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+                @Override
+                public void onCompletion(MediaPlayer mp) {
+                    Log.i(this, "playMediaTone: toneResourceId=%d completed.", toneResourceId);
+                    synchronized (this) {
+                        mState = STATE_OFF;
+                    }
+                    mToneMediaPlayer.release();
+                    mToneMediaPlayer = null;
+                    toneLatch.countDown();
+                }
+            });
+            mToneMediaPlayer.start();
+            try {
+                // Wait for the tone to stop playing; timeout at 2x the length of the file just to
+                // be on the safe side.
+                toneLatch.await(durationMillis * 2, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException ie) {
+                Log.e(this, ie, "playMediaTone: tone playback interrupted.");
+            }
+        }
+
+    }
+
     @VisibleForTesting
-    public void startTone() {
+    public boolean startTone() {
+        // Skip playing the end call tone if the volume is silenced.
+        if (mToneId == TONE_CALL_ENDED && !mAudioManagerAdapter.isVolumeOverZero()) {
+            Log.i(this, "startTone: skip end-call tone as device is silenced.");
+            return false;
+        }
+
         sTonesPlaying++;
         if (sTonesPlaying == 1) {
             mCallAudioManager.setIsTonePlaying(true);
@@ -287,6 +468,7 @@
         }
 
         super.start();
+        return true;
     }
 
     @Override
@@ -308,6 +490,11 @@
         }
     }
 
+    @VisibleForTesting
+    public void cleanup() {
+        sTonesPlaying = 0;
+    }
+
     private void cleanUpTonePlayer() {
         // Release focus on the main thread.
         mMainThreadHandler.post(new Runnable("ICTP.cUTP", mLock) {
diff --git a/src/com/android/server/telecom/LogUtils.java b/src/com/android/server/telecom/LogUtils.java
index 02a3b77..760d24e 100644
--- a/src/com/android/server/telecom/LogUtils.java
+++ b/src/com/android/server/telecom/LogUtils.java
@@ -65,6 +65,7 @@
         public static final String SET_ACTIVE = "SET_ACTIVE";
         public static final String SET_HOLD = "SET_HOLD";
         public static final String SET_RINGING = "SET_RINGING";
+        public static final String SET_ANSWERED = "SET_ANSWERED";
         public static final String SET_DISCONNECTED = "SET_DISCONNECTED";
         public static final String SET_DISCONNECTING = "SET_DISCONNECTING";
         public static final String SET_SELECT_PHONE_ACCOUNT = "SET_SELECT_PHONE_ACCOUNT";
@@ -94,6 +95,7 @@
         public static final String ADD_CHILD = "ADD_CHILD";
         public static final String REMOVE_CHILD = "REMOVE_CHILD";
         public static final String SET_PARENT = "SET_PARENT";
+        public static final String CONF_STATE_CHANGED = "CONF_STATE_CHANGED";
         public static final String MUTE = "MUTE";
         public static final String UNMUTE = "UNMUTE";
         public static final String AUDIO_ROUTE = "AUDIO_ROUTE";
@@ -107,7 +109,10 @@
         public static final String BIND_SCREENING = "BIND_SCREENING";
         public static final String SCREENING_BOUND = "SCREENING_BOUND";
         public static final String SCREENING_SENT = "SCREENING_SENT";
+        public static final String CONTROLLER_SCREENING_COMPLETED =
+                "CONTROLLER_SCREENING_COMPLETED";
         public static final String SCREENING_COMPLETED = "SCREENING_COMPLETED";
+        public static final String CALL_IDENTIFICATION_SET = "CALL_IDENTIFICATION_SET";
         public static final String BLOCK_CHECK_INITIATED = "BLOCK_CHECK_INITIATED";
         public static final String BLOCK_CHECK_FINISHED = "BLOCK_CHECK_FINISHED";
         public static final String DIRECT_TO_VM_INITIATED = "DIRECT_TO_VM_INITIATED";
@@ -136,6 +141,17 @@
         public static final String HANDOVER_FAILED = "HANDOVER_FAILED";
         public static final String START_RINBACK = "START_RINGBACK";
         public static final String STOP_RINGBACK = "STOP_RINGBACK";
+        public static final String REDIRECTION_BOUND_USER = "REDIRECTION_BOUND_USER";
+        public static final String REDIRECTION_BOUND_CARRIER = "REDIRECTION_BOUND_CARRIER";
+        public static final String REDIRECTION_SENT_USER = "REDIRECTION_SENT_USER";
+        public static final String REDIRECTION_SENT_CARRIER = "REDIRECTION_SENT_CARRIER";
+        public static final String REDIRECTION_COMPLETED_USER = "REDIRECTION_COMPLETED_USER";
+        public static final String REDIRECTION_COMPLETED_CARRIER = "REDIRECTION_COMPLETED_CARRIER";
+        public static final String REDIRECTION_TIMED_OUT_USER = "REDIRECTION_TIMED_OUT_USER";
+        public static final String REDIRECTION_TIMED_OUT_CARRIER = "REDIRECTION_TIMED_OUT_CARRIER";
+        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 class Timings {
             public static final String ACCEPT_TIMING = "accept";
diff --git a/src/com/android/server/telecom/LoggedHandlerExecutor.java b/src/com/android/server/telecom/LoggedHandlerExecutor.java
new file mode 100644
index 0000000..cc4dd28
--- /dev/null
+++ b/src/com/android/server/telecom/LoggedHandlerExecutor.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 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.os.Handler;
+import android.telecom.Logging.Runnable;
+
+import java.util.concurrent.Executor;
+
+/** An executor that starts a log session before executing a runnable */
+public class LoggedHandlerExecutor implements Executor {
+    private Handler mHandler;
+    private String mSessionName;
+    private TelecomSystem.SyncRoot mLock;
+
+    public LoggedHandlerExecutor(Handler handler, String sessionName,
+            TelecomSystem.SyncRoot lock) {
+        mHandler = handler;
+        mSessionName = sessionName;
+        mLock = lock;
+    }
+
+    @Override
+    public void execute(java.lang.Runnable command) {
+        mHandler.post(new Runnable(mSessionName, mLock) {
+            @Override
+            public void loggedRun() {
+                command.run();
+            }
+        }.prepare());
+    }
+}
diff --git a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
index 3797c68..9a58c4b 100644
--- a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
+++ b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
@@ -37,6 +37,7 @@
 import android.text.TextUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.telecom.callredirection.CallRedirectionProcessor;
 
 // TODO: Needed for move to system service: import com.android.internal.R;
 
@@ -81,6 +82,19 @@
      */
     private final boolean mIsDefaultOrSystemPhoneApp;
 
+    public static class CallDisposition {
+        // True for certain types of numbers that are not intended to be intercepted or modified
+        // by third parties (e.g. emergency numbers).
+        public boolean callImmediately = false;
+        // True for all managed calls, false for self-managed calls.
+        public boolean sendBroadcast = true;
+        // True for requesting call redirection, false for not requesting it.
+        public boolean requestRedirection = true;
+        public int disconnectCause = DisconnectCause.NOT_DISCONNECTED;
+        String number;
+        Uri callingAddress;
+    }
+
     @VisibleForTesting
     public NewOutgoingCallIntentBroadcaster(Context context, CallsManager callsManager, Call call,
             Intent intent, PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
@@ -192,8 +206,8 @@
      *         {@link DisconnectCause} if the call did not, describing why it failed.
      */
     @VisibleForTesting
-    public int processIntent() {
-        Log.v(this, "Processing call intent in OutgoingCallIntentBroadcaster.");
+    public CallDisposition evaluateCall() {
+        CallDisposition result = new CallDisposition();
 
         Intent intent = mIntent;
         String action = intent.getAction();
@@ -201,7 +215,8 @@
 
         if (handle == null) {
             Log.w(this, "Empty handle obtained from the call intent.");
-            return DisconnectCause.INVALID_NUMBER;
+            result.disconnectCause = DisconnectCause.INVALID_NUMBER;
+            return result;
         }
 
         boolean isVoicemailNumber = PhoneAccount.SCHEME_VOICEMAIL.equals(handle.getScheme());
@@ -209,16 +224,18 @@
             if (Intent.ACTION_CALL.equals(action)
                     || Intent.ACTION_CALL_PRIVILEGED.equals(action)) {
                 // Voicemail calls will be handled directly by the telephony connection manager
-
-                boolean speakerphoneOn = mIntent.getBooleanExtra(
-                        TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false);
-                placeOutgoingCallImmediately(mCall, handle, null, speakerphoneOn,
+                Log.i(this, "Voicemail number dialed. Skipping redirection and broadcast", intent);
+                mIntent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
                         VideoProfile.STATE_AUDIO_ONLY);
-
-                return DisconnectCause.NOT_DISCONNECTED;
+                result.callImmediately = true;
+                result.requestRedirection = false;
+                result.sendBroadcast = false;
+                result.callingAddress = handle;
+                return result;
             } else {
                 Log.i(this, "Unhandled intent %s. Ignoring and not placing call.", intent);
-                return DisconnectCause.OUTGOING_CANCELED;
+                result.disconnectCause = DisconnectCause.OUTGOING_CANCELED;
+                return result;
             }
         }
 
@@ -234,76 +251,88 @@
             }
         }
 
-        String number = "";
-        // True for certain types of numbers that are not intended to be intercepted or modified
-        // by third parties (e.g. emergency numbers).
-        boolean callImmediately = false;
-        // True for all managed calls, false for self-managed calls.
-        boolean sendNewOutgoingCallBroadcast = true;
-        Uri callingAddress = handle;
+        result.number = "";
+        result.callingAddress = handle;
 
-        if (!isSelfManaged) {
-            // Placing a managed call
-            number = mPhoneNumberUtilsAdapter.getNumberFromIntent(intent, mContext);
-            if (TextUtils.isEmpty(number)) {
-                Log.w(this, "Empty number obtained from the call intent.");
-                return DisconnectCause.NO_PHONE_NUMBER_SUPPLIED;
-            }
-
-            // TODO: Cleanup this dialing code; it makes the assumption that we're dialing with a
-            // SIP or TEL URI.
-            boolean isUriNumber = mPhoneNumberUtilsAdapter.isUriNumber(number);
-            if (!isUriNumber) {
-                number = mPhoneNumberUtilsAdapter.convertKeypadLettersToDigits(number);
-                number = mPhoneNumberUtilsAdapter.stripSeparators(number);
-            }
-
-            final boolean isPotentialEmergencyNumber = isPotentialEmergencyNumber(number);
-            Log.v(this, "isPotentialEmergencyNumber = %s", isPotentialEmergencyNumber);
-
-            rewriteCallIntentAction(intent, isPotentialEmergencyNumber);
-            action = intent.getAction();
-
-            if (Intent.ACTION_CALL.equals(action)) {
-                if (isPotentialEmergencyNumber) {
-                    if (!mIsDefaultOrSystemPhoneApp) {
-                        Log.w(this, "Cannot call potential emergency number %s with CALL Intent %s "
-                                + "unless caller is system or default dialer.", number, intent);
-                        launchSystemDialer(intent.getData());
-                        return DisconnectCause.OUTGOING_CANCELED;
-                    } else {
-                        callImmediately = true;
-                    }
-                }
-            } else if (Intent.ACTION_CALL_EMERGENCY.equals(action)) {
-                if (!isPotentialEmergencyNumber) {
-                    Log.w(this, "Cannot call non-potential-emergency number %s with EMERGENCY_CALL "
-                            + "Intent %s.", number, intent);
-                    return DisconnectCause.OUTGOING_CANCELED;
-                }
-                callImmediately = true;
-            } else {
-                Log.w(this, "Unhandled Intent %s. Ignoring and not placing call.", intent);
-                return DisconnectCause.INVALID_NUMBER;
-            }
-
-            // TODO: Support dialing using URIs instead of just assuming SIP or TEL.
-            String scheme = isUriNumber ? PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL;
-            callingAddress = Uri.fromParts(scheme, number, null);
-        } else {
+        if (isSelfManaged) {
             // Self-managed call.
-            callImmediately = true;
-            sendNewOutgoingCallBroadcast = false;
+            result.callImmediately = true;
+            result.sendBroadcast = false;
+            result.requestRedirection = false;
             Log.i(this, "Skipping NewOutgoingCallBroadcast for self-managed call.");
+            return result;
         }
 
-        if (callImmediately) {
+        // Placing a managed call
+        String number = getNumberFromCallIntent(intent);
+        result.number = number;
+        if (number == null) {
+            result.disconnectCause = DisconnectCause.NO_PHONE_NUMBER_SUPPLIED;
+            return result;
+        }
+
+        final boolean isPotentialEmergencyNumber = isPotentialEmergencyNumber(number);
+        Log.v(this, "isPotentialEmergencyNumber = %s", isPotentialEmergencyNumber);
+
+        action = calculateCallIntentAction(intent, isPotentialEmergencyNumber);
+        intent.setAction(action);
+
+        if (Intent.ACTION_CALL.equals(action)) {
+            if (isPotentialEmergencyNumber) {
+                if (!mIsDefaultOrSystemPhoneApp) {
+                    Log.w(this, "Cannot call potential emergency number %s with CALL Intent %s "
+                            + "unless caller is system or default dialer.", number, intent);
+                    launchSystemDialer(intent.getData());
+                    result.disconnectCause = DisconnectCause.OUTGOING_CANCELED;
+                    return result;
+                } else {
+                    result.callImmediately = true;
+                }
+            }
+        } else if (Intent.ACTION_CALL_EMERGENCY.equals(action)) {
+            if (!isPotentialEmergencyNumber) {
+                Log.w(this, "Cannot call non-potential-emergency number %s with EMERGENCY_CALL "
+                        + "Intent %s.", number, intent);
+                result.disconnectCause = DisconnectCause.OUTGOING_CANCELED;
+                return result;
+            }
+            result.callImmediately = true;
+        } else {
+            Log.w(this, "Unhandled Intent %s. Ignoring and not placing call.", intent);
+            result.disconnectCause = DisconnectCause.INVALID_NUMBER;
+            return result;
+        }
+
+        String scheme = mPhoneNumberUtilsAdapter.isUriNumber(number)
+                ? PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL;
+        result.callingAddress = Uri.fromParts(scheme, number, null);
+        return result;
+    }
+
+    private String getNumberFromCallIntent(Intent intent) {
+        String number;
+        number = mPhoneNumberUtilsAdapter.getNumberFromIntent(intent, mContext);
+        if (TextUtils.isEmpty(number)) {
+            Log.w(this, "Empty number obtained from the call intent.");
+            return null;
+        }
+
+        boolean isUriNumber = mPhoneNumberUtilsAdapter.isUriNumber(number);
+        if (!isUriNumber) {
+            number = mPhoneNumberUtilsAdapter.convertKeypadLettersToDigits(number);
+            number = mPhoneNumberUtilsAdapter.stripSeparators(number);
+        }
+        return number;
+    }
+
+    public void processCall(CallDisposition disposition) {
+        if (disposition.callImmediately) {
             boolean speakerphoneOn = mIntent.getBooleanExtra(
                     TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false);
             int videoState = mIntent.getIntExtra(
                     TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
                     VideoProfile.STATE_AUDIO_ONLY);
-            placeOutgoingCallImmediately(mCall, callingAddress, null,
+            placeOutgoingCallImmediately(mCall, disposition.callingAddress, null,
                     speakerphoneOn, videoState);
 
             // Don't return but instead continue and send the ACTION_NEW_OUTGOING_CALL broadcast
@@ -312,12 +341,34 @@
             // initiate the call again because of the presence of the EXTRA_ALREADY_CALLED extra.
         }
 
-        if (sendNewOutgoingCallBroadcast) {
+        boolean callRedirectionWithService = false;
+        if (disposition.requestRedirection) {
+            CallRedirectionProcessor callRedirectionProcessor = new CallRedirectionProcessor(
+                    mContext, mCallsManager, mCall, disposition.callingAddress,
+                    mCallsManager.getPhoneAccountRegistrar(),
+                    getGateWayInfoFromIntent(mIntent, mIntent.getData()),
+                    mIntent.getBooleanExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE,
+                            false),
+                    mIntent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
+                            VideoProfile.STATE_AUDIO_ONLY));
+            /**
+             * If there is an available {@link android.telecom.CallRedirectionService}, use the
+             * {@link CallRedirectionProcessor} to perform call redirection instead of using
+             * broadcasting.
+             */
+            callRedirectionWithService = callRedirectionProcessor
+                    .canMakeCallRedirectionWithService();
+            if (callRedirectionWithService) {
+                callRedirectionProcessor.performCallRedirection();
+            }
+        }
+
+        if (disposition.sendBroadcast) {
             UserHandle targetUser = mCall.getInitiatingUser();
             Log.i(this, "Sending NewOutgoingCallBroadcast for %s to %s", mCall, targetUser);
-            broadcastIntent(intent, number, !callImmediately, targetUser);
+            broadcastIntent(mIntent, disposition.number,
+                    !disposition.callImmediately && !callRedirectionWithService, targetUser);
         }
-        return DisconnectCause.NOT_DISCONNECTED;
     }
 
     /**
@@ -467,14 +518,15 @@
     }
 
     /**
-     * Given a call intent and whether or not the number to dial is an emergency number, rewrite
-     * the call intent action to an appropriate one.
+     * Given a call intent and whether or not the number to dial is an emergency number, determine
+     * the appropriate call intent action.
      *
-     * @param intent Intent to rewrite the action for
+     * @param intent Intent to evaluate
      * @param isPotentialEmergencyNumber Whether or not the number is potentially an emergency
      * number.
+     * @return The appropriate action.
      */
-    private void rewriteCallIntentAction(Intent intent, boolean isPotentialEmergencyNumber) {
+    private String calculateCallIntentAction(Intent intent, boolean isPotentialEmergencyNumber) {
         String action = intent.getAction();
 
         /* Change CALL_PRIVILEGED into CALL or CALL_EMERGENCY as needed. */
@@ -487,8 +539,8 @@
                 action = Intent.ACTION_CALL;
             }
             Log.v(this, " - updating action from CALL_PRIVILEGED to %s", action);
-            intent.setAction(action);
         }
+        return action;
     }
 
     private long getDisconnectTimeoutFromApp(Bundle resultExtras, long defaultTimeout) {
diff --git a/src/com/android/server/telecom/ParcelableCallUtils.java b/src/com/android/server/telecom/ParcelableCallUtils.java
index 77598c8..b936504 100644
--- a/src/com/android/server/telecom/ParcelableCallUtils.java
+++ b/src/com/android/server/telecom/ParcelableCallUtils.java
@@ -16,13 +16,22 @@
 
 package com.android.server.telecom;
 
+import static android.telecom.Call.Details.DIRECTION_INCOMING;
+import static android.telecom.Call.Details.DIRECTION_OUTGOING;
+import static android.telecom.Call.Details.DIRECTION_UNKNOWN;
+
 import android.net.Uri;
+import android.os.Bundle;
 import android.telecom.Connection;
+import android.telecom.DisconnectCause;
 import android.telecom.ParcelableCall;
 import android.telecom.ParcelableRttCall;
 import android.telecom.TelecomManager;
+import android.text.TextUtils;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -31,11 +40,27 @@
 public class ParcelableCallUtils {
     private static final int CALL_STATE_OVERRIDE_NONE = -1;
 
+    /**
+     * A list of extra keys which should be removed from a {@link ParcelableCall} when it is being
+     * generated for the purpose of sending to a dialer other than the system dialer.
+     * By convention we only pass keys namespaced with android.*, however there are some keys which
+     * should not be passed to non-system dialer apps either.
+     */
+    private static List<String> EXTRA_KEYS_TO_SANITIZE;
+    static {
+        EXTRA_KEYS_TO_SANITIZE = new ArrayList<>();
+        EXTRA_KEYS_TO_SANITIZE.add(android.telecom.Connection.EXTRA_SIP_INVITE);
+    }
+
     public static class Converter {
         public ParcelableCall toParcelableCall(Call call, boolean includeVideoProvider,
                 PhoneAccountRegistrar phoneAccountRegistrar) {
             return ParcelableCallUtils.toParcelableCall(
-                    call, includeVideoProvider, phoneAccountRegistrar, false, false);
+                    call, includeVideoProvider, phoneAccountRegistrar, false, false, false);
+        }
+
+        public ParcelableCall toParcelableCallForScreening(Call call) {
+            return ParcelableCallUtils.toParcelableCallForScreening(call);
         }
     }
 
@@ -50,16 +75,23 @@
      * @param phoneAccountRegistrar The {@link PhoneAccountRegistrar}.
      * @param supportsExternalCalls Indicates whether the call should be parcelled for an
      *      {@link InCallService} which supports external calls or not.
+     * @param includeRttCall {@code true} if the RTT call should be included, {@code false}
+     *      otherwise.
+     * @param isForSystemDialer {@code true} if this call is being parcelled for the system dialer,
+     *      {@code false} otherwise.  When parceling for the system dialer, the entire call extras
+     *      is included.  When parceling for anything other than the system dialer, some extra key
+     *      values will be stripped for privacy sake.
      */
     public static ParcelableCall toParcelableCall(
             Call call,
             boolean includeVideoProvider,
             PhoneAccountRegistrar phoneAccountRegistrar,
             boolean supportsExternalCalls,
-            boolean includeRttCall) {
+            boolean includeRttCall,
+            boolean isForSystemDialer) {
         return toParcelableCall(call, includeVideoProvider, phoneAccountRegistrar,
                 supportsExternalCalls, CALL_STATE_OVERRIDE_NONE /* overrideState */,
-                includeRttCall);
+                includeRttCall, isForSystemDialer);
     }
 
     /**
@@ -75,6 +107,10 @@
      *      {@link InCallService} which supports external calls or not.
      * @param overrideState When not {@link #CALL_STATE_OVERRIDE_NONE}, use the provided state as an
      *      override to whatever is defined in the call.
+     * @param isForSystemDialer {@code true} if this call is being parcelled for the system dialer,
+     *      {@code false} otherwise.  When parceling for the system dialer, the entire call extras
+     *      is included.  When parceling for anything other than the system dialer, some extra key
+     *      values will be stripped for privacy sake.
      * @return The {@link ParcelableCall} containing all call information from the {@link Call}.
      */
     public static ParcelableCall toParcelableCall(
@@ -83,7 +119,8 @@
             PhoneAccountRegistrar phoneAccountRegistrar,
             boolean supportsExternalCalls,
             int overrideState,
-            boolean includeRttCall) {
+            boolean includeRttCall,
+            boolean isForSystemDialer) {
         int state;
         if (overrideState == CALL_STATE_OVERRIDE_NONE) {
             state = getParcelableState(call, supportsExternalCalls);
@@ -102,6 +139,10 @@
             properties |= android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL;
         }
 
+        if (call.getIsVoipAudioMode()) {
+            properties |= android.telecom.Call.Details.PROPERTY_VOIP_AUDIO_MODE;
+        }
+
         // If this is a single-SIM device, the "default SIM" will always be the only SIM.
         boolean isDefaultSmsAccount = phoneAccountRegistrar != null &&
                 phoneAccountRegistrar.isUserSelectedSmsPhoneAccount(call.getTargetPhoneAccount());
@@ -157,6 +198,21 @@
         }
 
         ParcelableRttCall rttCall = includeRttCall ? getParcelableRttCall(call) : null;
+        int callDirection;
+        if (call.isIncoming()) {
+            callDirection = DIRECTION_INCOMING;
+        } else if (call.isUnknown()) {
+            callDirection = DIRECTION_UNKNOWN;
+        } else {
+            callDirection = DIRECTION_OUTGOING;
+        }
+
+        Bundle extras;
+        if (isForSystemDialer) {
+            extras = call.getExtras();
+        } else {
+            extras = sanitizeExtras(call.getExtras());
+        }
 
         return new ParcelableCall(
                 call.getId(),
@@ -183,8 +239,91 @@
                 call.getVideoState(),
                 conferenceableCallIds,
                 call.getIntentExtras(),
-                call.getExtras(),
-                call.getCreationTimeMillis());
+                extras,
+                call.getCreationTimeMillis(),
+                callDirection);
+    }
+
+    /**
+     * Creates a ParcelableCall with the bare minimum properties required for a
+     * {@link android.telecom.CallScreeningService}.  We ONLY expose the following:
+     * <ul>
+     *     <li>Call Id (not exposed to public, but needed to associated calls)</li>
+     *     <li>Call directoin</li>
+     *     <li>Creation time</li>
+     *     <li>Connection time</li>
+     *     <li>Handle (phone number)</li>
+     *     <li>Handle (phone number) presentation</li>
+     * </ul>
+     * All other fields are nulled or set to 0 values.
+     * @param call The telecom call to send to a call screening service.
+     * @return Minimal {@link ParcelableCall} to send to the call screening service.
+     */
+    public static ParcelableCall toParcelableCallForScreening(Call call) {
+        Uri handle = call.getHandlePresentation() == TelecomManager.PRESENTATION_ALLOWED ?
+                call.getHandle() : null;
+        int callDirection;
+        if (call.isIncoming()) {
+            callDirection = DIRECTION_INCOMING;
+        } else if (call.isUnknown()) {
+            callDirection = DIRECTION_UNKNOWN;
+        } else {
+            callDirection = DIRECTION_OUTGOING;
+        }
+        return new ParcelableCall(
+                call.getId(),
+                getParcelableState(call, false /* supportsExternalCalls */),
+                new DisconnectCause(DisconnectCause.UNKNOWN),
+                null, /* cannedSmsResponses */
+                0, /* capabilities */
+                0, /* properties */
+                0, /* supportedAudioRoutes */
+                call.getConnectTimeMillis(),
+                handle,
+                call.getHandlePresentation(),
+                null, /* callerDisplayName */
+                0 /* callerDisplayNamePresentation */,
+                null, /* gatewayInfo */
+                null, /* targetPhoneAccount */
+                false, /* includeVideoProvider */
+                null, /* videoProvider */
+                false, /* includeRttCall */
+                null, /* rttCall */
+                null, /* parentCallId */
+                null, /* childCallIds */
+                null, /* statusHints */
+                0, /* videoState */
+                Collections.emptyList(), /* conferenceableCallIds */
+                null, /* intentExtras */
+                null, /* callExtras */
+                call.getCreationTimeMillis(),
+                callDirection);
+    }
+
+    /**
+     * Sanitize the extras bundle passed in, removing keys which should not be sent to non-system
+     * dialer apps.
+     * @param extras Extras bundle to sanitize.
+     * @return The sanitized extras bundle.
+     */
+    private static Bundle sanitizeExtras(Bundle oldExtras) {
+        if (oldExtras == null) {
+            return new Bundle();
+        }
+        Bundle extras = new Bundle(oldExtras);
+        for (String key : EXTRA_KEYS_TO_SANITIZE) {
+            extras.remove(key);
+        }
+
+        // As a catch-all remove any that don't start with android namespace.
+        Iterator<String> toCheck = extras.keySet().iterator();
+        while (toCheck.hasNext()) {
+            String extraKey = toCheck.next();
+            if (TextUtils.isEmpty(extraKey) || !extraKey.startsWith("android.")) {
+                toCheck.remove();
+            }
+        }
+        return extras;
     }
 
     private static int getParcelableState(Call call, boolean supportsExternalCalls) {
@@ -226,6 +365,8 @@
                 state = android.telecom.Call.STATE_HOLDING;
                 break;
             case CallState.RINGING:
+            case CallState.ANSWERED:
+                // TODO: does in-call UI need to see ANSWERED?
                 state = android.telecom.Call.STATE_RINGING;
                 break;
             case CallState.SELECT_PHONE_ACCOUNT:
@@ -345,7 +486,10 @@
         android.telecom.Call.Details.PROPERTY_ASSISTED_DIALING_USED,
 
         Connection.PROPERTY_IS_RTT,
-        android.telecom.Call.Details.PROPERTY_RTT
+        android.telecom.Call.Details.PROPERTY_RTT,
+
+        Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL,
+        android.telecom.Call.Details.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL
     };
 
     private static int convertConnectionToCallProperties(int connectionProperties) {
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index d84fca5..fbd9d02 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -17,6 +17,7 @@
 package com.android.server.telecom;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -125,6 +126,8 @@
                                              PhoneAccountHandle handle) {}
         public void onPhoneAccountUnRegistered(PhoneAccountRegistrar registrar,
                                              PhoneAccountHandle handle) {}
+        public void onPhoneAccountChanged(PhoneAccountRegistrar registrar,
+                PhoneAccount phoneAccount) {}
     }
 
     /**
@@ -135,7 +138,7 @@
         CharSequence getAppLabel(String packageName);
     }
 
-    private static final String FILE_NAME = "phone-account-registrar-state.xml";
+    public static final String FILE_NAME = "phone-account-registrar-state.xml";
     @VisibleForTesting
     public static final int EXPECTED_STATE_VERSION = 9;
 
@@ -309,6 +312,11 @@
         if (userHandle == null) {
             return;
         }
+        DefaultPhoneAccountHandle currentDefaultInfo =
+                mState.defaultOutgoingAccountHandles.get(userHandle);
+        PhoneAccountHandle currentDefaultPhoneAccount = currentDefaultInfo == null ? null :
+                currentDefaultInfo.phoneAccountHandle;
+        boolean isSimAccount = false;
         if (accountHandle == null) {
             // Asking to clear the default outgoing is a valid request
             mState.defaultOutgoingAccountHandles.remove(userHandle);
@@ -329,15 +337,33 @@
             if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
                 // If the account selected is a SIM account, propagate down to the subscription
                 // record.
-                int subId = getSubscriptionIdForPhoneAccount(accountHandle);
-                mSubscriptionManager.setDefaultVoiceSubId(subId);
+                isSimAccount = true;
             }
 
+            Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s", accountHandle);
             mState.defaultOutgoingAccountHandles
                     .put(userHandle, new DefaultPhoneAccountHandle(userHandle, accountHandle,
                             account.getGroupId()));
         }
 
+        // Potentially update the default voice subid in SubscriptionManager.
+        if (!Objects.equals(currentDefaultPhoneAccount, accountHandle)) {
+            int newSubId = accountHandle == null ? SubscriptionManager.INVALID_SUBSCRIPTION_ID :
+                    getSubscriptionIdForPhoneAccount(accountHandle);
+            if (isSimAccount || accountHandle == null) {
+                int currentVoiceSubId = mSubscriptionManager.getDefaultVoiceSubscriptionId();
+                if (newSubId != currentVoiceSubId) {
+                    Log.i(this, "setUserSelectedOutgoingPhoneAccount: update voice sub; "
+                            + "account=%s, subId=%d", accountHandle, newSubId);
+                    mSubscriptionManager.setDefaultVoiceSubId(newSubId);
+                }
+            } else {
+                Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s is not a sub", accountHandle);
+            }
+        } else {
+            Log.i(this, "setUserSelectedOutgoingPhoneAccount: no change to voice sub");
+        }
+
         write();
         fireDefaultOutgoingChanged();
     }
@@ -650,6 +676,21 @@
         return getPhoneAccountHandles(0, null, packageName, false, userHandle);
     }
 
+    /**
+     * Determines if a {@link PhoneAccountHandle} is for a self-managed {@link ConnectionService}.
+     * @param handle The handle.
+     * @return {@code true} if for a self-managed {@link ConnectionService}, {@code false}
+     * otherwise.
+     */
+    public boolean isSelfManagedPhoneAccount(@NonNull PhoneAccountHandle handle) {
+        PhoneAccount account = getPhoneAccountUnchecked(handle);
+        if (account == null) {
+            return false;
+        }
+
+        return account.isSelfManaged();
+    }
+
     // TODO: Should we implement an artificial limit for # of accounts associated with a single
     // ComponentName?
     public void registerPhoneAccount(PhoneAccount account) {
@@ -727,6 +768,8 @@
         fireAccountsChanged();
         if (isNewAccount) {
             fireAccountRegistered(account.getAccountHandle());
+        } else {
+            fireAccountChanged(account);
         }
     }
 
@@ -788,6 +831,12 @@
         }
     }
 
+    private void fireAccountChanged(PhoneAccount account) {
+        for (Listener l : mListeners) {
+            l.onPhoneAccountChanged(this, account);
+        }
+    }
+
     private void fireAccountUnRegistered(PhoneAccountHandle handle) {
         for (Listener l : mListeners) {
             l.onPhoneAccountUnRegistered(this, handle);
@@ -815,7 +864,7 @@
         sb.append("[").append(account1.getAccountHandle());
         appendDiff(sb, "addr", Log.piiHandle(account1.getAddress()),
                 Log.piiHandle(account2.getAddress()));
-        appendDiff(sb, "cap", account1.getCapabilities(), account2.getCapabilities());
+        appendDiff(sb, "cap", account1.capabilitiesToString(), account2.capabilitiesToString());
         appendDiff(sb, "hl", account1.getHighlightColor(), account2.getHighlightColor());
         appendDiff(sb, "lbl", account1.getLabel(), account2.getLabel());
         appendDiff(sb, "desc", account1.getShortDescription(), account2.getShortDescription());
diff --git a/src/com/android/server/telecom/PhoneAccountSuggestionHelper.java b/src/com/android/server/telecom/PhoneAccountSuggestionHelper.java
new file mode 100644
index 0000000..438ee68
--- /dev/null
+++ b/src/com/android/server/telecom/PhoneAccountSuggestionHelper.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2018 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.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.content.pm.ServiceInfo;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.telecom.Log;
+import android.telecom.Logging.Session;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.PhoneAccountSuggestion;
+import android.telecom.PhoneAccountSuggestionService;
+import android.telephony.PhoneNumberUtils;
+import android.text.TextUtils;
+
+import com.android.internal.telecom.IPhoneAccountSuggestionCallback;
+import com.android.internal.telecom.IPhoneAccountSuggestionService;
+
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class PhoneAccountSuggestionHelper {
+    private static final String TAG = PhoneAccountSuggestionHelper.class.getSimpleName();
+    private static ComponentName sOverrideComponent;
+
+    /**
+     * @return A future (possible already complete) that contains a list of suggestions.
+     */
+    public static CompletableFuture<List<PhoneAccountSuggestion>>
+    bindAndGetSuggestions(Context context, Uri handle,
+            List<PhoneAccountHandle> availablePhoneAccounts) {
+        // Use the default list if there's no handle
+        if (handle == null) {
+            return CompletableFuture.completedFuture(getDefaultSuggestions(availablePhoneAccounts));
+        }
+        String number = PhoneNumberUtils.extractNetworkPortion(handle.getSchemeSpecificPart());
+
+        // Use the default list if there's no service on the device.
+        ServiceInfo suggestionServiceInfo = getSuggestionServiceInfo(context);
+        if (suggestionServiceInfo == null) {
+            return CompletableFuture.completedFuture(getDefaultSuggestions(availablePhoneAccounts));
+        }
+
+        Intent bindIntent = new Intent();
+        bindIntent.setComponent(new ComponentName(suggestionServiceInfo.packageName,
+                suggestionServiceInfo.name));
+
+        final CompletableFuture<List<PhoneAccountSuggestion>> future = new CompletableFuture<>();
+
+        final Session logSession = Log.createSubsession();
+        ServiceConnection serviceConnection = new ServiceConnection() {
+            @Override
+            public void onServiceConnected(ComponentName name, IBinder _service) {
+                Log.continueSession(logSession, "PASH.oSC");
+                try {
+                    IPhoneAccountSuggestionService service =
+                            IPhoneAccountSuggestionService.Stub.asInterface(_service);
+                    // Set up the callback to complete the future once the remote side comes
+                    // back with suggestions
+                    IPhoneAccountSuggestionCallback callback =
+                            new IPhoneAccountSuggestionCallback.Stub() {
+                                @Override
+                                public void suggestPhoneAccounts(String suggestResultNumber,
+                                        List<PhoneAccountSuggestion> suggestions) {
+                                    if (TextUtils.equals(number, suggestResultNumber)) {
+                                        if (suggestions == null) {
+                                            future.complete(
+                                                    getDefaultSuggestions(availablePhoneAccounts));
+                                        } else {
+                                            future.complete(
+                                                    addDefaultsToProvidedSuggestions(
+                                                            suggestions, availablePhoneAccounts));
+                                        }
+                                    }
+                                }
+                            };
+                    try {
+                        service.onAccountSuggestionRequest(callback, number);
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Cancelling suggestion process due to remote exception");
+                        future.complete(getDefaultSuggestions(availablePhoneAccounts));
+                    }
+                } finally {
+                    Log.endSession();
+                }
+            }
+
+            @Override
+            public void onServiceDisconnected(ComponentName name) {
+                // No locking needed -- CompletableFuture only lets one thread call complete.
+                Log.continueSession(logSession, "PASH.oSD");
+                try {
+                    if (!future.isDone()) {
+                        Log.w(TAG, "Cancelling suggestion process due to service disconnect");
+                    }
+                    future.complete(getDefaultSuggestions(availablePhoneAccounts));
+                } finally {
+                    Log.endSession();
+                }
+            }
+        };
+
+        if (!context.bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE)) {
+            Log.i(TAG, "Cancelling suggestion process due to bind failure.");
+            future.complete(getDefaultSuggestions(availablePhoneAccounts));
+        }
+
+        // Set up a timeout so that we're not waiting forever for the suggestion service.
+        Handler handler = new Handler();
+        handler.postDelayed(() -> {
+                    // No locking needed -- CompletableFuture only lets one thread call complete.
+                    Log.continueSession(logSession, "PASH.timeout");
+                    try {
+                        if (!future.isDone()) {
+                            Log.w(TAG, "Cancelling suggestion process due to timeout");
+                        }
+                        future.complete(getDefaultSuggestions(availablePhoneAccounts));
+                    } finally {
+                        Log.endSession();
+                    }
+                },
+                Timeouts.getPhoneAccountSuggestionServiceTimeout(context.getContentResolver()));
+        return future;
+    }
+
+    private static List<PhoneAccountSuggestion> addDefaultsToProvidedSuggestions(
+            List<PhoneAccountSuggestion> providedSuggestions,
+            List<PhoneAccountHandle> availableAccountHandles) {
+        List<PhoneAccountHandle> handlesInSuggestions = providedSuggestions.stream()
+                .map(PhoneAccountSuggestion::getPhoneAccountHandle)
+                .collect(Collectors.toList());
+        List<PhoneAccountHandle> handlesToFillIn = availableAccountHandles.stream()
+                .filter(handle -> !handlesInSuggestions.contains(handle))
+                .collect(Collectors.toList());
+        List<PhoneAccountSuggestion> suggestionsToAppend = getDefaultSuggestions(handlesToFillIn);
+        return Stream.concat(suggestionsToAppend.stream(), providedSuggestions.stream())
+                .collect( Collectors.toList());
+    }
+
+    private static ServiceInfo getSuggestionServiceInfo(Context context) {
+        PackageManager packageManager = context.getPackageManager();
+        Intent queryIntent = new Intent();
+        queryIntent.setAction(PhoneAccountSuggestionService.SERVICE_INTERFACE);
+
+        List<ResolveInfo> services;
+        if (sOverrideComponent == null) {
+            services = packageManager.queryIntentServices(queryIntent,
+                    PackageManager.MATCH_SYSTEM_ONLY);
+        } else {
+            Log.i(TAG, "Using override component %s", sOverrideComponent);
+            queryIntent.setComponent(sOverrideComponent);
+            services = packageManager.queryIntentServices(queryIntent,
+                    PackageManager.MATCH_ALL);
+        }
+
+        if (services == null || services.size() == 0) {
+            Log.i(TAG, "No acct suggestion services found. Using defaults.");
+            return null;
+        }
+
+        if (services.size() > 1) {
+            Log.w(TAG, "More than acct suggestion service found, cannot get unique service");
+            return null;
+        }
+        return services.get(0).serviceInfo;
+    }
+
+    static void setOverrideServiceName(String flattenedComponentName) {
+        try {
+            sOverrideComponent = TextUtils.isEmpty(flattenedComponentName)
+                    ? null : ComponentName.unflattenFromString(flattenedComponentName);
+        } catch (Exception e) {
+            sOverrideComponent = null;
+            throw e;
+        }
+    }
+
+    private static List<PhoneAccountSuggestion> getDefaultSuggestions(
+            List<PhoneAccountHandle> phoneAccountHandles) {
+        return phoneAccountHandles.stream().map(phoneAccountHandle ->
+                new PhoneAccountSuggestion(phoneAccountHandle,
+                        PhoneAccountSuggestion.REASON_NONE, false)
+        ).collect(Collectors.toList());
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/server/telecom/PhoneNumberUtilsAdapterImpl.java b/src/com/android/server/telecom/PhoneNumberUtilsAdapterImpl.java
index 7ff854e..8b3c856 100644
--- a/src/com/android/server/telecom/PhoneNumberUtilsAdapterImpl.java
+++ b/src/com/android/server/telecom/PhoneNumberUtilsAdapterImpl.java
@@ -19,16 +19,21 @@
 import android.content.Context;
 import android.content.Intent;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
 
 public class PhoneNumberUtilsAdapterImpl implements PhoneNumberUtilsAdapter {
     @Override
     public boolean isLocalEmergencyNumber(Context context, String number) {
-            return PhoneNumberUtils.isLocalEmergencyNumber(context, number);
+        TelephonyManager tm = (TelephonyManager) context.getSystemService(
+                Context.TELEPHONY_SERVICE);
+        return tm.isEmergencyNumber(number);
     }
 
     @Override
     public boolean isPotentialLocalEmergencyNumber(Context context, String number) {
-        return PhoneNumberUtils.isPotentialLocalEmergencyNumber(context, number);
+        TelephonyManager tm = (TelephonyManager) context.getSystemService(
+                Context.TELEPHONY_SERVICE);
+        return tm.isPotentialEmergencyNumber(number);
     }
 
     @Override
diff --git a/src/com/android/server/telecom/QuickResponseUtils.java b/src/com/android/server/telecom/QuickResponseUtils.java
index 5f8269d..84d2636 100644
--- a/src/com/android/server/telecom/QuickResponseUtils.java
+++ b/src/com/android/server/telecom/QuickResponseUtils.java
@@ -117,4 +117,48 @@
         Log.d(LOG_TAG, "maybeMigrateLegacyQuickResponses() - Done.");
         return;
     }
+
+    /**
+     * Determine if the user has changed any of the quick responses back to exactly the same text as
+     * the default text.  If they did, clear the preference so we'll rely on the default value and
+     * still be able to re-translate automatically when language changes occur.
+     *
+     * @param context The current context.
+     * @param prefs   The quick response shared prefs.
+     */
+    public static void maybeResetQuickResponses(Context context, SharedPreferences prefs) {
+        final Resources res = context.getResources();
+
+        String defaultResponse1 = res.getString(R.string.respond_via_sms_canned_response_1);
+        String currentValue1 = prefs.getString(QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_1, "");
+        if (currentValue1.equals(defaultResponse1)) {
+            prefs.edit().remove(QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_1).apply();
+            Log.i(QuickResponseUtils.class,
+                    "maybeResetQuickResponses: response 1 is identical to default; clear pref.");
+        }
+
+        String defaultResponse2 = res.getString(R.string.respond_via_sms_canned_response_2);
+        String currentValue2 = prefs.getString(QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_2, "");
+        if (currentValue2.equals(defaultResponse2)) {
+            prefs.edit().remove(QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_2).apply();
+            Log.i(QuickResponseUtils.class,
+                    "maybeResetQuickResponses: response 2 is identical to default; clear pref.");
+        }
+
+        String defaultResponse3 = res.getString(R.string.respond_via_sms_canned_response_3);
+        String currentValue3 = prefs.getString(QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_3, "");
+        if (currentValue3.equals(defaultResponse3)) {
+            prefs.edit().remove(QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_3).apply();
+            Log.i(QuickResponseUtils.class,
+                    "maybeResetQuickResponses: response 3 is identical to default; clear pref.");
+        }
+
+        String defaultResponse4 = res.getString(R.string.respond_via_sms_canned_response_4);
+        String currentValue4 = prefs.getString(QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_4, "");
+        if (currentValue4.equals(defaultResponse4)) {
+            prefs.edit().remove(QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_4).apply();
+            Log.i(QuickResponseUtils.class,
+                    "maybeResetQuickResponses: response 4 is identical to default; clear pref.");
+        }
+    }
 }
diff --git a/src/com/android/server/telecom/RespondViaSmsManager.java b/src/com/android/server/telecom/RespondViaSmsManager.java
index 964f6ad..ac9ee3c 100644
--- a/src/com/android/server/telecom/RespondViaSmsManager.java
+++ b/src/com/android/server/telecom/RespondViaSmsManager.java
@@ -17,16 +17,14 @@
 package com.android.server.telecom;
 
 // TODO: Needed for move to system service: import com.android.internal.R;
-import com.android.internal.os.SomeArgs;
-import com.android.internal.telephony.SmsApplication;
-
-import android.content.ComponentName;
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.SharedPreferences;
 import android.content.res.Resources;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
 import android.telecom.Connection;
 import android.telecom.Log;
 import android.telecom.Response;
@@ -45,30 +43,37 @@
  * Helper class to manage the "Respond via Message" feature for incoming calls.
  */
 public class RespondViaSmsManager extends CallsManagerListenerBase {
-    private static final int MSG_SHOW_SENT_TOAST = 2;
+    private static final String ACTION_MESSAGE_SENT = "com.android.server.telecom.MESSAGE_SENT";
+
+    private static final class MessageSentReceiver extends BroadcastReceiver {
+        private final String mContactName;
+        private final int mNumMessageParts;
+        private int mNumMessagesSent = 0;
+        MessageSentReceiver(String contactName, int numMessageParts) {
+            mContactName = contactName;
+            mNumMessageParts = numMessageParts;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (getResultCode() == Activity.RESULT_OK) {
+                mNumMessagesSent++;
+                if (mNumMessagesSent == mNumMessageParts) {
+                    showMessageResultToast(mContactName, context, true);
+                    context.unregisterReceiver(this);
+                }
+            } else {
+                context.unregisterReceiver(this);
+                showMessageResultToast(mContactName, context, false);
+                Log.w(RespondViaSmsManager.class.getSimpleName(),
+                        "Message failed with error %s", getResultCode());
+            }
+        }
+    }
 
     private final CallsManager mCallsManager;
     private final TelecomSystem.SyncRoot mLock;
 
-    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_SHOW_SENT_TOAST: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    try {
-                        String toastMessage = (String) args.arg1;
-                        Context context = (Context) args.arg2;
-                        showMessageSentToast(toastMessage, context);
-                    } finally {
-                        args.recycle();
-                    }
-                    break;
-                }
-            }
-        }
-    };
-
     public RespondViaSmsManager(CallsManager callsManager, TelecomSystem.SyncRoot lock) {
         mCallsManager = callsManager;
         mLock = lock;
@@ -105,6 +110,11 @@
                 final ArrayList<String> textMessages = new ArrayList<>(
                         QuickResponseUtils.NUM_CANNED_RESPONSES);
 
+                // Where the user has changed a quick response back to the same text as the
+                // original text, clear the shared pref.  This ensures we always load the resource
+                // in the current active language.
+                QuickResponseUtils.maybeResetQuickResponses(context, prefs);
+
                 // Note the default values here must agree with the corresponding
                 // android:defaultValue attributes in respond_via_sms_settings.xml.
                 textMessages.add(0, prefs.getString(QuickResponseUtils.KEY_CANNED_RESPONSE_PREF_1,
@@ -139,13 +149,15 @@
         }
     }
 
-    private void showMessageSentToast(final String phoneNumber, final Context context) {
+    private static void showMessageResultToast(final String phoneNumber,
+            final Context context, boolean success) {
         // ...and show a brief confirmation to the user (since
         // otherwise it's hard to be sure that anything actually
         // happened.)
         final Resources res = context.getResources();
-        final String formatString = res.getString(
-                R.string.respond_via_sms_confirmation_format);
+        final String formatString = res.getString(success
+                ? R.string.respond_via_sms_confirmation_format
+                : R.string.respond_via_sms_failure_format);
         final String confirmationMsg = String.format(formatString, phoneNumber);
         int startingPosition = confirmationMsg.indexOf(phoneNumber);
         int endingPosition = startingPosition + phoneNumber.length();
@@ -187,13 +199,20 @@
 
         SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId);
         try {
-            smsManager.sendTextMessage(phoneNumber, null, textMessage, null /*sentIntent*/,
-                    null /*deliveryIntent*/);
-
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = !TextUtils.isEmpty(contactName) ? contactName : phoneNumber;
-            args.arg2 = context;
-            mHandler.obtainMessage(MSG_SHOW_SENT_TOAST, args).sendToTarget();
+            ArrayList<String> messageParts = smsManager.divideMessage(textMessage);
+            ArrayList<PendingIntent> sentIntents = new ArrayList<>(messageParts.size());
+            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);
+                sentIntents.add(pendingIntent);
+            }
+            MessageSentReceiver receiver = new MessageSentReceiver(
+                    !TextUtils.isEmpty(contactName) ? contactName : phoneNumber,
+                    messageParts.size());
+            context.registerReceiver(receiver, new IntentFilter(ACTION_MESSAGE_SENT));
+            smsManager.sendMultipartTextMessageExternal(phoneNumber, null, messageParts,
+                    sentIntents/*sentIntent*/, null /*deliveryIntent*/, context.getOpPackageName());
         } catch (IllegalArgumentException e) {
             Log.w(RespondViaSmsManager.this, "Couldn't send SMS message: " +
                     e.getMessage());
diff --git a/src/com/android/server/telecom/RespondViaSmsSettings.java b/src/com/android/server/telecom/RespondViaSmsSettings.java
index 2ea204a..3bee5f7 100644
--- a/src/com/android/server/telecom/RespondViaSmsSettings.java
+++ b/src/com/android/server/telecom/RespondViaSmsSettings.java
@@ -54,6 +54,7 @@
 
         getPreferenceManager().setSharedPreferencesName(QuickResponseUtils.SHARED_PREFERENCES_NAME);
         mPrefs = getPreferenceManager().getSharedPreferences();
+        QuickResponseUtils.maybeResetQuickResponses(this, mPrefs);
     }
 
     @Override
@@ -108,6 +109,9 @@
         SharedPreferences.Editor editor = mPrefs.edit();
         editor.putString(pref.getKey(), (String) newValue).commit();
 
+        // If the user just reset the quick response to its original text, clear the pref.
+        QuickResponseUtils.maybeResetQuickResponses(this, mPrefs);
+
         return true;  // means it's OK to update the state of the Preference with the new value
     }
 
diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java
index 1d27f45..9baaef0 100644
--- a/src/com/android/server/telecom/Ringer.java
+++ b/src/com/android/server/telecom/Ringer.java
@@ -39,6 +39,15 @@
  */
 @VisibleForTesting
 public class Ringer {
+    public static class VibrationEffectProxy {
+        public VibrationEffect createWaveform(long[] timings, int[] amplitudes, int repeat) {
+            return VibrationEffect.createWaveform(timings, amplitudes, repeat);
+        }
+
+        public VibrationEffect get(Uri ringtoneUri, Context context) {
+            return VibrationEffect.get(ringtoneUri, context);
+        }
+    }
     @VisibleForTesting
     public VibrationEffect mDefaultVibrationEffect;
 
@@ -89,6 +98,7 @@
     private final Context mContext;
     private final Vibrator mVibrator;
     private final InCallController mInCallController;
+    private final VibrationEffectProxy mVibrationEffectProxy;
 
     private InCallTonePlayer mCallWaitingPlayer;
     private RingtoneFactory mRingtoneFactory;
@@ -115,6 +125,7 @@
             AsyncRingtonePlayer asyncRingtonePlayer,
             RingtoneFactory ringtoneFactory,
             Vibrator vibrator,
+            VibrationEffectProxy vibrationEffectProxy,
             InCallController inCallController) {
 
         mSystemSettingsUtil = systemSettingsUtil;
@@ -126,12 +137,13 @@
         mRingtonePlayer = asyncRingtonePlayer;
         mRingtoneFactory = ringtoneFactory;
         mInCallController = inCallController;
+        mVibrationEffectProxy = vibrationEffectProxy;
 
         if (mContext.getResources().getBoolean(R.bool.use_simple_vibration_pattern)) {
-            mDefaultVibrationEffect = VibrationEffect.createWaveform(SIMPLE_VIBRATION_PATTERN,
+            mDefaultVibrationEffect = mVibrationEffectProxy.createWaveform(SIMPLE_VIBRATION_PATTERN,
                     SIMPLE_VIBRATION_AMPLITUDE, REPEAT_SIMPLE_VIBRATION_AT);
         } else {
-            mDefaultVibrationEffect = VibrationEffect.createWaveform(PULSE_PATTERN,
+            mDefaultVibrationEffect = mVibrationEffectProxy.createWaveform(PULSE_PATTERN,
                     PULSE_AMPLITUDE, REPEAT_VIBRATION_AT);
         }
     }
@@ -167,7 +179,7 @@
 
         if (endEarly) {
             if (letDialerHandleRinging) {
-                Log.addEvent(foregroundCall, LogUtils.Events.SKIP_RINGING);
+                Log.addEvent(foregroundCall, LogUtils.Events.SKIP_RINGING, "Dialer handles");
             }
             Log.i(this, "Ending early -- isTheaterModeOn=%s, letDialerHandleRinging=%s, " +
                     "isSelfManaged=%s, hasExternalRinger=%s", isTheaterModeOn,
@@ -188,9 +200,11 @@
             mRingtonePlayer.play(mRingtoneFactory, foregroundCall);
             effect = getVibrationEffectForCall(mRingtoneFactory, foregroundCall);
         } else {
-            Log.i(this, "startRinging: skipping because ringer would not be audible. " +
+            String reason = String.format(
                     "isVolumeOverZero=%s, shouldRingForContact=%s, isRingtonePresent=%s",
                     isVolumeOverZero, shouldRingForContact, isRingtonePresent);
+            Log.i(this, "startRinging: skipping because ringer would not be audible. " + reason);
+            Log.addEvent(foregroundCall, LogUtils.Events.SKIP_RINGING, "Inaudible: " + reason);
             effect = mDefaultVibrationEffect;
         }
 
@@ -209,7 +223,16 @@
         Ringtone ringtone = factory.getRingtone(call);
         Uri ringtoneUri = ringtone != null ? ringtone.getUri() : null;
         if (ringtoneUri != null) {
-            effect = VibrationEffect.get(ringtoneUri, mContext);
+            try {
+                effect = mVibrationEffectProxy.get(ringtoneUri, mContext);
+            } catch (IllegalArgumentException iae) {
+                // Deep in the bowels of the VibrationEffect class it is possible for an
+                // IllegalArgumentException to be thrown if there is an invalid URI specified in the
+                // device config, or a content provider failure.  Rather than crashing the Telecom
+                // process we will just use the default vibration effect.
+                Log.e(this, iae, "getVibrationEffectForCall: failed to get vibration effect");
+                effect = null;
+            }
         }
 
         if (effect == null) {
@@ -219,12 +242,16 @@
     }
 
     public void startCallWaiting(Call call) {
+        startCallWaiting(call, null);
+    }
+
+    public void startCallWaiting(Call call, String reason) {
         if (mSystemSettingsUtil.isTheaterModeOn(mContext)) {
             return;
         }
 
         if (mInCallController.doesConnectedDialerSupportRinging()) {
-            Log.addEvent(call, LogUtils.Events.SKIP_RINGING);
+            Log.addEvent(call, LogUtils.Events.SKIP_RINGING, "Dialer handles");
             return;
         }
 
@@ -238,7 +265,7 @@
         stopRinging();
 
         if (mCallWaitingPlayer == null) {
-            Log.addEvent(call, LogUtils.Events.START_CALL_WAITING_TONE);
+            Log.addEvent(call, LogUtils.Events.START_CALL_WAITING_TONE, reason);
             mCallWaitingCall = call;
             mCallWaitingPlayer =
                     mPlayerFactory.createPlayer(InCallTonePlayer.TONE_CALL_WAITING);
diff --git a/src/com/android/server/telecom/RingtoneFactory.java b/src/com/android/server/telecom/RingtoneFactory.java
index b452338..7d06b9e 100644
--- a/src/com/android/server/telecom/RingtoneFactory.java
+++ b/src/com/android/server/telecom/RingtoneFactory.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.RingtoneManager;
 import android.media.Ringtone;
@@ -81,7 +82,10 @@
             ringtone = RingtoneManager.getRingtone(contextToUse, defaultRingtoneUri);
         }
         if (ringtone != null) {
-            ringtone.setStreamType(AudioManager.STREAM_RING);
+            ringtone.setAudioAttributes(new AudioAttributes.Builder()
+                    .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
+                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                    .build());
         }
         return ringtone;
     }
diff --git a/src/com/android/server/telecom/RoleManagerAdapter.java b/src/com/android/server/telecom/RoleManagerAdapter.java
new file mode 100644
index 0000000..c06339c
--- /dev/null
+++ b/src/com/android/server/telecom/RoleManagerAdapter.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 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.os.UserHandle;
+
+import java.util.List;
+
+/**
+ * Provides a means of wrapping {@code RoleManager} operations which Telecom uses to aid in testing
+ * and remove direct dependencies.
+ */
+public interface RoleManagerAdapter {
+    /**
+     * Returns the package name of the app which fills the {@link android.app.role.RoleManager} call
+     * redirection role.
+     * @return the package name of the app filling the role, {@code null} otherwise}.
+     */
+    String getDefaultCallRedirectionApp();
+
+    /**
+     * Override the {@link android.app.role.RoleManager} call redirection app with another value.
+     * Used for testing purposes only.
+     * @param packageName Package name of the app to fill the call redirection role.  Where
+     *                    {@code null}, the override is removed.
+     */
+    void setTestDefaultCallRedirectionApp(String packageName);
+
+    /**
+     * Returns the package name of the app which fills the {@link android.app.role.RoleManager} call
+     * screening role.
+     * @return the package name of the app filling the role, {@code null} otherwise}.
+     */
+    String getDefaultCallScreeningApp();
+
+    /**
+     * Override the {@link android.app.role.RoleManager} call screening app with another value.
+     * Used for testing purposes only.
+     * @param packageName Package name of the app to fill the call screening role.  Where
+     *                    {@code null}, the override is removed.
+     */
+    void setTestDefaultCallScreeningApp(String packageName);
+
+    /**
+     * @return List of package names of companion apps, or empty list if there are none.
+     */
+    List<String> getCallCompanionApps();
+
+    /**
+     * Set a package to be added to the list of the companion apps. Used for testing purposes only.
+     * @param packageName Package name of the app to be added or removed as an override call
+     *                    companion app.
+     * @param isAdded {@code true} if the specified package should be added, {@code false} if it
+     *                            should be removed.
+     */
+    void addOrRemoveTestCallCompanionApp(String packageName, boolean isAdded);
+
+    /**
+     * @return Package name of the car more app or {@code null} if there are no apps that match.
+     */
+    String getCarModeDialerApp();
+
+    /**
+     * Override the automotive app with another value. Used for testing purposes only.
+     * @param packageName Package name of the automotive app. Where
+     *                    {@code null}, the override is removed.
+     */
+    void setTestAutoModeApp(String packageName);
+
+    /**
+     * Using role manager needs to know the current user handle.  Need to make sure the role manager
+     * adapter can pass this to role manager.  As it changes, we'll pass it in.
+     * @param currentUserHandle The new user handle.
+     */
+    void setCurrentUserHandle(UserHandle currentUserHandle);
+
+    /**
+     * Returns the application label that corresponds to the given package name.
+     * @param packageName A valid package name.
+     * @return Application label for the given package name, or null if not found.
+     */
+    String getApplicationLabelForPackageName(String packageName);
+}
diff --git a/src/com/android/server/telecom/RoleManagerAdapterImpl.java b/src/com/android/server/telecom/RoleManagerAdapterImpl.java
new file mode 100644
index 0000000..0b64959
--- /dev/null
+++ b/src/com/android/server/telecom/RoleManagerAdapterImpl.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2018 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.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.telecom.Log;
+
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class RoleManagerAdapterImpl implements RoleManagerAdapter {
+    private static final String ROLE_CALL_REDIRECTION_APP = "android.app.role.PROXY_CALLING_APP";
+    private static final String ROLE_CAR_MODE_DIALER = "android.app.role.CAR_MODE_DIALER_APP";
+    private static final String ROLE_CALL_SCREENING = "android.app.role.CALL_SCREENING_APP";
+    private static final String ROLE_CALL_COMPANION_APP =
+            "android.app.role.CALL_COMPANION_APP";
+
+    private String mOverrideDefaultCallRedirectionApp = null;
+    private String mOverrideDefaultCallScreeningApp = null;
+    private String mOverrideDefaultCarModeApp = null;
+    private List<String> mOverrideCallCompanionApps = new ArrayList<>();
+    private Context mContext;
+    private UserHandle mCurrentUserHandle;
+
+    public RoleManagerAdapterImpl(Context context) {
+        mContext = context;
+    }
+
+    @Override
+    public String getDefaultCallRedirectionApp() {
+        if (mOverrideDefaultCallRedirectionApp != null) {
+            return mOverrideDefaultCallRedirectionApp;
+        }
+        return getRoleManagerCallRedirectionApp();
+    }
+
+    @Override
+    public void setTestDefaultCallRedirectionApp(String packageName) {
+        mOverrideDefaultCallRedirectionApp = packageName;
+    }
+
+    @Override
+    public String getDefaultCallScreeningApp() {
+        if (mOverrideDefaultCallScreeningApp != null) {
+            return mOverrideDefaultCallScreeningApp;
+        }
+        return getRoleManagerCallScreeningApp();
+    }
+
+    @Override
+    public void setTestDefaultCallScreeningApp(String packageName) {
+        mOverrideDefaultCallScreeningApp = packageName;
+    }
+
+    @Override
+    public List<String> getCallCompanionApps() {
+        List<String> callCompanionApps = new ArrayList<>();
+        // List from RoleManager is not resizable. AbstractList.add action is not supported.
+        callCompanionApps.addAll(getRoleManagerCallCompanionApps());
+        callCompanionApps.addAll(mOverrideCallCompanionApps);
+        return callCompanionApps;
+    }
+
+    @Override
+    public void addOrRemoveTestCallCompanionApp(String packageName, boolean isAdded) {
+        if (isAdded) {
+            mOverrideCallCompanionApps.add(packageName);
+        } else {
+            mOverrideCallCompanionApps.remove(packageName);
+        }
+    }
+
+    @Override
+    public String getCarModeDialerApp() {
+        if (mOverrideDefaultCarModeApp != null) {
+            return mOverrideDefaultCarModeApp;
+        }
+        return getRoleManagerCarModeDialerApp();
+    }
+
+    @Override
+    public void setTestAutoModeApp(String packageName) {
+        mOverrideDefaultCarModeApp = packageName;
+    }
+
+    @Override
+    public void setCurrentUserHandle(UserHandle currentUserHandle) {
+        mCurrentUserHandle = currentUserHandle;
+    }
+
+    private String getRoleManagerCallScreeningApp() {
+        // TODO: Link in RoleManager
+        return null;
+    }
+
+    private String getRoleManagerCarModeDialerApp() {
+        // TODO: Link in RoleManager
+        return null;
+    }
+
+    private List<String> getRoleManagerCallCompanionApps() {
+        // TODO: Link in RoleManager
+        return Collections.emptyList();
+    }
+
+    private String getRoleManagerCallRedirectionApp() {
+        // TODO: Link in RoleManager
+        return null;
+    }
+
+    /**
+     * Returns the application label that corresponds to the given package name
+     *
+     * @param packageName A valid package name.
+     *
+     * @return Application label for the given package name, or null if not found.
+     */
+    @Override
+    public String getApplicationLabelForPackageName(String packageName) {
+        PackageManager pm = mContext.getPackageManager();
+        ApplicationInfo info = null;
+        try {
+            info = pm.getApplicationInfo(packageName, 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.d(this, "Application info not found for packageName " + packageName);
+        }
+        if (info == null) {
+            return packageName;
+        } else {
+            return info.loadLabel(pm).toString();
+        }
+    }
+
+    /**
+     * Dumps the state of the {@link InCallController}.
+     *
+     * @param pw The {@code IndentingPrintWriter} to write the state to.
+     */
+    public void dump(IndentingPrintWriter pw) {
+        pw.print("DefaultCallRedirectionApp: ");
+        if (mOverrideDefaultCallRedirectionApp != null) {
+            pw.print("(override ");
+            pw.print(mOverrideDefaultCallRedirectionApp);
+            pw.print(") ");
+            pw.print(getRoleManagerCallRedirectionApp());
+        }
+        pw.println();
+
+        pw.print("DefaultCallScreeningApp: ");
+        if (mOverrideDefaultCallScreeningApp != null) {
+            pw.print("(override ");
+            pw.print(mOverrideDefaultCallScreeningApp);
+            pw.print(") ");
+            pw.print(getRoleManagerCallScreeningApp());
+        }
+        pw.println();
+
+        pw.print("DefaultCarModeDialerApp: ");
+        if (mOverrideDefaultCarModeApp != null) {
+            pw.print("(override ");
+            pw.print(mOverrideDefaultCarModeApp);
+            pw.print(") ");
+            pw.print(getRoleManagerCarModeDialerApp());
+        }
+        pw.println();
+
+        pw.print("DefaultCallCompanionApps: ");
+        if (mOverrideCallCompanionApps != null) {
+            pw.print("(override ");
+            pw.print(mOverrideCallCompanionApps.stream().collect(Collectors.joining(", ")));
+            pw.print(") ");
+            List<String> appsInRole = getRoleManagerCallCompanionApps();
+            if (appsInRole != null) {
+                pw.print(appsInRole.stream().collect(Collectors.joining(", ")));
+            }
+        }
+        pw.println();
+    }
+}
diff --git a/src/com/android/server/telecom/ServiceBinder.java b/src/com/android/server/telecom/ServiceBinder.java
index f15570b..a322a5e 100644
--- a/src/com/android/server/telecom/ServiceBinder.java
+++ b/src/com/android/server/telecom/ServiceBinder.java
@@ -39,7 +39,7 @@
  * Subclasses supply the service intent and component name and this class will invoke protected
  * methods when the class is bound, unbound, or upon failure.
  */
-abstract class ServiceBinder {
+public abstract class ServiceBinder {
 
     /**
      * Callback to notify after a binding succeeds or fails.
@@ -73,13 +73,15 @@
             // Reset any abort request if we're asked to bind again.
             clearAbort();
 
-            if (!mCallbacks.isEmpty()) {
-                // Binding already in progress, append to the list of callbacks and bail out.
+            synchronized (mCallbacks) {
+                if (!mCallbacks.isEmpty()) {
+                    // Binding already in progress, append to the list of callbacks and bail out.
+                    mCallbacks.add(callback);
+                    return;
+                }
                 mCallbacks.add(callback);
-                return;
             }
 
-            mCallbacks.add(callback);
             if (mServiceConnection == null) {
                 Intent serviceIntent = new Intent(mServiceAction).setComponent(mComponentName);
                 ServiceConnection connection = new ServiceBinderConnection(call);
@@ -351,10 +353,16 @@
      * outstanding callbacks is cleared afterwards.
      */
     private void handleSuccessfulConnection() {
-        for (BindCallback callback : mCallbacks) {
+        // Make a copy so that we don't have a deadlock inside one of the callbacks.
+        Set<BindCallback> callbacksCopy = new ArraySet<>();
+        synchronized (mCallbacks) {
+            callbacksCopy.addAll(mCallbacks);
+            mCallbacks.clear();
+        }
+
+        for (BindCallback callback : callbacksCopy) {
             callback.onSuccess();
         }
-        mCallbacks.clear();
     }
 
     /**
@@ -362,10 +370,16 @@
      * outstanding callbacks is cleared afterwards.
      */
     private void handleFailedConnection() {
-        for (BindCallback callback : mCallbacks) {
+        // Make a copy so that we don't have a deadlock inside one of the callbacks.
+        Set<BindCallback> callbacksCopy = new ArraySet<>();
+        synchronized (mCallbacks) {
+            callbacksCopy.addAll(mCallbacks);
+            mCallbacks.clear();
+        }
+
+        for (BindCallback callback : callbacksCopy) {
             callback.onFailure();
         }
-        mCallbacks.clear();
     }
 
     /**
diff --git a/src/com/android/server/telecom/SystemSettingsUtil.java b/src/com/android/server/telecom/SystemSettingsUtil.java
index 3c75e4d..97659a8 100644
--- a/src/com/android/server/telecom/SystemSettingsUtil.java
+++ b/src/com/android/server/telecom/SystemSettingsUtil.java
@@ -36,4 +36,14 @@
         return Settings.System.getInt(context.getContentResolver(),
                 Settings.System.VIBRATE_WHEN_RINGING, 0) != 0;
     }
+
+    public boolean isEnhancedCallBlockingEnabled(Context context) {
+        return Settings.System.getInt(context.getContentResolver(),
+                Settings.System.DEBUG_ENABLE_ENHANCED_CALL_BLOCKING, 0) != 0;
+    }
+
+    public boolean setEnhancedCallBlockingEnabled(Context context, boolean enabled) {
+        return Settings.System.putInt(context.getContentResolver(),
+                Settings.System.DEBUG_ENABLE_ENHANCED_CALL_BLOCKING, enabled ? 1 : 0);
+    }
 }
diff --git a/src/com/android/server/telecom/SystemStateHelper.java b/src/com/android/server/telecom/SystemStateHelper.java
new file mode 100644
index 0000000..69a46c6
--- /dev/null
+++ b/src/com/android/server/telecom/SystemStateHelper.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2015 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.app.UiModeManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.telecom.Log;
+
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Provides various system states to the rest of the telecom codebase.
+ */
+public class SystemStateHelper {
+    public static interface SystemStateListener {
+        public void onCarModeChanged(boolean isCarMode);
+    }
+
+    private final Context mContext;
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Log.startSession("SSP.oR");
+            try {
+                String action = intent.getAction();
+                if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(action)) {
+                    onEnterCarMode();
+                } else if (UiModeManager.ACTION_EXIT_CAR_MODE.equals(action)) {
+                    onExitCarMode();
+                } else {
+                    Log.w(this, "Unexpected intent received: %s", intent.getAction());
+                }
+            } finally {
+                Log.endSession();
+            }
+        }
+    };
+
+    private Set<SystemStateListener> mListeners = new CopyOnWriteArraySet<>();
+    private boolean mIsCarMode;
+
+    public SystemStateHelper(Context context) {
+        mContext = context;
+
+        IntentFilter intentFilter = new IntentFilter(UiModeManager.ACTION_ENTER_CAR_MODE);
+        intentFilter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
+        mContext.registerReceiver(mBroadcastReceiver, intentFilter);
+        Log.i(this, "Registering car mode receiver: %s", intentFilter);
+
+        mIsCarMode = getSystemCarMode();
+    }
+
+    public void addListener(SystemStateListener listener) {
+        if (listener != null) {
+            mListeners.add(listener);
+        }
+    }
+
+    public boolean removeListener(SystemStateListener listener) {
+        return mListeners.remove(listener);
+    }
+
+    public boolean isCarMode() {
+        return mIsCarMode;
+    }
+
+    public boolean isDeviceAtEar() {
+        return isDeviceAtEar(mContext);
+    }
+
+    /**
+     * Returns a guess whether the phone is up to the user's ear. Use the proximity sensor and
+     * the gravity sensor to make a guess
+     * @return true if the proximity sensor is activated, the magnitude of gravity in directions
+     *         parallel to the screen is greater than some configurable threshold, and the
+     *         y-component of gravity isn't less than some other configurable threshold.
+     */
+    public static boolean isDeviceAtEar(Context context) {
+        SensorManager sm = context.getSystemService(SensorManager.class);
+        if (sm == null) {
+            return false;
+        }
+        Sensor grav = sm.getDefaultSensor(Sensor.TYPE_GRAVITY);
+        Sensor proximity = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY);
+        if (grav == null || proximity == null) {
+            return false;
+        }
+
+        AtomicBoolean result = new AtomicBoolean(true);
+        CountDownLatch gravLatch = new CountDownLatch(1);
+        CountDownLatch proxLatch = new CountDownLatch(1);
+
+        final double xyGravityThreshold = context.getResources().getFloat(
+                R.dimen.device_on_ear_xy_gravity_threshold);
+        final double yGravityNegativeThreshold = context.getResources().getFloat(
+                R.dimen.device_on_ear_y_gravity_negative_threshold);
+
+        SensorEventListener listener = new SensorEventListener() {
+            @Override
+            public void onSensorChanged(SensorEvent event) {
+                if (event.sensor.getType() == Sensor.TYPE_GRAVITY) {
+                    if (gravLatch.getCount() == 0) {
+                        return;
+                    }
+                    double xyMag = Math.sqrt(event.values[0] * event.values[0]
+                            + event.values[1] * event.values[1]);
+                    if (xyMag < xyGravityThreshold
+                            || event.values[1] < yGravityNegativeThreshold) {
+                        result.set(false);
+                    }
+                    gravLatch.countDown();
+                } else if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) {
+                    if (proxLatch.getCount() == 0) {
+                        return;
+                    }
+                    if (event.values[0] >= proximity.getMaximumRange()) {
+                        result.set(false);
+                    }
+                    proxLatch.countDown();
+                }
+            }
+
+            @Override
+            public void onAccuracyChanged(Sensor sensor, int accuracy) {
+            }
+        };
+
+        try {
+            sm.registerListener(listener, grav, SensorManager.SENSOR_DELAY_FASTEST);
+            sm.registerListener(listener, proximity, SensorManager.SENSOR_DELAY_FASTEST);
+            boolean accelValid = gravLatch.await(100, TimeUnit.MILLISECONDS);
+            boolean proxValid = proxLatch.await(100, TimeUnit.MILLISECONDS);
+            if (accelValid && proxValid) {
+                return result.get();
+            } else {
+                Log.w(SystemStateHelper.class.getSimpleName(),
+                        "Timed out waiting for sensors: %b %b", accelValid, proxValid);
+                return false;
+            }
+        } catch (InterruptedException e) {
+            return false;
+        } finally {
+            sm.unregisterListener(listener);
+        }
+    }
+
+    private void onEnterCarMode() {
+        if (!mIsCarMode) {
+            Log.i(this, "Entering carmode");
+            mIsCarMode = true;
+            notifyCarMode();
+        }
+    }
+
+    private void onExitCarMode() {
+        if (mIsCarMode) {
+            Log.i(this, "Exiting carmode");
+            mIsCarMode = false;
+            notifyCarMode();
+        }
+    }
+
+    private void notifyCarMode() {
+        for (SystemStateListener listener : mListeners) {
+            listener.onCarModeChanged(mIsCarMode);
+        }
+    }
+
+    /**
+     * Checks the system for the current car mode.
+     *
+     * @return True if in car mode, false otherwise.
+     */
+    private boolean getSystemCarMode() {
+        UiModeManager uiModeManager =
+                (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
+
+        if (uiModeManager != null) {
+            return uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR;
+        }
+
+        return false;
+    }
+}
diff --git a/src/com/android/server/telecom/SystemStateProvider.java b/src/com/android/server/telecom/SystemStateProvider.java
deleted file mode 100644
index e1938b1..0000000
--- a/src/com/android/server/telecom/SystemStateProvider.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2015 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.app.UiModeManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Configuration;
-import android.telecom.Log;
-
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArraySet;
-
-/**
- * Provides various system states to the rest of the telecom codebase. So far, that's only car-mode.
- */
-public class SystemStateProvider {
-
-    public static interface SystemStateListener {
-        public void onCarModeChanged(boolean isCarMode);
-    }
-
-    private final Context mContext;
-    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            Log.startSession("SSP.oR");
-            try {
-                String action = intent.getAction();
-                if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(action)) {
-                    onEnterCarMode();
-                } else if (UiModeManager.ACTION_EXIT_CAR_MODE.equals(action)) {
-                    onExitCarMode();
-                } else {
-                    Log.w(this, "Unexpected intent received: %s", intent.getAction());
-                }
-            } finally {
-                Log.endSession();
-            }
-        }
-    };
-
-    private Set<SystemStateListener> mListeners = new CopyOnWriteArraySet<>();
-    private boolean mIsCarMode;
-
-    public SystemStateProvider(Context context) {
-        mContext = context;
-
-        IntentFilter intentFilter = new IntentFilter(UiModeManager.ACTION_ENTER_CAR_MODE);
-        intentFilter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
-        mContext.registerReceiver(mBroadcastReceiver, intentFilter);
-        Log.i(this, "Registering car mode receiver: %s", intentFilter);
-
-        mIsCarMode = getSystemCarMode();
-    }
-
-    public void addListener(SystemStateListener listener) {
-        if (listener != null) {
-            mListeners.add(listener);
-        }
-    }
-
-    public boolean removeListener(SystemStateListener listener) {
-        return mListeners.remove(listener);
-    }
-
-    public boolean isCarMode() {
-        return mIsCarMode;
-    }
-
-    private void onEnterCarMode() {
-        if (!mIsCarMode) {
-            Log.i(this, "Entering carmode");
-            mIsCarMode = true;
-            notifyCarMode();
-        }
-    }
-
-    private void onExitCarMode() {
-        if (mIsCarMode) {
-            Log.i(this, "Exiting carmode");
-            mIsCarMode = false;
-            notifyCarMode();
-        }
-    }
-
-    private void notifyCarMode() {
-        for (SystemStateListener listener : mListeners) {
-            listener.onCarModeChanged(mIsCarMode);
-        }
-    }
-
-    /**
-     * Checks the system for the current car mode.
-     *
-     * @return True if in car mode, false otherwise.
-     */
-    private boolean getSystemCarMode() {
-        UiModeManager uiModeManager =
-                (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
-
-        if (uiModeManager != null) {
-            return uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR;
-        }
-
-        return false;
-    }
-}
diff --git a/src/com/android/server/telecom/TelecomBroadcastIntentProcessor.java b/src/com/android/server/telecom/TelecomBroadcastIntentProcessor.java
index a51ef73..ca44cd4 100644
--- a/src/com/android/server/telecom/TelecomBroadcastIntentProcessor.java
+++ b/src/com/android/server/telecom/TelecomBroadcastIntentProcessor.java
@@ -21,6 +21,7 @@
 import android.os.UserHandle;
 import android.telecom.Log;
 
+import com.android.server.telecom.ui.CallRedirectionConfirmDialogActivity;
 import com.android.server.telecom.ui.ConfirmCallDialogActivity;
 
 public final class TelecomBroadcastIntentProcessor {
@@ -64,6 +65,27 @@
     public static final String ACTION_CANCEL_CALL =
             "com.android.server.telecom.CANCEL_CALL";
 
+    /**
+     * The action used to proceed with a redirected call being confirmed via
+     * {@link com.android.server.telecom.ui.CallRedirectionConfirmDialogActivity}.
+     */
+    public static final String ACTION_PLACE_REDIRECTED_CALL =
+            "com.android.server.telecom.PROCEED_WITH_REDIRECTED_CALL";
+
+    /**
+     * The action used to confirm to proceed the call without redirection via
+     * {@link com.android.server.telecom.ui.CallRedirectionConfirmDialogActivity}.
+     */
+    public static final String ACTION_PLACE_UNREDIRECTED_CALL =
+            "com.android.server.telecom.PROCEED_WITH_UNREDIRECTED_CALL";
+
+    /**
+     * The action used to cancel a redirected call being confirmed via
+     * {@link com.android.server.telecom.ui.CallRedirectionConfirmDialogActivity}.
+     */
+    public static final String ACTION_CANCEL_REDIRECTED_CALL =
+            "com.android.server.telecom.CANCEL_REDIRECTED_CALL";
+
     public static final String EXTRA_USERHANDLE = "userhandle";
 
     private final Context mContext;
@@ -155,6 +177,36 @@
             } finally {
                 Log.endSession();
             }
+        } else if (ACTION_PLACE_REDIRECTED_CALL.equals(action)) {
+            Log.startSession("TBIP.aPRC");
+            try {
+                mCallsManager.processRedirectedOutgoingCallAfterUserInteraction(
+                        intent.getStringExtra(CallRedirectionConfirmDialogActivity
+                                .EXTRA_REDIRECTION_OUTGOING_CALL_ID),
+                        ACTION_PLACE_REDIRECTED_CALL);
+            } finally {
+                Log.endSession();
+            }
+        } else if (ACTION_PLACE_UNREDIRECTED_CALL.equals(action)) {
+            Log.startSession("TBIP.aPUC");
+            try {
+                mCallsManager.processRedirectedOutgoingCallAfterUserInteraction(
+                        intent.getStringExtra(CallRedirectionConfirmDialogActivity
+                                .EXTRA_REDIRECTION_OUTGOING_CALL_ID),
+                        ACTION_PLACE_UNREDIRECTED_CALL);
+            } finally {
+                Log.endSession();
+            }
+        } else if (ACTION_CANCEL_REDIRECTED_CALL.equals(action)) {
+            Log.startSession("TBIP.aCRC");
+            try {
+                mCallsManager.processRedirectedOutgoingCallAfterUserInteraction(
+                        intent.getStringExtra(CallRedirectionConfirmDialogActivity
+                                .EXTRA_REDIRECTION_OUTGOING_CALL_ID),
+                        ACTION_CANCEL_REDIRECTED_CALL);
+            } finally {
+                Log.endSession();
+            }
         }
     }
 
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index ea55e63..f472421 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -29,16 +29,22 @@
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
 import android.content.res.Resources;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Process;
 import android.os.UserHandle;
+import android.provider.Settings;
+import android.telecom.CallScreeningService;
 import android.telecom.Log;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
@@ -78,8 +84,29 @@
         }
     }
 
+    public interface SettingsSecureAdapter {
+        void putStringForUser(ContentResolver resolver, String name, String value, int userHandle);
+
+        String getStringForUser(ContentResolver resolver, String name, int userHandle);
+    }
+
+    static class SettingsSecureAdapterImpl implements SettingsSecureAdapter {
+        @Override
+        public void putStringForUser(ContentResolver resolver, String name, String value,
+            int userHandle) {
+            Settings.Secure.putStringForUser(resolver, name, value, userHandle);
+        }
+
+        @Override
+        public String getStringForUser(ContentResolver resolver, String name, int userHandle) {
+            return Settings.Secure.getStringForUser(resolver, name, userHandle);
+        }
+    }
+
     private static final String TIME_LINE_ARG = "timeline";
     private static final int DEFAULT_VIDEO_STATE = -1;
+    private static final String PERMISSION_HANDLE_CALL_INTENT =
+            "android.permission.HANDLE_CALL_INTENT";
 
     private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub() {
         @Override
@@ -110,10 +137,14 @@
         }
 
         @Override
-        public PhoneAccountHandle getUserSelectedOutgoingPhoneAccount() {
+        public PhoneAccountHandle getUserSelectedOutgoingPhoneAccount(String callingPackage) {
             synchronized (mLock) {
                 try {
                     Log.startSession("TSI.gUSOPA");
+                    if (!isDialerOrPrivileged(callingPackage, "getDefaultOutgoingPhoneAccount")) {
+                        throw new SecurityException("Only the default dialer, or caller with "
+                                + "READ_PRIVILEGED_PHONE_STATE can call this method.");
+                    }
                     final UserHandle callingUserHandle = Binder.getCallingUserHandle();
                     return mPhoneAccountRegistrar.getUserSelectedOutgoingPhoneAccount(
                             callingUserHandle);
@@ -440,6 +471,11 @@
                         if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
                             enforceRegisterMultiUser();
                         }
+                        Bundle extras = account.getExtras();
+                        if (extras != null
+                                && extras.getBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING)) {
+                            enforceRegisterSkipCallFiltering();
+                        }
                         enforceUserHandleMatchesCaller(account.getAccountHandle());
                         final long token = Binder.clearCallingIdentity();
                         try {
@@ -1445,6 +1481,158 @@
                 Log.endSession();
             }
         }
+
+        /**
+         * See {@link TelecomManager#isInEmergencyCall()}
+         */
+        @Override
+        public boolean isInEmergencyCall() {
+            try {
+                Log.startSession("TSI.iIEC");
+                enforceModifyPermission();
+                synchronized (mLock) {
+                    long token = Binder.clearCallingIdentity();
+                    try {
+                        boolean isInEmergencyCall = mCallsManager.isInEmergencyCall();
+                        Log.i(this, "isInEmergencyCall: %b", isInEmergencyCall);
+                        return isInEmergencyCall;
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        /**
+         * See {@link TelecomManager#handleCallIntent(Intent)} ()}
+         */
+        @Override
+        public void handleCallIntent(Intent intent) {
+            try {
+                Log.startSession("TSI.hCI");
+                synchronized (mLock) {
+                    mContext.enforceCallingOrSelfPermission(PERMISSION_HANDLE_CALL_INTENT,
+                            "handleCallIntent is for internal use only.");
+
+                    long token = Binder.clearCallingIdentity();
+                    try {
+                        Log.i(this, "handleCallIntent: handling call intent");
+                        mCallIntentProcessorAdapter.processOutgoingCallIntent(mContext,
+                                mCallsManager, intent, null /* callingPackage */);
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
+        public void setTestDefaultCallRedirectionApp(String packageName) {
+            try {
+                Log.startSession("TSI.sTDCRA");
+                enforceModifyPermission();
+                if (!Build.IS_USERDEBUG) {
+                    throw new SecurityException("Test-only API.");
+                }
+                synchronized (mLock) {
+                    long token = Binder.clearCallingIdentity();
+                    try {
+                        mCallsManager.getRoleManagerAdapter().setTestDefaultCallRedirectionApp(
+                                packageName);
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
+        public void setTestDefaultCallScreeningApp(String packageName) {
+            try {
+                Log.startSession("TSI.sTDCSA");
+                enforceModifyPermission();
+                if (!Build.IS_USERDEBUG) {
+                    throw new SecurityException("Test-only API.");
+                }
+                synchronized (mLock) {
+                    long token = Binder.clearCallingIdentity();
+                    try {
+                        mCallsManager.getRoleManagerAdapter().setTestDefaultCallScreeningApp(
+                                packageName);
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
+        public void addOrRemoveTestCallCompanionApp(String packageName, boolean isAdded) {
+            try {
+                Log.startSession("TSI.aORTCCA");
+                enforceModifyPermission();
+                if (!Build.IS_USERDEBUG) {
+                    throw new SecurityException("Test-only API.");
+                }
+                synchronized (mLock) {
+                    long token = Binder.clearCallingIdentity();
+                    try {
+                        mCallsManager.getRoleManagerAdapter().addOrRemoveTestCallCompanionApp(
+                                packageName, isAdded);
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
+        public void setTestAutoModeApp(String packageName) {
+            try {
+                Log.startSession("TSI.sTAMA");
+                enforceModifyPermission();
+                if (!Build.IS_USERDEBUG) {
+                    throw new SecurityException("Test-only API.");
+                }
+                synchronized (mLock) {
+                    long token = Binder.clearCallingIdentity();
+                    try {
+                        mCallsManager.getRoleManagerAdapter().setTestAutoModeApp(packageName);
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
+        public void setTestPhoneAcctSuggestionComponent(String flattenedComponentName) {
+            try {
+                Log.startSession("TSI.sPASA");
+                enforceModifyPermission();
+                if (Binder.getCallingUid() != Process.SHELL_UID
+                        && Binder.getCallingUid() != Process.ROOT_UID) {
+                    throw new SecurityException("Shell-only API.");
+                }
+                synchronized (mLock) {
+                    PhoneAccountSuggestionHelper.setOverrideServiceName(flattenedComponentName);
+                }
+            } finally {
+                Log.endSession();
+            }
+        }
     };
 
     /**
@@ -1495,6 +1683,7 @@
     private final UserCallIntentProcessorFactory mUserCallIntentProcessorFactory;
     private final DefaultDialerCache mDefaultDialerCache;
     private final SubscriptionManagerAdapter mSubscriptionManagerAdapter;
+    private final SettingsSecureAdapter mSettingsSecureAdapter;
     private final TelecomSystem.SyncRoot mLock;
 
     public TelecomServiceImpl(
@@ -1505,6 +1694,7 @@
             UserCallIntentProcessorFactory userCallIntentProcessorFactory,
             DefaultDialerCache defaultDialerCache,
             SubscriptionManagerAdapter subscriptionManagerAdapter,
+            SettingsSecureAdapter settingsSecureAdapter,
             TelecomSystem.SyncRoot lock) {
         mContext = context;
         mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
@@ -1518,6 +1708,7 @@
         mDefaultDialerCache = defaultDialerCache;
         mCallIntentProcessorAdapter = callIntentProcessorAdapter;
         mSubscriptionManagerAdapter = subscriptionManagerAdapter;
+        mSettingsSecureAdapter = settingsSecureAdapter;
     }
 
     public ITelecomService.Stub getBinder() {
@@ -1671,6 +1862,13 @@
         }
     }
 
+    private void enforceRegisterSkipCallFiltering() {
+        if (!isCallerSystemApp()) {
+            throw new SecurityException(
+                "EXTRA_SKIP_CALL_FILTERING is only available to system apps.");
+        }
+    }
+
     private void enforceUserHandleMatchesCaller(PhoneAccountHandle accountHandle) {
         if (!Binder.getCallingUserHandle().equals(accountHandle.getUserHandle())) {
             throw new SecurityException("Calling UserHandle does not match PhoneAccountHandle's");
@@ -1715,6 +1913,19 @@
         }
     }
 
+    private boolean isDialerOrPrivileged(String callingPackage, String message) {
+        // The system/default dialer can always read phone state - so that emergency calls will
+        // still work.
+        if (isPrivilegedDialerCalling(callingPackage)) {
+            return true;
+        }
+
+        mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, message);
+        // SKIP checking run-time OP_READ_PHONE_STATE since caller or self has PRIVILEGED
+        // permission
+        return true;
+    }
+
     private boolean isSelfManagedConnectionService(PhoneAccountHandle phoneAccountHandle) {
         if (phoneAccountHandle != null) {
                 PhoneAccount phoneAccount = mPhoneAccountRegistrar.getPhoneAccountUnchecked(
@@ -1787,4 +1998,24 @@
         // If only TX or RX were set (or neither), the video state is valid.
         return remainingState == 0;
     }
+
+    private void broadcastCallScreeningAppChangedIntent(String componentName,
+        boolean isDefault) {
+        if (TextUtils.isEmpty(componentName)) {
+            return;
+        }
+
+        ComponentName broadcastComponentName = ComponentName.unflattenFromString(componentName);
+
+        if (broadcastComponentName != null) {
+            Intent intent = new Intent(TelecomManager
+                .ACTION_DEFAULT_CALL_SCREENING_APP_CHANGED);
+            intent.putExtra(TelecomManager
+                .EXTRA_IS_DEFAULT_CALL_SCREENING_APP, isDefault);
+            intent.putExtra(TelecomManager
+                .EXTRA_DEFAULT_CALL_SCREENING_APP_COMPONENT_NAME, componentName);
+            intent.setPackage(broadcastComponentName.getPackageName());
+            mContext.sendBroadcast(intent);
+        }
+    }
 }
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index 3fd0e21..aae2dea 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -35,10 +35,15 @@
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.location.Country;
+import android.location.CountryDetector;
 import android.net.Uri;
+import android.os.Process;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.telecom.Log;
 import android.telecom.PhoneAccountHandle;
+import android.telephony.PhoneNumberUtils;
 
 import java.io.FileNotFoundException;
 import java.io.InputStream;
@@ -96,6 +101,8 @@
                 .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_DEBUG_OFF, null);
         DIALER_SECRET_CODE_FILTER
                 .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_MARK, null);
+        DIALER_SECRET_CODE_FILTER
+                .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_MENU, null);
     }
 
     private static TelecomSystem INSTANCE = null;
@@ -193,7 +200,9 @@
             PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
             IncomingCallNotifier incomingCallNotifier,
             InCallTonePlayer.ToneGeneratorFactory toneGeneratorFactory,
-            ClockProxy clockProxy) {
+            CallAudioRouteStateMachine.Factory callAudioRouteStateMachineFactory,
+            ClockProxy clockProxy,
+            RoleManagerAdapter roleManagerAdapter) {
         mContext = context.getApplicationContext();
         LogUtils.initLogging(mContext);
         DefaultDialerManagerAdapter defaultDialerAdapter =
@@ -227,7 +236,7 @@
                     }
                 });
         BluetoothDeviceManager bluetoothDeviceManager = new BluetoothDeviceManager(mContext,
-                new BluetoothAdapterProxy(), mLock);
+                new BluetoothAdapterProxy());
         BluetoothRouteManager bluetoothRouteManager = new BluetoothRouteManager(mContext, mLock,
                 bluetoothDeviceManager, new Timeouts.Adapter());
         BluetoothStateReceiver bluetoothStateReceiver = new BluetoothStateReceiver(
@@ -235,18 +244,22 @@
         mContext.registerReceiver(bluetoothStateReceiver, BluetoothStateReceiver.INTENT_FILTER);
 
         WiredHeadsetManager wiredHeadsetManager = new WiredHeadsetManager(mContext);
-        SystemStateProvider systemStateProvider = new SystemStateProvider(mContext);
+        SystemStateHelper systemStateHelper = new SystemStateHelper(mContext);
 
         mMissedCallNotifier = missedCallNotifierImplFactory
                 .makeMissedCallNotifierImpl(mContext, mPhoneAccountRegistrar, defaultDialerCache);
 
+        CallerInfoLookupHelper callerInfoLookupHelper =
+                new CallerInfoLookupHelper(context, callerInfoAsyncQueryFactory,
+                        mContactsAsyncHelper, mLock);
+
         EmergencyCallHelper emergencyCallHelper = new EmergencyCallHelper(mContext,
                 mContext.getResources().getString(R.string.ui_default_package), timeoutsAdapter);
 
         InCallControllerFactory inCallControllerFactory = new InCallControllerFactory() {
             @Override
             public InCallController create(Context context, SyncRoot lock,
-                    CallsManager callsManager, SystemStateProvider systemStateProvider,
+                    CallsManager callsManager, SystemStateHelper systemStateProvider,
                     DefaultDialerCache defaultDialerCache, Timeouts.Adapter timeoutsAdapter,
                     EmergencyCallHelper emergencyCallHelper) {
                 return new InCallController(context, lock, callsManager, systemStateProvider,
@@ -257,8 +270,7 @@
         mCallsManager = new CallsManager(
                 mContext,
                 mLock,
-                mContactsAsyncHelper,
-                callerInfoAsyncQueryFactory,
+                callerInfoLookupHelper,
                 mMissedCallNotifier,
                 mPhoneAccountRegistrar,
                 headsetMediaButtonFactory,
@@ -268,7 +280,7 @@
                 audioServiceFactory,
                 bluetoothRouteManager,
                 wiredHeadsetManager,
-                systemStateProvider,
+                systemStateHelper,
                 defaultDialerCache,
                 timeoutsAdapter,
                 asyncRingtonePlayer,
@@ -277,7 +289,10 @@
                 toneGeneratorFactory,
                 clockProxy,
                 bluetoothStateReceiver,
-                inCallControllerFactory);
+                callAudioRouteStateMachineFactory,
+                new CallAudioModeStateMachine.Factory(),
+                inCallControllerFactory,
+                roleManagerAdapter);
 
         mIncomingCallNotifier = incomingCallNotifier;
         incomingCallNotifier.setCallsManagerProxy(new IncomingCallNotifier.CallsManagerProxy() {
@@ -316,6 +331,8 @@
         mContext.registerReceiver(mDialerCodeReceiver, DIALER_SECRET_CODE_FILTER,
                 Manifest.permission.CONTROL_INCALL_EXPERIENCE, null);
 
+        // There is no USER_SWITCHED broadcast for user 0, handle it here explicitly.
+        final UserManager userManager = UserManager.get(mContext);
         mTelecomServiceImpl = new TelecomServiceImpl(
                 mContext, mCallsManager, mPhoneAccountRegistrar,
                 new CallIntentProcessor.AdapterImpl(),
@@ -327,6 +344,7 @@
                 },
                 defaultDialerCache,
                 new TelecomServiceImpl.SubscriptionManagerAdapterImpl(),
+                new TelecomServiceImpl.SettingsSecureAdapterImpl(),
                 mLock);
         Log.endSession();
     }
diff --git a/src/com/android/server/telecom/TelephonyUtil.java b/src/com/android/server/telecom/TelephonyUtil.java
index a76821a..b8fe9ab 100644
--- a/src/com/android/server/telecom/TelephonyUtil.java
+++ b/src/com/android/server/telecom/TelephonyUtil.java
@@ -70,8 +70,9 @@
     }
 
     public static boolean shouldProcessAsEmergency(Context context, Uri handle) {
-        return handle != null && PhoneNumberUtils.isLocalEmergencyNumber(
-                context, handle.getSchemeSpecificPart());
+        TelephonyManager tm = (TelephonyManager) context.getSystemService(
+                Context.TELEPHONY_SERVICE);
+        return handle != null && tm.isEmergencyNumber(handle.getSchemeSpecificPart());
     }
 
     public static void sortSimPhoneAccounts(Context context, List<PhoneAccount> accounts) {
diff --git a/src/com/android/server/telecom/Timeouts.java b/src/com/android/server/telecom/Timeouts.java
index 5187641..37f9363 100644
--- a/src/com/android/server/telecom/Timeouts.java
+++ b/src/com/android/server/telecom/Timeouts.java
@@ -18,6 +18,7 @@
 
 import android.content.ContentResolver;
 import android.provider.Settings;
+import android.telecom.CallRedirectionService;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -49,6 +50,18 @@
         public long getEmergencyCallbackWindowMillis(ContentResolver cr) {
             return Timeouts.getEmergencyCallbackWindowMillis(cr);
         }
+
+        public long getUserDefinedCallRedirectionTimeoutMillis(ContentResolver cr) {
+            return Timeouts.getUserDefinedCallRedirectionTimeoutMillis(cr);
+        }
+
+        public long getCarrierCallRedirectionTimeoutMillis(ContentResolver cr) {
+            return Timeouts.getCarrierCallRedirectionTimeoutMillis(cr);
+        }
+
+        public long getPhoneAccountSuggestionServiceTimeout(ContentResolver cr) {
+            return Timeouts.getPhoneAccountSuggestionServiceTimeout(cr);
+        }
     }
 
     /** A prefix to use for all keys so to not clobber the global namespace. */
@@ -143,6 +156,14 @@
     }
 
     /**
+     * Returns the amount of time to wait for the phone account suggestion service to reply.
+     */
+    public static long getPhoneAccountSuggestionServiceTimeout(ContentResolver contentResolver) {
+        return get(contentResolver, "phone_account_suggestion_service_timeout",
+                5000L /* 5 seconds */);
+    }
+
+    /**
      * Returns the amount of time to wait for the call screening service to allow or disallow a
      * call.
      */
@@ -158,4 +179,23 @@
       return get(contentResolver, "emergency_callback_window_millis",
           TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES));
     }
+
+    /**
+     * Returns the amount of time for an user-defined {@link CallRedirectionService}.
+     *
+     * @param contentResolver The content resolved.
+     */
+    public static long getUserDefinedCallRedirectionTimeoutMillis(ContentResolver contentResolver) {
+        return get(contentResolver, "user_defined_call_redirection_timeout",
+            5000L /* 5 seconds */);
+    }
+
+    /**
+     * Returns the amount of time for a carrier {@link CallRedirectionService}.
+     *
+     * @param contentResolver The content resolved.
+     */
+    public static long getCarrierCallRedirectionTimeoutMillis(ContentResolver contentResolver) {
+        return get(contentResolver, "carrier_call_redirection_timeout", 5000L /* 5 seconds */);
+    }
 }
diff --git a/src/com/android/server/telecom/VideoProviderProxy.java b/src/com/android/server/telecom/VideoProviderProxy.java
index 7d90a6d..364e0f4 100644
--- a/src/com/android/server/telecom/VideoProviderProxy.java
+++ b/src/com/android/server/telecom/VideoProviderProxy.java
@@ -20,7 +20,6 @@
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.net.Uri;
-import android.os.Binder;
 import android.os.Build;
 import android.os.IBinder;
 import android.os.Looper;
@@ -33,6 +32,7 @@
 import android.text.TextUtils;
 import android.view.Surface;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telecom.IVideoCallback;
 import com.android.internal.telecom.IVideoProvider;
 
@@ -40,8 +40,6 @@
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
-import static android.Manifest.permission.CALL_PHONE;
-
 /**
  * Proxies video provider messages from {@link InCallService.VideoCall}
  * implementations to the underlying {@link Connection.VideoProvider} implementation.  Also proxies
@@ -55,7 +53,7 @@
     /**
      * Listener for Telecom components interested in callbacks from the video provider.
      */
-    interface Listener {
+    public interface Listener {
         void onSessionModifyRequestReceived(Call call, VideoProfile videoProfile);
     }
 
@@ -112,7 +110,7 @@
      * @param call The current call.
      * @throws RemoteException Remote exception.
      */
-    VideoProviderProxy(TelecomSystem.SyncRoot lock,
+    public VideoProviderProxy(TelecomSystem.SyncRoot lock,
             IVideoProvider videoProvider, Call call, CurrentUserProxy currentUserProxy)
             throws RemoteException {
 
@@ -136,11 +134,16 @@
         }
     }
 
+    @VisibleForTesting
+    public VideoCallListenerBinder getVideoCallListenerBinder() {
+        return mVideoCallListenerBinder;
+    }
+
     /**
      * IVideoCallback stub implementation.  An instance of this class receives callbacks from the
      * {@code ConnectionService}'s video provider.
      */
-    private final class VideoCallListenerBinder extends IVideoCallback.Stub {
+    public final class VideoCallListenerBinder extends IVideoCallback.Stub {
         /**
          * Proxies a request from the {@link #mConectionServiceVideoProvider} to the
          * {@link InCallService} when a session modification request is received.
@@ -160,13 +163,14 @@
                             Analytics.RECEIVE_REMOTE_SESSION_MODIFY_REQUEST,
                             videoProfile.getVideoState());
 
-                    if (!mCall.isVideoCallingSupported() &&
-                            VideoProfile.isVideo(videoProfile.getVideoState())) {
-                        // If video calling is not supported by the phone account, and we receive
-                        // a request to upgrade to video, automatically reject it without informing
-                        // the InCallService.
-
-                        Log.addEvent(mCall, LogUtils.Events.SEND_VIDEO_RESPONSE, "video not supported");
+                    if ((!mCall.isVideoCallingSupportedByPhoneAccount()
+                            || !mCall.isLocallyVideoCapable())
+                            && VideoProfile.isVideo(videoProfile.getVideoState())) {
+                        // If video calling is not supported by the phone account, or is not
+                        // locally video capable and we receive a request to upgrade to video,
+                        // automatically reject it without informing the InCallService.
+                        Log.addEvent(mCall, LogUtils.Events.SEND_VIDEO_RESPONSE,
+                                "video not supported");
                         VideoProfile responseProfile = new VideoProfile(
                                 VideoProfile.STATE_AUDIO_ONLY);
                         try {
@@ -434,6 +438,11 @@
             logFromInCall("sendSessionModifyRequest: from=" + fromProfile + " to=" + toProfile);
             Log.addEvent(mCall, LogUtils.Events.SEND_VIDEO_REQUEST,
                     VideoProfile.videoStateToString(toProfile.getVideoState()));
+            if (!VideoProfile.isVideo(fromProfile.getVideoState())
+                    && VideoProfile.isVideo(toProfile.getVideoState())) {
+                // Upgrading to video; change to speaker potentially.
+                mCall.maybeEnableSpeakerForVideoUpgrade(toProfile.getVideoState());
+            }
             mCall.getAnalytics().addVideoEvent(
                     Analytics.SEND_LOCAL_SESSION_MODIFY_REQUEST,
                     toProfile.getVideoState());
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
index 26fe94e..3c334ca 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
@@ -18,25 +18,22 @@
 
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothProfile;
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.telecom.Log;
 
 import com.android.server.telecom.BluetoothAdapterProxy;
 import com.android.server.telecom.BluetoothHeadsetProxy;
-import com.android.server.telecom.TelecomSystem;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
+import java.util.Set;
 
 public class BluetoothDeviceManager {
     private final BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
@@ -50,8 +47,12 @@
                                 mBluetoothHeadsetService =
                                         new BluetoothHeadsetProxy((BluetoothHeadset) proxy);
                                 Log.i(this, "- Got BluetoothHeadset: " + mBluetoothHeadsetService);
+                            } else if (profile == BluetoothProfile.HEARING_AID) {
+                                mBluetoothHearingAidService = (BluetoothHearingAid) proxy;
+                                Log.i(this, "- Got BluetoothHearingAid: "
+                                        + mBluetoothHearingAidService);
                             } else {
-                                Log.w(this, "Connected to non-headset bluetooth service." +
+                                Log.w(this, "Connected to non-requested bluetooth service." +
                                         " Not changing bluetooth headset.");
                             }
                         }
@@ -65,12 +66,27 @@
                     Log.startSession("BMSL.oSD");
                     try {
                         synchronized (mLock) {
-                            mBluetoothHeadsetService = null;
-                            Log.i(BluetoothDeviceManager.this, "Lost BluetoothHeadset service. " +
-                                    "Removing all tracked devices.");
+                            LinkedHashMap<String, BluetoothDevice> lostServiceDevices;
+                            if (profile == BluetoothProfile.HEADSET) {
+                                mBluetoothHeadsetService = null;
+                                Log.i(BluetoothDeviceManager.this,
+                                        "Lost BluetoothHeadset service. " +
+                                                "Removing all tracked devices.");
+                                lostServiceDevices = mHfpDevicesByAddress;
+                                mBluetoothRouteManager.onActiveDeviceChanged(null, false);
+                            } else if (profile == BluetoothProfile.HEARING_AID) {
+                                mBluetoothHearingAidService = null;
+                                Log.i(BluetoothDeviceManager.this,
+                                        "Lost BluetoothHearingAid service. " +
+                                                "Removing all tracked devices.");
+                                lostServiceDevices = mHearingAidDevicesByAddress;
+                                mBluetoothRouteManager.onActiveDeviceChanged(null, true);
+                            } else {
+                                return;
+                            }
                             List<BluetoothDevice> devicesToRemove = new LinkedList<>(
-                                    mConnectedDevicesByAddress.values());
-                            mConnectedDevicesByAddress.clear();
+                                    lostServiceDevices.values());
+                            lostServiceDevices.clear();
                             for (BluetoothDevice device : devicesToRemove) {
                                 mBluetoothRouteManager.onDeviceLost(device.getAddress());
                             }
@@ -81,20 +97,27 @@
                 }
            };
 
-    private final LinkedHashMap<String, BluetoothDevice> mConnectedDevicesByAddress =
+    private final LinkedHashMap<String, BluetoothDevice> mHfpDevicesByAddress =
             new LinkedHashMap<>();
-    private final TelecomSystem.SyncRoot mLock;
+    private final LinkedHashMap<String, BluetoothDevice> mHearingAidDevicesByAddress =
+            new LinkedHashMap<>();
+    private final LinkedHashMap<BluetoothDevice, Long> mHearingAidDeviceSyncIds =
+            new LinkedHashMap<>();
+
+    // This lock only protects internal state -- it doesn't lock on anything going into Telecom.
+    private final Object mLock = new Object();
 
     private BluetoothRouteManager mBluetoothRouteManager;
     private BluetoothHeadsetProxy mBluetoothHeadsetService;
+    private BluetoothHearingAid mBluetoothHearingAidService;
+    private BluetoothDevice mBluetoothHearingAidActiveDeviceCache;
 
-    public BluetoothDeviceManager(Context context, BluetoothAdapterProxy bluetoothAdapter,
-            TelecomSystem.SyncRoot lock) {
-        mLock = lock;
-
+    public BluetoothDeviceManager(Context context, BluetoothAdapterProxy bluetoothAdapter) {
         if (bluetoothAdapter != null) {
             bluetoothAdapter.getProfileProxy(context, mBluetoothProfileServiceListener,
                     BluetoothProfile.HEADSET);
+            bluetoothAdapter.getProfileProxy(context, mBluetoothProfileServiceListener,
+                    BluetoothProfile.HEARING_AID);
         }
     }
 
@@ -103,57 +126,172 @@
     }
 
     public int getNumConnectedDevices() {
-        return mConnectedDevicesByAddress.size();
+        synchronized (mLock) {
+            return mHfpDevicesByAddress.size() + mHearingAidDevicesByAddress.size();
+        }
     }
 
     public Collection<BluetoothDevice> getConnectedDevices() {
-        return mConnectedDevicesByAddress.values();
+        synchronized (mLock) {
+            ArrayList<BluetoothDevice> result = new ArrayList<>(mHfpDevicesByAddress.values());
+            result.addAll(mHearingAidDevicesByAddress.values());
+            return Collections.unmodifiableCollection(result);
+        }
     }
 
-    public String getMostRecentlyConnectedDevice(String excludeAddress) {
-        String result = null;
-        synchronized (mLock) {
-            for (String addr : mConnectedDevicesByAddress.keySet()) {
-                if (!Objects.equals(addr, excludeAddress)) {
-                    result = addr;
+    // Same as getConnectedDevices except it filters out the hearing aid devices that are linked
+    // together by their hiSyncId.
+    public Collection<BluetoothDevice> getUniqueConnectedDevices() {
+        ArrayList<BluetoothDevice> result = new ArrayList<>(mHfpDevicesByAddress.values());
+        Set<Long> seenHiSyncIds = new LinkedHashSet<>();
+        // Add the left-most active device to the seen list so that we match up with the list
+        // generated in BluetoothRouteManager.
+        if (mBluetoothHearingAidService != null) {
+            for (BluetoothDevice device : mBluetoothHearingAidService.getActiveDevices()) {
+                if (device != null) {
+                    result.add(device);
+                    seenHiSyncIds.add(mHearingAidDeviceSyncIds.getOrDefault(device, -1L));
+                    break;
                 }
             }
         }
-        return result;
+        synchronized (mLock) {
+            for (BluetoothDevice d : mHearingAidDevicesByAddress.values()) {
+                long hiSyncId = mHearingAidDeviceSyncIds.getOrDefault(d, -1L);
+                if (seenHiSyncIds.contains(hiSyncId)) {
+                    continue;
+                }
+                result.add(d);
+                seenHiSyncIds.add(hiSyncId);
+            }
+        }
+        return Collections.unmodifiableCollection(result);
     }
 
     public BluetoothHeadsetProxy getHeadsetService() {
         return mBluetoothHeadsetService;
     }
 
+    public BluetoothHearingAid getHearingAidService() {
+        return mBluetoothHearingAidService;
+    }
+
     public void setHeadsetServiceForTesting(BluetoothHeadsetProxy bluetoothHeadset) {
         mBluetoothHeadsetService = bluetoothHeadset;
     }
 
-    public BluetoothDevice getDeviceFromAddress(String address) {
-        return mConnectedDevicesByAddress.get(address);
+    public void setHearingAidServiceForTesting(BluetoothHearingAid bluetoothHearingAid) {
+        mBluetoothHearingAidService = bluetoothHearingAid;
     }
 
-    void onDeviceConnected(BluetoothDevice device) {
+    void onDeviceConnected(BluetoothDevice device, boolean isHearingAid) {
         synchronized (mLock) {
-            if (mBluetoothHeadsetService == null) {
-                Log.w(this, "Headset service null when receiving device added broadcast");
-                return;
+            LinkedHashMap<String, BluetoothDevice> targetDeviceMap;
+            if (isHearingAid) {
+                if (mBluetoothHearingAidService == null) {
+                    Log.w(this, "Hearing aid service null when receiving device added broadcast");
+                    return;
+                }
+                long hiSyncId = mBluetoothHearingAidService.getHiSyncId(device);
+                mHearingAidDeviceSyncIds.put(device, hiSyncId);
+                targetDeviceMap = mHearingAidDevicesByAddress;
+            } else {
+                if (mBluetoothHeadsetService == null) {
+                    Log.w(this, "Headset service null when receiving device added broadcast");
+                    return;
+                }
+                targetDeviceMap = mHfpDevicesByAddress;
             }
-
-            if (!mConnectedDevicesByAddress.containsKey(device.getAddress())) {
-                mConnectedDevicesByAddress.put(device.getAddress(), device);
+            if (!targetDeviceMap.containsKey(device.getAddress())) {
+                targetDeviceMap.put(device.getAddress(), device);
                 mBluetoothRouteManager.onDeviceAdded(device.getAddress());
             }
         }
     }
 
-    void onDeviceDisconnected(BluetoothDevice device) {
+    void onDeviceDisconnected(BluetoothDevice device, boolean isHearingAid) {
         synchronized (mLock) {
-            if (mConnectedDevicesByAddress.containsKey(device.getAddress())) {
-                mConnectedDevicesByAddress.remove(device.getAddress());
+            LinkedHashMap<String, BluetoothDevice> targetDeviceMap;
+            if (isHearingAid) {
+                mHearingAidDeviceSyncIds.remove(device);
+                targetDeviceMap = mHearingAidDevicesByAddress;
+            } else {
+                targetDeviceMap = mHfpDevicesByAddress;
+            }
+            if (targetDeviceMap.containsKey(device.getAddress())) {
+                targetDeviceMap.remove(device.getAddress());
                 mBluetoothRouteManager.onDeviceLost(device.getAddress());
             }
         }
     }
+
+    public void disconnectAudio() {
+        if (mBluetoothHearingAidService == null) {
+            Log.w(this, "Trying to disconnect audio but no hearing aid service exists");
+        } else {
+            for (BluetoothDevice device : mBluetoothHearingAidService.getActiveDevices()) {
+                if (device != null) {
+                    mBluetoothHearingAidService.setActiveDevice(null);
+                }
+            }
+        }
+        disconnectSco();
+    }
+
+    public void disconnectSco() {
+        if (mBluetoothHeadsetService == null) {
+            Log.w(this, "Trying to disconnect audio but no headset service exists.");
+        } else {
+            mBluetoothHeadsetService.disconnectAudio();
+        }
+    }
+
+    // Connect audio to the bluetooth device at address, checking to see whether it's a hearing aid
+    // or a HFP device, and using the proper BT API.
+    public boolean connectAudio(String address) {
+        if (mHearingAidDevicesByAddress.containsKey(address)) {
+            if (mBluetoothHearingAidService == null) {
+                Log.w(this, "Attempting to turn on audio when the hearing aid service is null");
+                return false;
+            }
+            return mBluetoothHearingAidService.setActiveDevice(
+                    mHearingAidDevicesByAddress.get(address));
+        } else if (mHfpDevicesByAddress.containsKey(address)) {
+            BluetoothDevice device = mHfpDevicesByAddress.get(address);
+            if (mBluetoothHeadsetService == null) {
+                Log.w(this, "Attempting to turn on audio when the headset service is null");
+                return false;
+            }
+            boolean success = mBluetoothHeadsetService.setActiveDevice(device);
+            if (!success) {
+                Log.w(this, "Couldn't set active device to %s", address);
+                return false;
+            }
+            if (!mBluetoothHeadsetService.isAudioOn()) {
+                return mBluetoothHeadsetService.connectAudio();
+            }
+            return true;
+        } else {
+            Log.w(this, "Attempting to turn on audio for a disconnected device");
+            return false;
+        }
+    }
+
+    public void cacheHearingAidDevice() {
+        if (mBluetoothHearingAidService != null) {
+             for (BluetoothDevice device : mBluetoothHearingAidService.getActiveDevices()) {
+                 if (device != null) {
+                     mBluetoothHearingAidActiveDeviceCache = device;
+                 }
+             }
+        }
+    }
+
+    public void restoreHearingAidDevice() {
+        if (mBluetoothHearingAidActiveDeviceCache != null && mBluetoothHearingAidService != null) {
+            mBluetoothHearingAidService.setActiveDevice(mBluetoothHearingAidActiveDeviceCache);
+            mBluetoothHearingAidActiveDeviceCache = null;
+        }
+    }
+
 }
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java b/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
index f72c342..fe34be3 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothRouteManager.java
@@ -18,6 +18,7 @@
 
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothHearingAid;
 import android.content.Context;
 import android.os.Message;
 import android.telecom.Log;
@@ -33,13 +34,10 @@
 import com.android.server.telecom.TelecomSystem;
 import com.android.server.telecom.Timeouts;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
@@ -57,8 +55,8 @@
          put(CONNECT_HFP, "CONNECT_HFP");
          put(DISCONNECT_HFP, "DISCONNECT_HFP");
          put(RETRY_HFP_CONNECTION, "RETRY_HFP_CONNECTION");
-         put(HFP_IS_ON, "HFP_IS_ON");
-         put(HFP_LOST, "HFP_LOST");
+         put(BT_AUDIO_IS_ON, "BT_AUDIO_IS_ON");
+         put(BT_AUDIO_LOST, "BT_AUDIO_LOST");
          put(CONNECTION_TIMEOUT, "CONNECTION_TIMEOUT");
          put(GET_CURRENT_STATE, "GET_CURRENT_STATE");
          put(RUN_RUNNABLE, "RUN_RUNNABLE");
@@ -77,6 +75,12 @@
         void onBluetoothActiveDeviceGone();
         void onBluetoothAudioConnected();
         void onBluetoothAudioDisconnected();
+        /**
+         * This gets called when we get an unexpected state change from Bluetooth. Their stack does
+         * weird things sometimes, so this is really a signal for the listener to refresh their
+         * internal state and make sure it matches up with what the BT stack is doing.
+         */
+        void onUnexpectedBluetoothStateChange();
     }
 
     /**
@@ -97,9 +101,9 @@
     public static final int RETRY_HFP_CONNECTION = 102;
 
     // arg2: the address of the device that is on
-    public static final int HFP_IS_ON = 200;
-    // arg2: the address of the device that lost HFP
-    public static final int HFP_LOST = 201;
+    public static final int BT_AUDIO_IS_ON = 200;
+    // arg2: the address of the device that lost BT audio
+    public static final int BT_AUDIO_LOST = 201;
 
     // No args; only used internally
     public static final int CONNECTION_TIMEOUT = 300;
@@ -125,8 +129,9 @@
             BluetoothDevice erroneouslyConnectedDevice = getBluetoothAudioConnectedDevice();
             if (erroneouslyConnectedDevice != null) {
                 Log.w(LOG_TAG, "Entering AudioOff state but device %s appears to be connected. " +
-                        "Disconnecting.", erroneouslyConnectedDevice);
-                disconnectAudio();
+                        "Switching to audio-on state for that device.", erroneouslyConnectedDevice);
+                // change this to just transition to the new audio on state
+                transitionToActualState();
             }
             cleanupStatesForDisconnectedDevices();
             if (mListener != null) {
@@ -151,7 +156,7 @@
                         removeDevice((String) args.arg2);
                         break;
                     case CONNECT_HFP:
-                        String actualAddress = connectHfpAudio((String) args.arg2);
+                        String actualAddress = connectBtAudio((String) args.arg2);
 
                         if (actualAddress != null) {
                             transitionTo(getConnectingStateForAddress(actualAddress,
@@ -166,7 +171,7 @@
                         break;
                     case RETRY_HFP_CONNECTION:
                         Log.i(LOG_TAG, "Retrying HFP connection to %s", (String) args.arg2);
-                        String retryAddress = connectHfpAudio((String) args.arg2, args.argi1);
+                        String retryAddress = connectBtAudio((String) args.arg2, args.argi1);
 
                         if (retryAddress != null) {
                             transitionTo(getConnectingStateForAddress(retryAddress,
@@ -178,14 +183,16 @@
                     case CONNECTION_TIMEOUT:
                         // Ignore.
                         break;
-                    case HFP_IS_ON:
+                    case BT_AUDIO_IS_ON:
                         String address = (String) args.arg2;
                         Log.w(LOG_TAG, "HFP audio unexpectedly turned on from device %s", address);
-                        transitionTo(getConnectedStateForAddress(address, "AudioOff/HFP_IS_ON"));
+                        transitionTo(getConnectedStateForAddress(address,
+                                "AudioOff/BT_AUDIO_IS_ON"));
                         break;
-                    case HFP_LOST:
+                    case BT_AUDIO_LOST:
                         Log.i(LOG_TAG, "Received HFP off for device %s while HFP off.",
                                 (String) args.arg2);
+                        mListener.onUnexpectedBluetoothStateChange();
                         break;
                     case GET_CURRENT_STATE:
                         BlockingQueue<IState> sink = (BlockingQueue<IState>) args.arg3;
@@ -253,7 +260,7 @@
                             // Ignore repeated connection attempts to the same device
                             break;
                         }
-                        String actualAddress = connectHfpAudio(address);
+                        String actualAddress = connectBtAudio(address);
 
                         if (actualAddress != null) {
                             transitionTo(getConnectingStateForAddress(actualAddress,
@@ -264,14 +271,13 @@
                         }
                         break;
                     case DISCONNECT_HFP:
-                        disconnectAudio();
-                        transitionTo(mAudioOffState);
+                        mDeviceManager.disconnectAudio();
                         break;
                     case RETRY_HFP_CONNECTION:
                         if (Objects.equals(address, mDeviceAddress)) {
                             Log.d(LOG_TAG, "Retry message came through while connecting.");
                         } else {
-                            String retryAddress = connectHfpAudio(address, args.argi1);
+                            String retryAddress = connectBtAudio(address, args.argi1);
                             if (retryAddress != null) {
                                 transitionTo(getConnectingStateForAddress(retryAddress,
                                         "AudioConnecting/RETRY_HFP_CONNECTION"));
@@ -285,7 +291,7 @@
                                 mDeviceAddress);
                         transitionToActualState();
                         break;
-                    case HFP_IS_ON:
+                    case BT_AUDIO_IS_ON:
                         if (Objects.equals(mDeviceAddress, address)) {
                             Log.i(LOG_TAG, "HFP connection success for device %s.", mDeviceAddress);
                             transitionTo(mAudioConnectedStates.get(mDeviceAddress));
@@ -293,17 +299,18 @@
                             Log.w(LOG_TAG, "In connecting state for device %s but %s" +
                                     " is now connected", mDeviceAddress, address);
                             transitionTo(getConnectedStateForAddress(address,
-                                    "AudioConnecting/HFP_IS_ON"));
+                                    "AudioConnecting/BT_AUDIO_IS_ON"));
                         }
                         break;
-                    case HFP_LOST:
-                        if (Objects.equals(mDeviceAddress, address)) {
+                    case BT_AUDIO_LOST:
+                        if (Objects.equals(mDeviceAddress, address) || address == null) {
                             Log.i(LOG_TAG, "Connection with device %s failed.",
                                     mDeviceAddress);
                             transitionToActualState();
                         } else {
                             Log.w(LOG_TAG, "Got HFP lost message for device %s while" +
                                     " connecting to %s.", address, mDeviceAddress);
+                            mListener.onUnexpectedBluetoothStateChange();
                         }
                         break;
                     case GET_CURRENT_STATE:
@@ -366,7 +373,7 @@
                             // Ignore connection to already connected device.
                             break;
                         }
-                        String actualAddress = connectHfpAudio(address);
+                        String actualAddress = connectBtAudio(address);
 
                         if (actualAddress != null) {
                             transitionTo(getConnectingStateForAddress(address,
@@ -377,14 +384,13 @@
                         }
                         break;
                     case DISCONNECT_HFP:
-                        disconnectAudio();
-                        transitionTo(mAudioOffState);
+                        mDeviceManager.disconnectAudio();
                         break;
                     case RETRY_HFP_CONNECTION:
                         if (Objects.equals(address, mDeviceAddress)) {
                             Log.d(LOG_TAG, "Retry message came through while connected.");
                         } else {
-                            String retryAddress = connectHfpAudio(address, args.argi1);
+                            String retryAddress = connectBtAudio(address, args.argi1);
                             if (retryAddress != null) {
                                 transitionTo(getConnectingStateForAddress(retryAddress,
                                         "AudioConnected/RETRY_HFP_CONNECTION"));
@@ -396,23 +402,25 @@
                     case CONNECTION_TIMEOUT:
                         Log.w(LOG_TAG, "Received CONNECTION_TIMEOUT while connected.");
                         break;
-                    case HFP_IS_ON:
+                    case BT_AUDIO_IS_ON:
                         if (Objects.equals(mDeviceAddress, address)) {
-                            Log.i(LOG_TAG, "Received redundant HFP_IS_ON for %s", mDeviceAddress);
+                            Log.i(LOG_TAG,
+                                    "Received redundant BT_AUDIO_IS_ON for %s", mDeviceAddress);
                         } else {
                             Log.w(LOG_TAG, "In connected state for device %s but %s" +
                                     " is now connected", mDeviceAddress, address);
                             transitionTo(getConnectedStateForAddress(address,
-                                    "AudioConnected/HFP_IS_ON"));
+                                    "AudioConnected/BT_AUDIO_IS_ON"));
                         }
                         break;
-                    case HFP_LOST:
-                        if (Objects.equals(mDeviceAddress, address)) {
+                    case BT_AUDIO_LOST:
+                        if (Objects.equals(mDeviceAddress, address) || address == null) {
                             Log.i(LOG_TAG, "HFP connection with device %s lost.", mDeviceAddress);
                             transitionToActualState();
                         } else {
                             Log.w(LOG_TAG, "Got HFP lost message for device %s while" +
                                     " connected to %s.", address, mDeviceAddress);
+                            mListener.onUnexpectedBluetoothStateChange();
                         }
                         break;
                     case GET_CURRENT_STATE:
@@ -439,8 +447,10 @@
 
     private BluetoothStateListener mListener;
     private BluetoothDeviceManager mDeviceManager;
-    // Tracks the active device in the BT stack.
-    private BluetoothDevice mActiveDeviceCache = null;
+    // Tracks the active devices in the BT stack (HFP or hearing aid).
+    private BluetoothDevice mHfpActiveDeviceCache = null;
+    private BluetoothDevice mHearingAidActiveDeviceCache = null;
+    private BluetoothDevice mMostRecentlyReportedActiveDevice = null;
 
     public BluetoothRouteManager(Context context, TelecomSystem.SyncRoot lock,
             BluetoothDeviceManager deviceManager, Timeouts.Adapter timeoutsAdapter) {
@@ -537,6 +547,18 @@
         sendMessage(DISCONNECT_HFP, args);
     }
 
+    public void disconnectSco() {
+        mDeviceManager.disconnectSco();
+    }
+
+    public void cacheHearingAidDevice() {
+        mDeviceManager.cacheHearingAidDevice();
+    }
+
+    public void restoreHearingAidDevice() {
+        mDeviceManager.restoreHearingAidDevice();
+    }
+
     public void setListener(BluetoothStateListener listener) {
         mListener = listener;
     }
@@ -559,29 +581,41 @@
         mListener.onBluetoothDeviceListChanged();
     }
 
-    public void onActiveDeviceChanged(BluetoothDevice device) {
-        BluetoothDevice oldActiveDevice = mActiveDeviceCache;
-        mActiveDeviceCache = device;
-        if ((oldActiveDevice == null) ^ (device == null)) {
-            if (device == null) {
-                mListener.onBluetoothActiveDeviceGone();
-            } else {
-                mListener.onBluetoothActiveDevicePresent();
-            }
+    public void onActiveDeviceChanged(BluetoothDevice device, boolean isHearingAid) {
+        boolean wasActiveDevicePresent = mHearingAidActiveDeviceCache != null
+                || mHfpActiveDeviceCache != null;
+        if (isHearingAid) {
+            mHearingAidActiveDeviceCache = device;
+        } else {
+            mHfpActiveDeviceCache = device;
+        }
+
+        if (device != null) mMostRecentlyReportedActiveDevice = device;
+
+        boolean isActiveDevicePresent = mHearingAidActiveDeviceCache != null
+                || mHfpActiveDeviceCache != null;
+
+        if (wasActiveDevicePresent && !isActiveDevicePresent) {
+            mListener.onBluetoothActiveDeviceGone();
+        } else if (!wasActiveDevicePresent && isActiveDevicePresent) {
+            mListener.onBluetoothActiveDevicePresent();
         }
     }
 
-    public Collection<BluetoothDevice> getConnectedDevices() {
-        return Collections.unmodifiableCollection(
-                new ArrayList<>(mDeviceManager.getConnectedDevices()));
+    public boolean hasBtActiveDevice() {
+        return mHearingAidActiveDeviceCache != null || mHfpActiveDeviceCache != null;
     }
 
-    private String connectHfpAudio(String address) {
-        return connectHfpAudio(address, 0);
+    public Collection<BluetoothDevice> getConnectedDevices() {
+        return mDeviceManager.getUniqueConnectedDevices();
+    }
+
+    private String connectBtAudio(String address) {
+        return connectBtAudio(address, 0);
     }
 
     /**
-     * Initiates a HFP connection to the BT address specified.
+     * Initiates a connection to the BT address specified.
      * Note: This method is not synchronized on the Telecom lock, so don't try and call back into
      * Telecom from within it.
      * @param address The address that should be tried first. May be null.
@@ -589,8 +623,8 @@
      * @return The address of the device that's actually being connected to, or null if no
      * connection was successful.
      */
-    private String connectHfpAudio(String address, int retryCount) {
-        Collection<BluetoothDevice> deviceList = getConnectedDevices();
+    private String connectBtAudio(String address, int retryCount) {
+        Collection<BluetoothDevice> deviceList = mDeviceManager.getConnectedDevices();
         Optional<BluetoothDevice> matchingDevice = deviceList.stream()
                 .filter(d -> Objects.equals(d.getAddress(), address))
                 .findAny();
@@ -611,7 +645,7 @@
             Log.i(this, "No device with address %s available. Using %s instead.",
                     address, actualAddress);
         }
-        if (!connectAudio(actualAddress)) {
+        if (!mDeviceManager.connectAudio(actualAddress)) {
             boolean shouldRetry = retryCount < MAX_CONNECTION_RETRIES;
             Log.w(LOG_TAG, "Could not connect to %s. Will %s", actualAddress,
                     shouldRetry ? "retry" : "not retry");
@@ -631,7 +665,13 @@
     }
 
     private String getActiveDeviceAddress() {
-        return mActiveDeviceCache == null ? null : mActiveDeviceCache.getAddress();
+        if (mHfpActiveDeviceCache != null) {
+            return mHfpActiveDeviceCache.getAddress();
+        }
+        if (mHearingAidActiveDeviceCache != null) {
+            return mHearingAidActiveDeviceCache.getAddress();
+        }
+        return null;
     }
 
     private void transitionToActualState() {
@@ -652,23 +692,45 @@
     @VisibleForTesting
     public BluetoothDevice getBluetoothAudioConnectedDevice() {
         BluetoothHeadsetProxy bluetoothHeadset = mDeviceManager.getHeadsetService();
-        if (bluetoothHeadset == null) {
-            Log.i(this, "getBluetoothAudioConnectedDevice: no headset service available.");
+        BluetoothHearingAid bluetoothHearingAid = mDeviceManager.getHearingAidService();
+
+        BluetoothDevice hfpAudioOnDevice = null;
+        BluetoothDevice hearingAidActiveDevice = null;
+
+        if (bluetoothHeadset == null && bluetoothHearingAid == null) {
+            Log.i(this, "getBluetoothAudioConnectedDevice: no service available.");
             return null;
         }
-        List<BluetoothDevice> deviceList = bluetoothHeadset.getConnectedDevices();
 
-        for (int i = 0; i < deviceList.size(); i++) {
-            BluetoothDevice device = deviceList.get(i);
-            boolean isAudioOn = bluetoothHeadset.getAudioState(device)
-                    != BluetoothHeadset.STATE_AUDIO_DISCONNECTED;
-            Log.v(this, "isBluetoothAudioConnected: ==> isAudioOn = " + isAudioOn
-                    + "for headset: " + device);
-            if (isAudioOn) {
-                return device;
+        if (bluetoothHeadset != null) {
+            hfpAudioOnDevice = bluetoothHeadset.getActiveDevice();
+
+            if (bluetoothHeadset.getAudioState(hfpAudioOnDevice)
+                    == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
+                hfpAudioOnDevice = null;
             }
         }
-        return null;
+
+        if (bluetoothHearingAid != null) {
+            for (BluetoothDevice device : bluetoothHearingAid.getActiveDevices()) {
+                if (device != null) {
+                    hearingAidActiveDevice = device;
+                    break;
+                }
+            }
+        }
+
+        // Return the active device reported by either HFP or hearing aid. If both are reporting
+        // active devices, go with the most recent one as reported by the receiver.
+        if (hfpAudioOnDevice != null) {
+            if (hearingAidActiveDevice != null) {
+                Log.i(this, "Both HFP and hearing aid are reporting active devices. Going with"
+                        + " the most recently reported active device: %s");
+                return mMostRecentlyReportedActiveDevice;
+            }
+            return hfpAudioOnDevice;
+        }
+        return hearingAidActiveDevice;
     }
 
     /**
@@ -687,37 +749,6 @@
         return bluetoothHeadset.isInbandRingingEnabled();
     }
 
-    private boolean connectAudio(String address) {
-        BluetoothHeadsetProxy bluetoothHeadset = mDeviceManager.getHeadsetService();
-        if (bluetoothHeadset == null) {
-            Log.w(this, "Trying to connect audio but no headset service exists.");
-            return false;
-        }
-        BluetoothDevice device = mDeviceManager.getDeviceFromAddress(address);
-        if (device == null) {
-            Log.w(this, "Attempting to turn on audio for a disconnected device");
-            return false;
-        }
-        boolean success = bluetoothHeadset.setActiveDevice(device);
-        if (!success) {
-            Log.w(LOG_TAG, "Couldn't set active device to %s", address);
-            return false;
-        }
-        if (!bluetoothHeadset.isAudioOn()) {
-            return bluetoothHeadset.connectAudio();
-        }
-        return true;
-    }
-
-    private void disconnectAudio() {
-        BluetoothHeadsetProxy bluetoothHeadset = mDeviceManager.getHeadsetService();
-        if (bluetoothHeadset == null) {
-            Log.w(this, "Trying to disconnect audio but no headset service exists.");
-        } else {
-            bluetoothHeadset.disconnectAudio();
-        }
-    }
-
     private boolean addDevice(String address) {
         if (mAudioConnectingStates.containsKey(address)) {
             Log.i(this, "Attempting to add device %s twice.", address);
@@ -776,23 +807,30 @@
 
     @VisibleForTesting
     public void setInitialStateForTesting(String stateName, BluetoothDevice device) {
-        switch (stateName) {
-            case AUDIO_OFF_STATE_NAME:
-                transitionTo(mAudioOffState);
-                break;
-            case AUDIO_CONNECTING_STATE_NAME_PREFIX:
-                transitionTo(getConnectingStateForAddress(device.getAddress(),
-                        "setInitialStateForTesting"));
-                break;
-            case AUDIO_CONNECTED_STATE_NAME_PREFIX:
-                transitionTo(getConnectedStateForAddress(device.getAddress(),
-                        "setInitialStateForTesting"));
-                break;
-        }
+        sendMessage(RUN_RUNNABLE, (Runnable) () -> {
+            switch (stateName) {
+                case AUDIO_OFF_STATE_NAME:
+                    transitionTo(mAudioOffState);
+                    break;
+                case AUDIO_CONNECTING_STATE_NAME_PREFIX:
+                    transitionTo(getConnectingStateForAddress(device.getAddress(),
+                            "setInitialStateForTesting"));
+                    break;
+                case AUDIO_CONNECTED_STATE_NAME_PREFIX:
+                    transitionTo(getConnectedStateForAddress(device.getAddress(),
+                            "setInitialStateForTesting"));
+                    break;
+            }
+            Log.i(LOG_TAG, "transition for testing done: %s", stateName);
+        });
     }
 
     @VisibleForTesting
-    public void setActiveDeviceCacheForTesting(BluetoothDevice device) {
-        mActiveDeviceCache = device;
+    public void setActiveDeviceCacheForTesting(BluetoothDevice device, boolean isHearingAid) {
+        if (isHearingAid) {
+            mHearingAidActiveDeviceCache = device;
+        } else {
+            mHfpActiveDeviceCache = device;
+        }
     }
 }
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
index f9c6437..9e64b56 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
@@ -18,6 +18,8 @@
 
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothProfile;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -27,8 +29,8 @@
 
 import com.android.internal.os.SomeArgs;
 
-import static com.android.server.telecom.bluetooth.BluetoothRouteManager.HFP_IS_ON;
-import static com.android.server.telecom.bluetooth.BluetoothRouteManager.HFP_LOST;
+import static com.android.server.telecom.bluetooth.BluetoothRouteManager.BT_AUDIO_IS_ON;
+import static com.android.server.telecom.bluetooth.BluetoothRouteManager.BT_AUDIO_LOST;
 
 
 public class BluetoothStateReceiver extends BroadcastReceiver {
@@ -39,6 +41,8 @@
         INTENT_FILTER.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
         INTENT_FILTER.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
         INTENT_FILTER.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED);
+        INTENT_FILTER.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
+        INTENT_FILTER.addAction(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED);
     }
 
     // If not in a call, BSR won't listen to the Bluetooth stack's HFP on/off messages, since
@@ -55,9 +59,11 @@
                 case BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED:
                     handleAudioStateChanged(intent);
                     break;
+                case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED:
                 case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED:
                     handleConnectionStateChanged(intent);
                     break;
+                case BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED:
                 case BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED:
                     handleActiveDeviceChanged(intent);
                     break;
@@ -68,10 +74,6 @@
     }
 
     private void handleAudioStateChanged(Intent intent) {
-        if (!mIsInCall) {
-            Log.i(LOG_TAG, "Ignoring BT audio state change since we're not in a call");
-            return;
-        }
         int bluetoothHeadsetAudioState =
                 intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
                         BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
@@ -91,10 +93,14 @@
         args.arg2 = device.getAddress();
         switch (bluetoothHeadsetAudioState) {
             case BluetoothHeadset.STATE_AUDIO_CONNECTED:
-                mBluetoothRouteManager.sendMessage(HFP_IS_ON, args);
+                if (!mIsInCall) {
+                    Log.i(LOG_TAG, "Ignoring BT audio on since we're not in a call");
+                    return;
+                }
+                mBluetoothRouteManager.sendMessage(BT_AUDIO_IS_ON, args);
                 break;
             case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
-                mBluetoothRouteManager.sendMessage(HFP_LOST, args);
+                mBluetoothRouteManager.sendMessage(BT_AUDIO_LOST, args);
                 break;
         }
     }
@@ -114,19 +120,36 @@
         Log.i(LOG_TAG, "Device %s changed state to %d",
                 device.getAddress(), bluetoothHeadsetState);
 
-        if (bluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED) {
-            mBluetoothDeviceManager.onDeviceConnected(device);
-        } else if (bluetoothHeadsetState == BluetoothHeadset.STATE_DISCONNECTED
-                || bluetoothHeadsetState == BluetoothHeadset.STATE_DISCONNECTING) {
-            mBluetoothDeviceManager.onDeviceDisconnected(device);
+        boolean isHearingAid = BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED
+                .equals(intent.getAction());
+        if (bluetoothHeadsetState == BluetoothProfile.STATE_CONNECTED) {
+            mBluetoothDeviceManager.onDeviceConnected(device, isHearingAid);
+        } else if (bluetoothHeadsetState == BluetoothProfile.STATE_DISCONNECTED
+                || bluetoothHeadsetState == BluetoothProfile.STATE_DISCONNECTING) {
+            mBluetoothDeviceManager.onDeviceDisconnected(device, isHearingAid);
         }
     }
 
     private void handleActiveDeviceChanged(Intent intent) {
         BluetoothDevice device =
                 intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-        Log.i(LOG_TAG, "Device %s is now the preferred HFP device", device);
-        mBluetoothRouteManager.onActiveDeviceChanged(device);
+        boolean isHearingAid =
+                BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED.equals(intent.getAction());
+        Log.i(LOG_TAG, "Device %s is now the preferred BT device for %s", device,
+                isHearingAid ? "hearing aid" : "HFP");
+
+        mBluetoothRouteManager.onActiveDeviceChanged(device, isHearingAid);
+        if (isHearingAid) {
+            Session session = Log.createSubsession();
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = session;
+            if (device == null) {
+                mBluetoothRouteManager.sendMessage(BT_AUDIO_LOST, args);
+            } else {
+                args.arg2 = device.getAddress();
+                mBluetoothRouteManager.sendMessage(BT_AUDIO_IS_ON, args);
+            }
+        }
     }
 
     public BluetoothStateReceiver(BluetoothDeviceManager deviceManager,
diff --git a/src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java b/src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java
index 748d15e..0abd15d 100644
--- a/src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java
+++ b/src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java
@@ -21,6 +21,7 @@
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.provider.BlockedNumberContract;
+import android.provider.CallLog;
 import android.telecom.Log;
 import android.telecom.Logging.Session;
 import android.telecom.TelecomManager;
@@ -40,17 +41,20 @@
         implements IncomingCallFilter.CallFilter {
     private final Context mContext;
     private final BlockCheckerAdapter mBlockCheckerAdapter;
+    private final CallBlockListener mCallBlockListener;
     private Call mIncomingCall;
     private Session mBackgroundTaskSubsession;
     private Session mPostExecuteSubsession;
     private CallFilterResultCallback mCallback;
     private CallerInfoLookupHelper mCallerInfoLookupHelper;
+    private int mBlockStatus = BlockedNumberContract.STATUS_NOT_BLOCKED;
 
     public AsyncBlockCheckFilter(Context context, BlockCheckerAdapter blockCheckerAdapter,
-            CallerInfoLookupHelper callerInfoLookupHelper) {
+            CallerInfoLookupHelper callerInfoLookupHelper, CallBlockListener callBlockListener) {
         mContext = context;
         mBlockCheckerAdapter = blockCheckerAdapter;
         mCallerInfoLookupHelper = callerInfoLookupHelper;
+        mCallBlockListener = callBlockListener;
     }
 
     @Override
@@ -104,7 +108,8 @@
                 extras.putBoolean(BlockedNumberContract.EXTRA_CONTACT_EXIST,
                         Boolean.valueOf(params[2]));
             }
-            return mBlockCheckerAdapter.isBlocked(mContext, params[0], extras);
+            mBlockStatus = mBlockCheckerAdapter.getBlockStatus(mContext, params[0], extras);
+            return mBlockStatus != BlockedNumberContract.STATUS_NOT_BLOCKED;
         } finally {
             Log.endSession();
         }
@@ -119,9 +124,18 @@
                 result = new CallFilteringResult(
                         false, // shouldAllowCall
                         true, //shouldReject
-                        false, //shouldAddToCallLog
-                        false // shouldShowNotification
+                        true, //shouldAddToCallLog
+                        false, // shouldShowNotification
+                        convertBlockStatusToReason(), //callBlockReason
+                        null, //callScreeningAppName
+                        null //callScreeningComponentName
                 );
+                if (mCallBlockListener != null) {
+                    String number = mIncomingCall.getHandle() == null ? null
+                            : mIncomingCall.getHandle().getSchemeSpecificPart();
+                    mCallBlockListener.onCallBlocked(mBlockStatus, number,
+                            mIncomingCall.getInitiatingUser());
+                }
             } else {
                 result = new CallFilteringResult(
                         true, // shouldAllowCall
@@ -130,10 +144,36 @@
                         true // shouldShowNotification
                 );
             }
-            Log.addEvent(mIncomingCall, LogUtils.Events.BLOCK_CHECK_FINISHED, result);
+            Log.addEvent(mIncomingCall, LogUtils.Events.BLOCK_CHECK_FINISHED,
+                    BlockedNumberContract.SystemContract.blockStatusToString(mBlockStatus) + " "
+                            + result);
             mCallback.onCallFilteringComplete(mIncomingCall, result);
         } finally {
             Log.endSession();
         }
     }
+
+    private int convertBlockStatusToReason() {
+        switch (mBlockStatus) {
+            case BlockedNumberContract.STATUS_BLOCKED_IN_LIST:
+                return CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER;
+
+            case BlockedNumberContract.STATUS_BLOCKED_UNKNOWN_NUMBER:
+                return CallLog.Calls.BLOCK_REASON_UNKNOWN_NUMBER;
+
+            case BlockedNumberContract.STATUS_BLOCKED_RESTRICTED:
+                return CallLog.Calls.BLOCK_REASON_RESTRICTED_NUMBER;
+
+            case BlockedNumberContract.STATUS_BLOCKED_PAYPHONE:
+                return CallLog.Calls.BLOCK_REASON_PAY_PHONE;
+
+            case BlockedNumberContract.STATUS_BLOCKED_NOT_IN_CONTACTS:
+                return CallLog.Calls.BLOCK_REASON_NOT_IN_CONTACTS;
+
+            default:
+                Log.w(AsyncBlockCheckFilter.class.getSimpleName(),
+                    "There's no call log block reason can be converted");
+                return CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER;
+        }
+    }
 }
diff --git a/src/com/android/server/telecom/callfiltering/BlockCheckerAdapter.java b/src/com/android/server/telecom/callfiltering/BlockCheckerAdapter.java
index 8c74fa9..4a5ac60 100644
--- a/src/com/android/server/telecom/callfiltering/BlockCheckerAdapter.java
+++ b/src/com/android/server/telecom/callfiltering/BlockCheckerAdapter.java
@@ -30,9 +30,15 @@
      * @param context the context of the caller.
      * @param number the number to check.
      * @param extras the extra attribute of the number.
-     * @return {@code true} if the number is blocked. {@code false} otherwise.
+     * @return result code indicating if the number should be blocked, and if so why.
+     *         Valid values are: {@link android.provider.BlockedNumberContract#STATUS_NOT_BLOCKED},
+     *         {@link android.provider.BlockedNumberContract#STATUS_BLOCKED_IN_LIST},
+     *         {@link android.provider.BlockedNumberContract#STATUS_BLOCKED_NOT_IN_CONTACTS},
+     *         {@link android.provider.BlockedNumberContract#STATUS_BLOCKED_PAYPHONE},
+     *         {@link android.provider.BlockedNumberContract#STATUS_BLOCKED_RESTRICTED},
+     *         {@link android.provider.BlockedNumberContract#STATUS_BLOCKED_UNKNOWN_NUMBER}.
      */
-    public boolean isBlocked(Context context, String number, Bundle extras) {
-        return BlockChecker.isBlocked(context, number, extras);
+    public int getBlockStatus(Context context, String number, Bundle extras) {
+        return BlockChecker.getBlockStatus(context, number, extras);
     }
 }
diff --git a/src/com/android/server/telecom/callfiltering/CallBlockListener.java b/src/com/android/server/telecom/callfiltering/CallBlockListener.java
new file mode 100644
index 0000000..d0a9949
--- /dev/null
+++ b/src/com/android/server/telecom/callfiltering/CallBlockListener.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2018 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.callfiltering;
+
+import android.os.UserHandle;
+
+/**
+ * Listener for components which wish to be notified when a call is blocked.
+ */
+public interface CallBlockListener {
+    void onCallBlocked(int blockStatus, String number, UserHandle userHandle);
+}
diff --git a/src/com/android/server/telecom/callfiltering/CallFilteringResult.java b/src/com/android/server/telecom/callfiltering/CallFilteringResult.java
index 9e35d86..6c37fd4 100644
--- a/src/com/android/server/telecom/callfiltering/CallFilteringResult.java
+++ b/src/com/android/server/telecom/callfiltering/CallFilteringResult.java
@@ -16,11 +16,18 @@
 
 package com.android.server.telecom.callfiltering;
 
+import android.provider.CallLog;
+import android.provider.CallLog.Calls;
+import android.text.TextUtils;
+
 public class CallFilteringResult {
     public boolean shouldAllowCall;
     public boolean shouldReject;
     public boolean shouldAddToCallLog;
     public boolean shouldShowNotification;
+    public int mCallBlockReason = CallLog.Calls.BLOCK_REASON_NOT_BLOCKED;
+    public CharSequence mCallScreeningAppName = null;
+    public String mCallScreeningComponentName = null;
 
     public CallFilteringResult(boolean shouldAllowCall, boolean shouldReject, boolean
             shouldAddToCallLog, boolean shouldShowNotification) {
@@ -30,22 +37,85 @@
         this.shouldShowNotification = shouldShowNotification;
     }
 
+    public CallFilteringResult(boolean shouldAllowCall, boolean shouldReject, boolean
+            shouldAddToCallLog, boolean shouldShowNotification, int callBlockReason,
+            CharSequence callScreeningAppName, String callScreeningComponentName) {
+        this.shouldAllowCall = shouldAllowCall;
+        this.shouldReject = shouldReject;
+        this.shouldAddToCallLog = shouldAddToCallLog;
+        this.shouldShowNotification = shouldShowNotification;
+        this.mCallBlockReason = callBlockReason;
+        this.mCallScreeningAppName = callScreeningAppName;
+        this.mCallScreeningComponentName = callScreeningComponentName;
+    }
+
     /**
-     * Combine this CallFilteringResult with another, returning a CallFilteringResult with
-     * the more restrictive properties of the two.
+     * Combine this CallFilteringResult with another, returning a CallFilteringResult with the more
+     * restrictive properties of the two. Where there are multiple call filtering components which
+     * block a call, the first filter from {@link AsyncBlockCheckFilter},
+     * {@link DirectToVoicemailCallFilter}, {@link CallScreeningServiceFilter} which blocked a call
+     * shall be used to populate the call block reason, component name, etc.
      */
     public CallFilteringResult combine(CallFilteringResult other) {
         if (other == null) {
             return this;
         }
 
+        if (isBlockedByProvider(mCallBlockReason)) {
+            return getCombinedCallFilteringResult(other, mCallBlockReason,
+                null /*callScreeningAppName*/, null /*callScreeningComponentName*/);
+        } else if (isBlockedByProvider(other.mCallBlockReason)) {
+            return getCombinedCallFilteringResult(other, other.mCallBlockReason,
+                null /*callScreeningAppName*/, null /*callScreeningComponentName*/);
+        }
+
+        if (mCallBlockReason == Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL
+            || other.mCallBlockReason == Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL) {
+            return getCombinedCallFilteringResult(other, Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL,
+                null /*callScreeningAppName*/, null /*callScreeningComponentName*/);
+        }
+
+        if (shouldReject && mCallBlockReason == CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE) {
+            return getCombinedCallFilteringResult(other, Calls.BLOCK_REASON_CALL_SCREENING_SERVICE,
+                mCallScreeningAppName, mCallScreeningComponentName);
+        } else if (other.shouldReject && other.mCallBlockReason == CallLog.Calls
+            .BLOCK_REASON_CALL_SCREENING_SERVICE) {
+            return getCombinedCallFilteringResult(other, Calls.BLOCK_REASON_CALL_SCREENING_SERVICE,
+                other.mCallScreeningAppName, other.mCallScreeningComponentName);
+        }
+
         return new CallFilteringResult(
-                shouldAllowCall && other.shouldAllowCall,
-                shouldReject || other.shouldReject,
-                shouldAddToCallLog && other.shouldAddToCallLog,
-                shouldShowNotification && other.shouldShowNotification);
+            shouldAllowCall && other.shouldAllowCall,
+            shouldReject || other.shouldReject,
+            shouldAddToCallLog && other.shouldAddToCallLog,
+            shouldShowNotification && other.shouldShowNotification);
     }
 
+    private boolean isBlockedByProvider(int blockReason) {
+        if (blockReason == Calls.BLOCK_REASON_BLOCKED_NUMBER
+            || blockReason == Calls.BLOCK_REASON_UNKNOWN_NUMBER
+            || blockReason == Calls.BLOCK_REASON_RESTRICTED_NUMBER
+            || blockReason == Calls.BLOCK_REASON_PAY_PHONE
+            || blockReason == Calls.BLOCK_REASON_NOT_IN_CONTACTS) {
+            return true;
+        }
+
+        return false;
+    }
+
+    private CallFilteringResult getCombinedCallFilteringResult(CallFilteringResult other,
+        int callBlockReason, CharSequence callScreeningAppName, String callScreeningComponentName) {
+        return new CallFilteringResult(
+            shouldAllowCall && other.shouldAllowCall,
+            shouldReject || other.shouldReject,
+            shouldAddToCallLog && other.shouldAddToCallLog,
+            shouldShowNotification && other.shouldShowNotification,
+            callBlockReason,
+            callScreeningAppName,
+            callScreeningComponentName);
+    }
+
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
@@ -56,7 +126,24 @@
         if (shouldAllowCall != that.shouldAllowCall) return false;
         if (shouldReject != that.shouldReject) return false;
         if (shouldAddToCallLog != that.shouldAddToCallLog) return false;
-        return shouldShowNotification == that.shouldShowNotification;
+        if (shouldShowNotification != that.shouldShowNotification) return false;
+        if (mCallBlockReason != that.mCallBlockReason) return false;
+
+        if ((TextUtils.isEmpty(mCallScreeningAppName) &&
+            TextUtils.isEmpty(that.mCallScreeningAppName)) &&
+            (TextUtils.isEmpty(mCallScreeningComponentName) &&
+            TextUtils.isEmpty(that.mCallScreeningComponentName))) {
+            return true;
+        } else if (!TextUtils.isEmpty(mCallScreeningAppName) &&
+            !TextUtils.isEmpty(that.mCallScreeningAppName) &&
+            mCallScreeningAppName.equals(that.mCallScreeningAppName) &&
+            !TextUtils.isEmpty(mCallScreeningComponentName) &&
+            !TextUtils.isEmpty(that.mCallScreeningComponentName) &&
+            mCallScreeningComponentName.equals(that.mCallScreeningComponentName)) {
+            return true;
+        }
+
+        return false;
     }
 
     @Override
@@ -87,6 +174,21 @@
         if (shouldShowNotification) {
             sb.append(", notified");
         }
+
+        if (mCallBlockReason != 0) {
+            sb.append(", mCallBlockReason = ");
+            sb.append(mCallBlockReason);
+        }
+
+        if (!TextUtils.isEmpty(mCallScreeningAppName)) {
+            sb.append(", mCallScreeningAppName = ");
+            sb.append(mCallScreeningAppName);
+        }
+
+        if (!TextUtils.isEmpty(mCallScreeningComponentName)) {
+            sb.append(", mCallScreeningComponentName = ");
+            sb.append(mCallScreeningComponentName);
+        }
         sb.append("]");
 
         return sb.toString();
diff --git a/src/com/android/server/telecom/callfiltering/CallScreeningServiceController.java b/src/com/android/server/telecom/callfiltering/CallScreeningServiceController.java
new file mode 100644
index 0000000..b72ac0b
--- /dev/null
+++ b/src/com/android/server/telecom/callfiltering/CallScreeningServiceController.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2018 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.callfiltering;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PersistableBundle;
+import android.provider.CallLog;
+import android.telecom.Log;
+import android.telecom.Logging.Runnable;
+import android.telecom.TelecomManager;
+import android.telephony.CarrierConfigManager;
+import android.text.TextUtils;
+
+import com.android.internal.telephony.CallerInfo;
+import com.android.server.telecom.Call;
+import com.android.server.telecom.CallScreeningServiceHelper;
+import com.android.server.telecom.CallerInfoLookupHelper;
+import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.LogUtils;
+import com.android.server.telecom.ParcelableCallUtils;
+import com.android.server.telecom.PhoneAccountRegistrar;
+import com.android.server.telecom.TelecomServiceImpl;
+import com.android.server.telecom.TelecomSystem;
+
+/**
+ * This class supports binding to the various {@link android.telecom.CallScreeningService}:
+ * carrier, default dialer and user chosen. Carrier's CallScreeningService implementation will be
+ * bound first, and then default dialer's and user chosen's. If Carrier's CallScreeningService
+ * blocks a call, no further CallScreeningService after it will be bound.
+ */
+public class CallScreeningServiceController implements IncomingCallFilter.CallFilter,
+        CallScreeningServiceFilter.CallScreeningFilterResultCallback {
+
+    private final Context mContext;
+    private final CallsManager mCallsManager;
+    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
+    private final ParcelableCallUtils.Converter mParcelableCallUtilsConverter;
+    private final TelecomSystem.SyncRoot mTelecomLock;
+    private final TelecomServiceImpl.SettingsSecureAdapter mSettingsSecureAdapter;
+    private final CallerInfoLookupHelper mCallerInfoLookupHelper;
+    private final CallScreeningServiceHelper.AppLabelProxy mAppLabelProxy;
+
+    private final int CARRIER_CALL_FILTERING_TIMED_OUT = 2000; // 2 seconds
+    private final int CALL_FILTERING_TIMED_OUT = 4500; // 4.5 seconds
+
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+
+    private Call mCall;
+    private CallFilterResultCallback mCallback;
+
+    private CallFilteringResult mResult = new CallFilteringResult(
+            true, // shouldAllowCall
+            false, // shouldReject
+            true, // shouldAddToCallLog
+            true // shouldShowNotification
+    );
+
+    private boolean mIsFinished;
+    private boolean mIsCarrierFinished;
+    private boolean mIsDefaultDialerFinished;
+    private boolean mIsUserChosenFinished;
+
+    public CallScreeningServiceController(
+            Context context,
+            CallsManager callsManager,
+            PhoneAccountRegistrar phoneAccountRegistrar,
+            ParcelableCallUtils.Converter parcelableCallUtilsConverter,
+            TelecomSystem.SyncRoot lock,
+            TelecomServiceImpl.SettingsSecureAdapter settingsSecureAdapter,
+            CallerInfoLookupHelper callerInfoLookupHelper,
+            CallScreeningServiceHelper.AppLabelProxy appLabelProxy) {
+        mContext = context;
+        mCallsManager = callsManager;
+        mPhoneAccountRegistrar = phoneAccountRegistrar;
+        mParcelableCallUtilsConverter = parcelableCallUtilsConverter;
+        mTelecomLock = lock;
+        mSettingsSecureAdapter = settingsSecureAdapter;
+        mCallerInfoLookupHelper = callerInfoLookupHelper;
+        mAppLabelProxy = appLabelProxy;
+    }
+
+    @Override
+    public void startFilterLookup(Call call, CallFilterResultCallback callBack) {
+        mCall = call;
+        mCallback = callBack;
+        mIsFinished = false;
+        mIsCarrierFinished = false;
+        mIsDefaultDialerFinished = false;
+        mIsUserChosenFinished = false;
+
+        bindCarrierService();
+
+        // Call screening filtering timed out
+        mHandler.postDelayed(new Runnable("ICF.pFTO", mTelecomLock) {
+            @Override
+            public void loggedRun() {
+                if (!mIsFinished) {
+                    Log.i(CallScreeningServiceController.this, "Call screening has timed out.");
+                    finishCallScreening();
+                }
+            }
+        }.prepare(), CALL_FILTERING_TIMED_OUT);
+    }
+
+    @Override
+    public void onCallScreeningFilterComplete(Call call, CallFilteringResult result,
+            String packageName) {
+        synchronized (mTelecomLock) {
+            mResult = result.combine(mResult);
+            if (!TextUtils.isEmpty(packageName) && packageName.equals(getCarrierPackageName())) {
+                mIsCarrierFinished = true;
+                if (result.mCallBlockReason == CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE) {
+                    finishCallScreening();
+                } else {
+                    checkContactExistsAndBindService();
+                }
+            } else if (!TextUtils.isEmpty(packageName) &&
+                    packageName.equals(getDefaultDialerPackageName())) {
+                // Default dialer defined CallScreeningService cannot skip the call log.
+                mResult.shouldAddToCallLog = true;
+                mIsDefaultDialerFinished = true;
+                if (result.mCallBlockReason == CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE ||
+                        mIsUserChosenFinished) {
+                    finishCallScreening();
+                }
+            } else if (!TextUtils.isEmpty(packageName) &&
+                    packageName.equals(getUserChosenPackageName())) {
+                // User defined CallScreeningService cannot skip the call log.
+                mResult.shouldAddToCallLog = true;
+                mIsUserChosenFinished = true;
+                if (mIsDefaultDialerFinished) {
+                    finishCallScreening();
+                }
+            }
+        }
+    }
+
+    private void bindCarrierService() {
+        String carrierPackageName = getCarrierPackageName();
+        if (TextUtils.isEmpty(carrierPackageName)) {
+            mIsCarrierFinished = true;
+            bindDefaultDialerAndUserChosenService();
+        } else {
+            createCallScreeningServiceFilter().startCallScreeningFilter(mCall, this,
+                    carrierPackageName, mAppLabelProxy.getAppLabel(carrierPackageName));
+        }
+
+        // Carrier filtering timed out
+        mHandler.postDelayed(new Runnable("ICF.pFTO", mTelecomLock) {
+            @Override
+            public void loggedRun() {
+                if (!mIsCarrierFinished) {
+                    mIsCarrierFinished = true;
+                    checkContactExistsAndBindService();
+                }
+            }
+        }.prepare(), CARRIER_CALL_FILTERING_TIMED_OUT);
+    }
+
+    private void bindDefaultDialerAndUserChosenService() {
+        if (mIsCarrierFinished) {
+            String dialerPackageName = getDefaultDialerPackageName();
+            if (TextUtils.isEmpty(dialerPackageName)) {
+                mIsDefaultDialerFinished = true;
+            } else {
+                createCallScreeningServiceFilter().startCallScreeningFilter(mCall,
+                        CallScreeningServiceController.this, dialerPackageName,
+                        mAppLabelProxy.getAppLabel(dialerPackageName));
+            }
+
+            String userChosenPackageName = getUserChosenPackageName();
+            if (TextUtils.isEmpty(userChosenPackageName)) {
+                mIsUserChosenFinished = true;
+            } else {
+                createCallScreeningServiceFilter().startCallScreeningFilter(mCall,
+                        CallScreeningServiceController.this, userChosenPackageName,
+                        mAppLabelProxy.getAppLabel(userChosenPackageName));
+            }
+
+            if (mIsDefaultDialerFinished && mIsUserChosenFinished) {
+                finishCallScreening();
+            }
+        }
+    }
+
+    private CallScreeningServiceFilter createCallScreeningServiceFilter() {
+        return new CallScreeningServiceFilter(
+                mContext,
+                mCallsManager,
+                mPhoneAccountRegistrar,
+                mParcelableCallUtilsConverter,
+                mTelecomLock,
+                mSettingsSecureAdapter);
+    }
+
+    private void checkContactExistsAndBindService() {
+        mCallerInfoLookupHelper.startLookup(mCall.getHandle(),
+                new CallerInfoLookupHelper.OnQueryCompleteListener() {
+                    @Override
+                    public void onCallerInfoQueryComplete(Uri handle, CallerInfo info) {
+                        boolean contactExists = info != null && info.contactExists;
+                        Log.i(CallScreeningServiceController.this, "Contact exists: " +
+                                contactExists);
+                        if (!contactExists) {
+                            bindDefaultDialerAndUserChosenService();
+                        } else {
+                            finishCallScreening();
+                        }
+                    }
+
+                    @Override
+                    public void onContactPhotoQueryComplete(Uri handle, CallerInfo
+                            info) {
+                        // ignore
+                    }
+                });
+    }
+
+    private void finishCallScreening() {
+        Log.addEvent(mCall, LogUtils.Events.CONTROLLER_SCREENING_COMPLETED, mResult);
+        mCallback.onCallFilteringComplete(mCall, mResult);
+        mIsFinished = true;
+    }
+
+    private String getCarrierPackageName() {
+        ComponentName componentName = null;
+        CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService
+                (Context.CARRIER_CONFIG_SERVICE);
+        PersistableBundle configBundle = configManager.getConfig();
+        if (configBundle != null) {
+            componentName = ComponentName.unflattenFromString(configBundle.getString
+                    (CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING));
+        }
+
+        return componentName != null ? componentName.getPackageName() : null;
+    }
+
+    private String getDefaultDialerPackageName() {
+        return TelecomManager.from(mContext).getDefaultDialerPackage();
+    }
+
+    private String getUserChosenPackageName() {
+        return mCallsManager.getRoleManagerAdapter().getDefaultCallScreeningApp();
+    }
+}
diff --git a/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java b/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java
index 4830b31..996ebc2 100644
--- a/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java
+++ b/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java
@@ -24,21 +24,27 @@
 import android.content.pm.ResolveInfo;
 import android.os.Binder;
 import android.os.IBinder;
+import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.provider.CallLog;
+import android.provider.Settings;
 import android.telecom.CallScreeningService;
 import android.telecom.Log;
+import android.telecom.ParcelableCall;
+import android.telecom.TelecomManager;
+import android.telephony.CarrierConfigManager;
 import android.text.TextUtils;
 
 import com.android.internal.telecom.ICallScreeningAdapter;
 import com.android.internal.telecom.ICallScreeningService;
 import com.android.server.telecom.Call;
+import com.android.server.telecom.CallScreeningServiceHelper;
 import com.android.server.telecom.CallsManager;
-import com.android.server.telecom.DefaultDialerCache;
 import com.android.server.telecom.LogUtils;
 import com.android.server.telecom.ParcelableCallUtils;
 import com.android.server.telecom.PhoneAccountRegistrar;
-import com.android.server.telecom.TelecomServiceImpl;
+import com.android.server.telecom.TelecomServiceImpl.SettingsSecureAdapter;
 import com.android.server.telecom.TelecomSystem;
 
 import java.util.List;
@@ -47,7 +53,13 @@
  * Binds to {@link ICallScreeningService} to allow call blocking. A single instance of this class
  * handles a single call.
  */
-public class CallScreeningServiceFilter implements IncomingCallFilter.CallFilter {
+public class CallScreeningServiceFilter {
+
+    public interface CallScreeningFilterResultCallback {
+        void onCallScreeningFilterComplete(Call call, CallFilteringResult result, String
+                packageName);
+    }
+
     private class CallScreeningServiceConnection implements ServiceConnection {
         @Override
         public void onServiceConnected(ComponentName componentName, IBinder service) {
@@ -108,20 +120,26 @@
                 String callId,
                 boolean shouldReject,
                 boolean shouldAddToCallLog,
-                boolean shouldShowNotification) {
+                boolean shouldShowNotification,
+                ComponentName componentName) {
             Log.startSession("CSCR.dC");
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mTelecomLock) {
+                    boolean isServiceRequestingLogging = isLoggable(componentName,
+                            shouldAddToCallLog);
                     Log.i(this, "disallowCall(%s), shouldReject: %b, shouldAddToCallLog: %b, "
                                     + "shouldShowNotification: %b", callId, shouldReject,
-                            shouldAddToCallLog, shouldShowNotification);
+                            isServiceRequestingLogging, shouldShowNotification);
                     if (mCall != null && mCall.getId().equals(callId)) {
                         mResult = new CallFilteringResult(
                                 false, // shouldAllowCall
                                 shouldReject, //shouldReject
-                                shouldAddToCallLog, //shouldAddToCallLog
-                                shouldShowNotification // shouldShowNotification
+                                isServiceRequestingLogging, //shouldAddToCallLog
+                                shouldShowNotification, // shouldShowNotification
+                                CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, //callBlockReason
+                                mAppName, //callScreeningAppName
+                                componentName.flattenToString() //callScreeningComponentName
                         );
                     } else {
                         Log.w(this, "disallowCall, unknown call id: %s", callId);
@@ -136,18 +154,19 @@
     }
 
     private final Context mContext;
-    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
     private final CallsManager mCallsManager;
-    private final DefaultDialerCache mDefaultDialerCache;
     private final ParcelableCallUtils.Converter mParcelableCallUtilsConverter;
     private final TelecomSystem.SyncRoot mTelecomLock;
+    private final SettingsSecureAdapter mSettingsSecureAdapter;
 
     private Call mCall;
-    private CallFilterResultCallback mCallback;
+    private CallScreeningFilterResultCallback mCallback;
     private ICallScreeningService mService;
     private ServiceConnection mConnection;
-
+    private String mPackageName;
+    private CharSequence mAppName;
     private boolean mHasFinished = false;
+
     private CallFilteringResult mResult = new CallFilteringResult(
             true, // shouldAllowCall
             false, //shouldReject
@@ -159,27 +178,35 @@
             Context context,
             CallsManager callsManager,
             PhoneAccountRegistrar phoneAccountRegistrar,
-            DefaultDialerCache defaultDialerCache,
             ParcelableCallUtils.Converter parcelableCallUtilsConverter,
-            TelecomSystem.SyncRoot lock) {
+            TelecomSystem.SyncRoot lock,
+            SettingsSecureAdapter settingsSecureAdapter) {
         mContext = context;
-        mPhoneAccountRegistrar = phoneAccountRegistrar;
         mCallsManager = callsManager;
-        mDefaultDialerCache = defaultDialerCache;
         mParcelableCallUtilsConverter = parcelableCallUtilsConverter;
         mTelecomLock = lock;
+        mSettingsSecureAdapter = settingsSecureAdapter;
     }
 
-    @Override
-    public void startFilterLookup(Call call, CallFilterResultCallback callback) {
+    public void startCallScreeningFilter(Call call,
+                                         CallScreeningFilterResultCallback callback,
+                                         String packageName,
+                                         CharSequence appName) {
         if (mHasFinished) {
             Log.w(this, "Attempting to reuse CallScreeningServiceFilter. Ignoring.");
             return;
         }
-        Log.addEvent(call, LogUtils.Events.SCREENING_SENT);
+        Log.addEvent(call, LogUtils.Events.SCREENING_SENT, packageName);
         mCall = call;
         mCallback = callback;
-        if (!bindService()) {
+        mPackageName = packageName;
+        mAppName = appName;
+
+        mConnection = new CallScreeningServiceConnection();
+        if (!CallScreeningServiceHelper.bindCallScreeningService(mContext,
+                mCallsManager.getCurrentUserHandle(),
+                mPackageName,
+                mConnection)) {
             Log.i(this, "Could not bind to call screening service");
             finishCallScreening();
         }
@@ -188,11 +215,15 @@
     private void finishCallScreening() {
         if (!mHasFinished) {
             Log.addEvent(mCall, LogUtils.Events.SCREENING_COMPLETED, mResult);
-            mCallback.onCallFilteringComplete(mCall, mResult);
+            mCallback.onCallScreeningFilterComplete(mCall, mResult, mPackageName);
 
             if (mConnection != null) {
                 // We still need to call unbind even if the service disconnected.
-                mContext.unbindService(mConnection);
+                try {
+                    mContext.unbindService(mConnection);
+                } catch (IllegalArgumentException ie) {
+                    Log.e(this, ie, "Unbind error");
+                }
                 mConnection = null;
             }
             mService = null;
@@ -200,65 +231,67 @@
         }
     }
 
-    private boolean bindService() {
-        String dialerPackage = mDefaultDialerCache
-                .getDefaultDialerApplication(UserHandle.USER_CURRENT);
-        if (TextUtils.isEmpty(dialerPackage)) {
-            Log.i(this, "Default dialer is empty. Not performing call screening.");
-            return false;
+    private void onServiceBound(ICallScreeningService service) {
+        mService = service;
+        try {
+            // Important: Only send a minimal subset of the call to the screening service.
+            mService.screenCall(new CallScreeningAdapter(),
+                    mParcelableCallUtilsConverter.toParcelableCallForScreening(mCall));
+        } catch (RemoteException e) {
+            Log.e(this, e, "Failed to set the call screening adapter.");
+            finishCallScreening();
+        }
+    }
+
+    private boolean isLoggable(ComponentName componentName, boolean shouldAddToCallLog) {
+        if (isCarrierCallScreeningApp(componentName)) {
+            return shouldAddToCallLog;
+        } else if (isDefaultDialer(componentName) || isUserChosenCallScreeningApp(componentName)) {
+            return true;
         }
 
-        Intent intent = new Intent(CallScreeningService.SERVICE_INTERFACE)
-            .setPackage(dialerPackage);
-        List<ResolveInfo> entries = mContext.getPackageManager().queryIntentServicesAsUser(
-                intent, 0, mCallsManager.getCurrentUserHandle().getIdentifier());
-        if (entries.isEmpty()) {
-            Log.i(this, "There are no call screening services installed on this device.");
-            return false;
+        return shouldAddToCallLog;
+    }
+
+    private boolean isCarrierCallScreeningApp(ComponentName componentName) {
+        String carrierCallScreeningApp = null;
+        CarrierConfigManager configManager = (CarrierConfigManager) mContext
+                .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+        PersistableBundle configBundle = configManager.getConfig();
+        if (configBundle != null) {
+            carrierCallScreeningApp = configBundle
+                    .getString(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING);
         }
 
-        ResolveInfo entry = entries.get(0);
-        if (entry.serviceInfo == null) {
-            Log.w(this, "The call screening service has invalid service info");
-            return false;
-        }
-
-        if (entry.serviceInfo.permission == null || !entry.serviceInfo.permission.equals(
-                Manifest.permission.BIND_SCREENING_SERVICE)) {
-            Log.w(this, "CallScreeningService must require BIND_SCREENING_SERVICE permission: " +
-                    entry.serviceInfo.packageName);
-            return false;
-        }
-
-        ComponentName componentName =
-                new ComponentName(entry.serviceInfo.packageName, entry.serviceInfo.name);
-        Log.addEvent(mCall, LogUtils.Events.BIND_SCREENING, componentName);
-        intent.setComponent(componentName);
-        ServiceConnection connection = new CallScreeningServiceConnection();
-        if (mContext.bindServiceAsUser(
-                intent,
-                connection,
-                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
-                UserHandle.CURRENT)) {
-            Log.d(this, "bindService, found service, waiting for it to connect");
-            mConnection = connection;
+        if (!TextUtils.isEmpty(carrierCallScreeningApp) && carrierCallScreeningApp
+                .equals(componentName.flattenToString())) {
             return true;
         }
 
         return false;
     }
 
-    private void onServiceBound(ICallScreeningService service) {
-        mService = service;
-        try {
-            mService.screenCall(new CallScreeningAdapter(),
-                    mParcelableCallUtilsConverter.toParcelableCall(
-                            mCall,
-                            false, /* includeVideoProvider */
-                            mPhoneAccountRegistrar));
-        } catch (RemoteException e) {
-            Log.e(this, e, "Failed to set the call screening adapter.");
-            finishCallScreening();
+    private boolean isDefaultDialer(ComponentName componentName) {
+        String defaultDialer = TelecomManager.from(mContext).getDefaultDialerPackage();
+
+        if (!TextUtils.isEmpty(defaultDialer) && defaultDialer
+                .equals(componentName.getPackageName())) {
+            return true;
         }
+
+        return false;
+    }
+
+    private boolean isUserChosenCallScreeningApp(ComponentName componentName) {
+        String defaultCallScreeningApplication = mSettingsSecureAdapter
+                .getStringForUser(mContext.getContentResolver(),
+                        Settings.Secure.CALL_SCREENING_DEFAULT_COMPONENT, UserHandle.USER_CURRENT);
+
+        if (!TextUtils.isEmpty(defaultCallScreeningApplication) && defaultCallScreeningApplication
+                .equals(componentName.flattenToString())) {
+            return true;
+        }
+
+        return false;
     }
 }
diff --git a/src/com/android/server/telecom/callfiltering/DirectToVoicemailCallFilter.java b/src/com/android/server/telecom/callfiltering/DirectToVoicemailCallFilter.java
index 2ac82dc..3a8ff7d 100644
--- a/src/com/android/server/telecom/callfiltering/DirectToVoicemailCallFilter.java
+++ b/src/com/android/server/telecom/callfiltering/DirectToVoicemailCallFilter.java
@@ -17,6 +17,7 @@
 package com.android.server.telecom.callfiltering;
 
 import android.net.Uri;
+import android.provider.CallLog;
 import android.telecom.Log;
 
 import com.android.internal.telephony.CallerInfo;
@@ -49,7 +50,11 @@
                                         false, // shouldAllowCall
                                         true, // shouldReject
                                         true, // shouldAddToCallLog
-                                        true // shouldShowNotification
+                                        true, // shouldShowNotification
+                                        CallLog.Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL,
+                                        //callBlockReason
+                                        null, //callScreeningAppName
+                                        null // callScreeningComponentName
                                 );
                             } else {
                                 result = new CallFilteringResult(
diff --git a/src/com/android/server/telecom/callredirection/CallRedirectionCallback.java b/src/com/android/server/telecom/callredirection/CallRedirectionCallback.java
new file mode 100644
index 0000000..24ac326
--- /dev/null
+++ b/src/com/android/server/telecom/callredirection/CallRedirectionCallback.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2018 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.callredirection;
+
+import com.android.server.telecom.Call;
+
+public interface CallRedirectionCallback {
+    void onCallRedirectionComplete(Call call);
+}
diff --git a/src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java b/src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java
new file mode 100644
index 0000000..ab91bdc
--- /dev/null
+++ b/src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java
@@ -0,0 +1,430 @@
+/*
+ * Copyright (C) 2018 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.callredirection;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.telecom.CallRedirectionService;
+import android.telecom.GatewayInfo;
+import android.telecom.Log;
+import android.telecom.Logging.Runnable;
+import android.telecom.PhoneAccountHandle;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telecom.ICallRedirectionAdapter;
+import com.android.internal.telecom.ICallRedirectionService;
+import com.android.server.telecom.Call;
+import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.LogUtils;
+import com.android.server.telecom.PhoneAccountRegistrar;
+import com.android.server.telecom.TelecomSystem;
+import com.android.server.telecom.Timeouts;
+
+/**
+ * A single instance of call redirection processor that handles the call redirection with
+ * user-defined {@link CallRedirectionService} and carrier {@link CallRedirectionService} for a
+ * single call.
+ *
+ * A user-defined call redirection will be performed firstly and a carrier call redirection will be
+ * performed after that; there will be a total of two call redirection cycles.
+ *
+ * A call redirection cycle is a cycle:
+ * 1) Telecom requests a call redirection of a call with a specific {@link CallRedirectionService},
+ * 2) Telecom receives the response either from a specific {@link CallRedirectionService} or from
+ * the timeout.
+ *
+ * Telecom should return to {@link CallsManager} at the end of current call redirection
+ * cycle, if
+ * 1) {@link CallRedirectionService} sends {@link CallRedirectionService#cancelCall()} response
+ * before timeout;
+ * or 2) Telecom finishes call redirection with carrier {@link CallRedirectionService}.
+ */
+public class CallRedirectionProcessor implements CallRedirectionCallback {
+
+    private class CallRedirectionAttempt {
+        private final ComponentName mComponentName;
+        private final String mServiceType;
+        private ServiceConnection mConnection;
+        private ICallRedirectionService mService;
+
+        private CallRedirectionAttempt(ComponentName componentName, String serviceType) {
+            mComponentName = componentName;
+            mServiceType = serviceType;
+        }
+
+        private void process() {
+            Intent intent = new Intent(CallRedirectionService.SERVICE_INTERFACE)
+                    .setComponent(mComponentName);
+            ServiceConnection connection = new CallRedirectionServiceConnection();
+            if (mContext.bindServiceAsUser(
+                    intent,
+                    connection,
+                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+                    UserHandle.CURRENT)) {
+                Log.d(this, "bindService, found " + mServiceType + " call redirection service,"
+                        + " waiting for it to connect");
+                mConnection = connection;
+            }
+        }
+
+        private void onServiceBound(ICallRedirectionService service) {
+            mService = service;
+            try {
+                // Telecom does not perform user interactions for carrier call redirection.
+                mService.placeCall(new CallRedirectionAdapter(), mProcessedDestinationUri,
+                        mPhoneAccountHandle, mAllowInteractiveResponse
+                                && mServiceType.equals(SERVICE_TYPE_USER_DEFINED));
+                Log.addEvent(mCall, mServiceType.equals(SERVICE_TYPE_USER_DEFINED)
+                        ? LogUtils.Events.REDIRECTION_SENT_USER
+                        : LogUtils.Events.REDIRECTION_SENT_CARRIER, mComponentName);
+                Log.d(this, "Requested placeCall with [Destination Uri] "
+                        + Log.pii(mProcessedDestinationUri)
+                        + " [phoneAccountHandle]" + mPhoneAccountHandle);
+            } catch (RemoteException e) {
+                Log.e(this, e, "Failed to request with the found " + mServiceType + " call"
+                        + " redirection service");
+                finishCallRedirection();
+            }
+        }
+
+        private void finishCallRedirection() {
+            if (((mServiceType.equals(SERVICE_TYPE_CARRIER)) && mIsCarrierRedirectionPending)
+                || ((mServiceType.equals(SERVICE_TYPE_USER_DEFINED))
+                    && mIsUserDefinedRedirectionPending)) {
+                if (mConnection != null) {
+                    // We still need to call unbind even if the service disconnected.
+                    mContext.unbindService(mConnection);
+                    mConnection = null;
+                }
+                mService = null;
+                onCallRedirectionComplete(mCall);
+            }
+        }
+
+        private class CallRedirectionServiceConnection implements ServiceConnection {
+            @Override
+            public void onServiceConnected(ComponentName componentName, IBinder service) {
+                Log.startSession("CRSC.oSC");
+                try {
+                    synchronized (mTelecomLock) {
+                        Log.addEvent(mCall, mServiceType.equals(SERVICE_TYPE_USER_DEFINED)
+                                ? LogUtils.Events.REDIRECTION_BOUND_USER
+                                : LogUtils.Events.REDIRECTION_BOUND_CARRIER, componentName);
+                        onServiceBound(ICallRedirectionService.Stub.asInterface(service));
+                    }
+                } finally {
+                    Log.endSession();
+                }
+            }
+
+            @Override
+            public void onServiceDisconnected(ComponentName componentName) {
+                Log.startSession("CRSC.oSD");
+                try {
+                    synchronized (mTelecomLock) {
+                        finishCallRedirection();
+                    }
+                } finally {
+                    Log.endSession();
+                }
+            }
+        }
+
+        private class CallRedirectionAdapter extends ICallRedirectionAdapter.Stub {
+            @Override
+            public void cancelCall() {
+                Log.startSession("CRA.cC");
+                long token = Binder.clearCallingIdentity();
+                try {
+                    synchronized (mTelecomLock) {
+                        Log.d(this, "Received cancelCall from " +  mServiceType + " call"
+                                + " redirection service");
+                        mShouldCancelCall = true;
+                        finishCallRedirection();
+                    }
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                    Log.endSession();
+                }
+            }
+
+            @Override
+            public void placeCallUnmodified() {
+                Log.startSession("CRA.pCU");
+                long token = Binder.clearCallingIdentity();
+                try {
+                    synchronized (mTelecomLock) {
+                        Log.d(this, "Received placeCallUnmodified from " +  mServiceType + " call"
+                                + " redirection service");
+                        finishCallRedirection();
+                    }
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                    Log.endSession();
+                }
+            }
+
+            @Override
+            public void redirectCall(Uri gatewayUri, PhoneAccountHandle targetPhoneAccount,
+                                     boolean confirmFirst) {
+                Log.startSession("CRA.rC");
+                long token = Binder.clearCallingIdentity();
+                try {
+                    synchronized (mTelecomLock) {
+                        mRedirectionGatewayInfo = mCallRedirectionProcessorHelper
+                                .getGatewayInfoFromGatewayUri(mComponentName.getPackageName(),
+                                        gatewayUri, mDestinationUri);
+                        mPhoneAccountHandle = targetPhoneAccount;
+                        // If carrier redirects call, we should skip to notify users about
+                        // the user-defined call redirection service.
+                        mUiAction = (confirmFirst && mServiceType.equals(SERVICE_TYPE_USER_DEFINED)
+                                && mAllowInteractiveResponse)
+                                ? UI_TYPE_USER_DEFINED_ASK_FOR_CONFIRM : UI_TYPE_NO_ACTION;
+                        Log.d(this, "Received redirectCall with [gatewayUri]"
+                                + Log.pii(gatewayUri) + " [phoneAccountHandle]"
+                                + mPhoneAccountHandle + "[confirmFirst]" + confirmFirst + " from "
+                                + mServiceType + " call redirection service");
+                        finishCallRedirection();
+                    }
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                    Log.endSession();
+                }
+            }
+        }
+    }
+
+    private final Context mContext;
+    private final CallsManager mCallsManager;
+    private final Call mCall;
+    private final boolean mAllowInteractiveResponse;
+    private GatewayInfo mRedirectionGatewayInfo;
+    private final boolean mSpeakerphoneOn;
+    private final int mVideoState;
+    private final Timeouts.Adapter mTimeoutsAdapter;
+    private final TelecomSystem.SyncRoot mTelecomLock;
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+
+    private CallRedirectionAttempt mAttempt;
+    private CallRedirectionProcessorHelper mCallRedirectionProcessorHelper;
+
+    public static final String SERVICE_TYPE_CARRIER = "carrier";
+    public static final String SERVICE_TYPE_USER_DEFINED = "user_defined";
+    public static final String UI_TYPE_NO_ACTION = "no_action";
+    public static final String UI_TYPE_USER_DEFINED_TIMEOUT = "user_defined_timeout";
+    public static final String UI_TYPE_USER_DEFINED_ASK_FOR_CONFIRM
+            = "user_defined_ask_for_confirm";
+
+    private PhoneAccountHandle mPhoneAccountHandle;
+    private Uri mDestinationUri;
+    /**
+     * Try to send the implemented service with processed destination uri by formatting it to E.164
+     * and removing post dial digits.
+     */
+    private Uri mProcessedDestinationUri;
+
+    /**
+     * Indicates if Telecom should cancel the call when the whole call redirection finishes.
+     */
+    private boolean mShouldCancelCall = false;
+    /**
+     * Indicates Telecom should handle different types of UI if need.
+     */
+    private String mUiAction = UI_TYPE_NO_ACTION;
+    /**
+     * Indicates if Telecom is waiting for a callback from a user-defined
+     * {@link CallRedirectionService}.
+     */
+    private boolean mIsUserDefinedRedirectionPending = false;
+    /**
+     * Indicates if Telecom is waiting for a callback from a carrier
+     * {@link CallRedirectionService}.
+     */
+    private boolean mIsCarrierRedirectionPending = false;
+
+    public CallRedirectionProcessor(
+            Context context,
+            CallsManager callsManager,
+            Call call,
+            Uri handle,
+            PhoneAccountRegistrar phoneAccountRegistrar,
+            GatewayInfo gatewayInfo,
+            boolean speakerphoneOn,
+            int videoState) {
+        mContext = context;
+        mCallsManager = callsManager;
+        mCall = call;
+        mDestinationUri = handle;
+        mPhoneAccountHandle = call.getTargetPhoneAccount();
+        mRedirectionGatewayInfo = gatewayInfo;
+        mSpeakerphoneOn = speakerphoneOn;
+        mVideoState = videoState;
+        mTimeoutsAdapter = callsManager.getTimeoutsAdapter();
+        mTelecomLock = callsManager.getLock();
+        /**
+         * The current rule to decide whether the implemented {@link CallRedirectionService} should
+         * allow interactive responses with users is only based on whether it is in car mode.
+         */
+        mAllowInteractiveResponse = !callsManager.getSystemStateHelper().isCarMode();
+        mCallRedirectionProcessorHelper = new CallRedirectionProcessorHelper(
+                context, callsManager, phoneAccountRegistrar);
+        mProcessedDestinationUri = mCallRedirectionProcessorHelper.formatNumberForRedirection(
+                mDestinationUri);
+    }
+
+    @Override
+    public void onCallRedirectionComplete(Call call) {
+        // synchronized on mTelecomLock to enter into Telecom.
+        mHandler.post(new Runnable("CRP.oCRC", mTelecomLock) {
+            @Override
+            public void loggedRun() {
+                if (mIsUserDefinedRedirectionPending) {
+                    Log.addEvent(mCall, LogUtils.Events.REDIRECTION_COMPLETED_USER);
+                    mIsUserDefinedRedirectionPending = false;
+                    if (mShouldCancelCall) {
+                        mCallsManager.onCallRedirectionComplete(mCall, mDestinationUri,
+                                mPhoneAccountHandle, mRedirectionGatewayInfo, mSpeakerphoneOn,
+                                mVideoState, mShouldCancelCall, mUiAction);
+                    } else {
+                        performCarrierCallRedirection();
+                    }
+                }
+                if (mIsCarrierRedirectionPending) {
+                    Log.addEvent(mCall, LogUtils.Events.REDIRECTION_COMPLETED_CARRIER);
+                    mIsCarrierRedirectionPending = false;
+                    mCallsManager.onCallRedirectionComplete(mCall, mDestinationUri,
+                            mPhoneAccountHandle, mRedirectionGatewayInfo, mSpeakerphoneOn,
+                            mVideoState, mShouldCancelCall, mUiAction);
+                }
+            }
+        }.prepare());
+    }
+
+    /**
+     * The entry to perform call redirection of the call from (@link CallsManager)
+     */
+    public void performCallRedirection() {
+        // If the Gateway Info is set with intent, only request with carrier call redirection.
+        if (mRedirectionGatewayInfo != null) {
+            performCarrierCallRedirection();
+        } else {
+            performUserDefinedCallRedirection();
+        }
+    }
+
+    private void performUserDefinedCallRedirection() {
+        Log.d(this, "performUserDefinedCallRedirection");
+        ComponentName componentName =
+                mCallRedirectionProcessorHelper.getUserDefinedCallRedirectionService();
+        if (componentName != null) {
+            mAttempt = new CallRedirectionAttempt(componentName, SERVICE_TYPE_USER_DEFINED);
+            mAttempt.process();
+            mIsUserDefinedRedirectionPending = true;
+            processTimeoutForCallRedirection(SERVICE_TYPE_USER_DEFINED);
+        } else {
+            Log.i(this, "There are no user-defined call redirection services installed on this"
+                    + " device.");
+            performCarrierCallRedirection();
+        }
+    }
+
+    private void performCarrierCallRedirection() {
+        Log.d(this, "performCarrierCallRedirection");
+        ComponentName componentName =
+                mCallRedirectionProcessorHelper.getCarrierCallRedirectionService(
+                        mPhoneAccountHandle);
+        if (componentName != null) {
+            mAttempt = new CallRedirectionAttempt(componentName, SERVICE_TYPE_CARRIER);
+            mAttempt.process();
+            mIsCarrierRedirectionPending = true;
+            processTimeoutForCallRedirection(SERVICE_TYPE_CARRIER);
+        } else {
+            Log.i(this, "There are no carrier call redirection services installed on this"
+                    + " device.");
+            mCallsManager.onCallRedirectionComplete(mCall, mDestinationUri,
+                    mPhoneAccountHandle, mRedirectionGatewayInfo, mSpeakerphoneOn, mVideoState,
+                    mShouldCancelCall, mUiAction);
+        }
+    }
+
+    private void processTimeoutForCallRedirection(String serviceType) {
+        long timeout = serviceType.equals(SERVICE_TYPE_USER_DEFINED) ?
+            mTimeoutsAdapter.getUserDefinedCallRedirectionTimeoutMillis(
+                mContext.getContentResolver()) : mTimeoutsAdapter
+            .getCarrierCallRedirectionTimeoutMillis(mContext.getContentResolver());
+
+        mHandler.postDelayed(new Runnable("CRP.pTFCR", null) {
+            @Override
+            public void loggedRun() {
+                boolean isCurrentRedirectionPending =
+                        serviceType.equals(SERVICE_TYPE_USER_DEFINED) ?
+                                mIsUserDefinedRedirectionPending : mIsCarrierRedirectionPending;
+                if (isCurrentRedirectionPending) {
+                    Log.i(this, serviceType + " call redirection has timed out.");
+                    Log.addEvent(mCall, serviceType.equals(SERVICE_TYPE_USER_DEFINED)
+                            ? LogUtils.Events.REDIRECTION_TIMED_OUT_USER
+                            : LogUtils.Events.REDIRECTION_TIMED_OUT_CARRIER);
+                    if (serviceType.equals(SERVICE_TYPE_USER_DEFINED)) {
+                        mUiAction = UI_TYPE_USER_DEFINED_TIMEOUT;
+                        mShouldCancelCall = true;
+                    }
+                    onCallRedirectionComplete(mCall);
+                }
+            }
+        }.prepare(), timeout);
+    }
+
+    /**
+     * Checks if Telecom can make call redirection with any available call redirection service.
+     *
+     * @return {@code true} if it can; {@code false} otherwise.
+     */
+    public boolean canMakeCallRedirectionWithService() {
+        boolean canMakeCallRedirectionWithService =
+                mCallRedirectionProcessorHelper.getUserDefinedCallRedirectionService() != null
+                        || mCallRedirectionProcessorHelper.getCarrierCallRedirectionService(
+                                mPhoneAccountHandle) != null;
+        Log.i(this, "Can make call redirection with any available service: "
+                + canMakeCallRedirectionWithService);
+        return canMakeCallRedirectionWithService;
+    }
+
+    /**
+     * Returns the handler, for testing purposes.
+     */
+    @VisibleForTesting
+    public Handler getHandler() {
+        return mHandler;
+    }
+
+    /**
+     * Set CallRedirectionProcessorHelper for testing purposes.
+     */
+    @VisibleForTesting
+    public void setCallRedirectionServiceHelper(
+            CallRedirectionProcessorHelper callRedirectionProcessorHelper) {
+        mCallRedirectionProcessorHelper = callRedirectionProcessorHelper;
+    }
+}
diff --git a/src/com/android/server/telecom/callredirection/CallRedirectionProcessorHelper.java b/src/com/android/server/telecom/callredirection/CallRedirectionProcessorHelper.java
new file mode 100644
index 0000000..12c8c57
--- /dev/null
+++ b/src/com/android/server/telecom/callredirection/CallRedirectionProcessorHelper.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2018 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.callredirection;
+
+import android.Manifest;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.PersistableBundle;
+import android.telecom.CallRedirectionService;
+import android.telecom.GatewayInfo;
+import android.telecom.Log;
+import android.telecom.PhoneAccountHandle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.PhoneAccountRegistrar;
+
+import java.util.List;
+
+public class CallRedirectionProcessorHelper {
+
+    private final Context mContext;
+    private final CallsManager mCallsManager;
+    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
+
+    public CallRedirectionProcessorHelper(
+            Context context,
+            CallsManager callsManager,
+            PhoneAccountRegistrar phoneAccountRegistrar) {
+        mContext = context;
+        mCallsManager = callsManager;
+        mPhoneAccountRegistrar = phoneAccountRegistrar;
+    }
+
+    @VisibleForTesting
+    public ComponentName getUserDefinedCallRedirectionService() {
+        String packageName = mCallsManager.getRoleManagerAdapter().getDefaultCallRedirectionApp();
+        if (TextUtils.isEmpty(packageName)) {
+            Log.i(this, "PackageName is empty. Not performing user-defined call redirection.");
+            return null;
+        }
+        Intent intent = new Intent(CallRedirectionService.SERVICE_INTERFACE)
+                .setPackage(packageName);
+        return getComponentName(intent, CallRedirectionProcessor.SERVICE_TYPE_USER_DEFINED);
+    }
+
+    @VisibleForTesting
+    public ComponentName getCarrierCallRedirectionService(
+            PhoneAccountHandle targetPhoneAccountHandle) {
+        CarrierConfigManager configManager = (CarrierConfigManager)
+                mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+        if (configManager == null) {
+            Log.i(this, "Cannot get CarrierConfigManager.");
+            return null;
+        }
+        PersistableBundle pb = configManager.getConfigForSubId(mPhoneAccountRegistrar
+                .getSubscriptionIdForPhoneAccount(targetPhoneAccountHandle));
+        if (pb == null) {
+            Log.i(this, "Cannot get PersistableBundle.");
+            return null;
+        }
+        String componentNameString = pb.getString(
+                CarrierConfigManager.KEY_CALL_REDIRECTION_SERVICE_COMPONENT_NAME_STRING);
+        if (componentNameString == null) {
+            Log.i(this, "Cannot get carrier componentNameString.");
+            return null;
+        }
+        ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
+        if (componentName == null) {
+            Log.w(this, "ComponentName is null from string: " + componentNameString);
+            return null;
+        }
+        Intent intent = new Intent(CallRedirectionService.SERVICE_INTERFACE);
+        intent.setComponent(componentName);
+        return getComponentName(intent, CallRedirectionProcessor.SERVICE_TYPE_CARRIER);
+    }
+
+    protected ComponentName getComponentName(Intent intent, String serviceType) {
+        List<ResolveInfo> entries = mContext.getPackageManager().queryIntentServicesAsUser(
+                intent, 0, mCallsManager.getCurrentUserHandle().getIdentifier());
+        if (entries.isEmpty()) {
+            Log.i(this, "There are no " + serviceType + " call redirection services installed" +
+                    " on this device.");
+            return null;
+        } else if (entries.size() != 1) {
+            Log.i(this, "There are multiple " + serviceType + " call redirection services" +
+                    " installed on this device.");
+            return null;
+        }
+        ResolveInfo entry = entries.get(0);
+        if (entry.serviceInfo == null) {
+            Log.w(this, "The " + serviceType + " call redirection service has invalid" +
+                    " service info");
+            return null;
+        }
+        if (entry.serviceInfo.permission == null || !entry.serviceInfo.permission.equals(
+                Manifest.permission.BIND_CALL_REDIRECTION_SERVICE)) {
+            Log.w(this, "CallRedirectionService must require BIND_CALL_REDIRECTION_SERVICE"
+                    + " permission: " + entry.serviceInfo.packageName);
+            return null;
+        }
+        return new ComponentName(entry.serviceInfo.packageName, entry.serviceInfo.name);
+    }
+
+    /**
+     * Format Number to E164, and remove post dial digits.
+     */
+    protected Uri formatNumberForRedirection(Uri handle) {
+        return removePostDialDigits(formatNumberToE164(handle));
+    }
+
+    protected Uri formatNumberToE164(Uri handle) {
+        String number = handle.getSchemeSpecificPart();
+
+        // Format number to E164
+        TelephonyManager tm = (TelephonyManager) mContext.getSystemService(
+                Context.TELEPHONY_SERVICE);
+        Log.i(this, "formatNumberToE164, original number: " + Log.pii(number));
+        number = PhoneNumberUtils.formatNumberToE164(number, tm.getNetworkCountryIso());
+        Log.i(this, "formatNumberToE164, formatted E164 number: " + Log.pii(number));
+        // if there is a problem with parsing the phone number, formatNumberToE164 will return null;
+        // and should just use the original number in that case.
+        if (number == null) {
+            return handle;
+        } else {
+            return Uri.fromParts(handle.getScheme(), number, null);
+        }
+    }
+
+    protected Uri removePostDialDigits(Uri handle) {
+        String number = handle.getSchemeSpecificPart();
+
+        // Extract the post dial portion
+        number = PhoneNumberUtils.extractNetworkPortionAlt(number);
+        Log.i(this, "removePostDialDigits, number after being extracted post dial digits: "
+                + Log.pii(number));
+        // if there is a problem with parsing the phone number, removePostDialDigits will return
+        // null; and should just use the original number in that case.
+        if (number == null) {
+            return handle;
+        } else {
+            return Uri.fromParts(handle.getScheme(), number, null);
+        }
+    }
+
+    protected GatewayInfo getGatewayInfoFromGatewayUri(
+            String gatewayPackageName, Uri gatewayUri, Uri destinationUri) {
+        if (!TextUtils.isEmpty(gatewayPackageName) && gatewayUri != null) {
+            return new GatewayInfo(gatewayPackageName, gatewayUri, destinationUri);
+        }
+        return null;
+    }
+}
diff --git a/src/com/android/server/telecom/components/PhoneAccountBroadcastReceiver.java b/src/com/android/server/telecom/components/AppUninstallBroadcastReceiver.java
similarity index 68%
rename from src/com/android/server/telecom/components/PhoneAccountBroadcastReceiver.java
rename to src/com/android/server/telecom/components/AppUninstallBroadcastReceiver.java
index 7737cd8..3a0d517 100644
--- a/src/com/android/server/telecom/components/PhoneAccountBroadcastReceiver.java
+++ b/src/com/android/server/telecom/components/AppUninstallBroadcastReceiver.java
@@ -19,9 +19,12 @@
 import com.android.server.telecom.PhoneAccountRegistrar;
 
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
+import android.os.UserHandle;
+import android.provider.Settings;
 import android.telecom.TelecomManager;
 
 import java.lang.String;
@@ -30,14 +33,20 @@
  * Captures {@code android.intent.action.ACTION_PACKAGE_FULLY_REMOVED} intents and triggers the
  * removal of associated {@link android.telecom.PhoneAccount}s via the
  * {@link com.android.telecom.PhoneAccountRegistrar}.
+ *
  * Note: This class listens for the {@code PACKAGE_FULLY_REMOVED} intent rather than
  * {@code PACKAGE_REMOVED} as {@code PACKAGE_REMOVED} is triggered on re-installation of the same
  * package, where {@code PACKAGE_FULLY_REMOVED} is triggered only when an application is completely
- * uninstalled.  This is desirable as we do not wish to un-register all
+ * uninstalled.
+ *
+ * This is desirable as we do not wish to un-register all
  * {@link android.telecom.PhoneAccount}s associated with a package being re-installed to ensure
  * the enabled state of the accounts is retained.
+ *
+ * When default call screening application is removed, set
+ * {@link Settings.Secure.CALL_SCREENING_DEFAULT_APPLICATION} as null into provider.
  */
-public class PhoneAccountBroadcastReceiver extends BroadcastReceiver {
+public class AppUninstallBroadcastReceiver extends BroadcastReceiver {
     /**
      * Receives the intents the class is configured to received.
      *
@@ -54,6 +63,7 @@
 
             String packageName = uri.getSchemeSpecificPart();
             handlePackageRemoved(context, packageName);
+            handleUninstallOfCallScreeningService(context, packageName);
         }
     }
 
@@ -69,4 +79,20 @@
             telecomManager.clearAccountsForPackage(packageName);
         }
     }
+
+    private void handleUninstallOfCallScreeningService(Context context, String packageName) {
+        ComponentName componentName = null;
+        String defaultCallScreeningApp = Settings.Secure
+            .getStringForUser(context.getContentResolver(),
+                Settings.Secure.CALL_SCREENING_DEFAULT_COMPONENT, UserHandle.USER_CURRENT);
+
+        if (defaultCallScreeningApp != null) {
+            componentName = ComponentName.unflattenFromString(defaultCallScreeningApp);
+        }
+
+        if (componentName != null && componentName.getPackageName().equals(packageName)) {
+            Settings.Secure.putStringForUser(context.getContentResolver(),
+                Settings.Secure.CALL_SCREENING_DEFAULT_COMPONENT, null, UserHandle.USER_CURRENT);
+        }
+    }
 }
diff --git a/src/com/android/server/telecom/components/PrimaryCallReceiver.java b/src/com/android/server/telecom/components/PrimaryCallReceiver.java
deleted file mode 100644
index f19a243..0000000
--- a/src/com/android/server/telecom/components/PrimaryCallReceiver.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.android.server.telecom.components;
-
-import com.android.server.telecom.TelecomSystem;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.telecom.Log;
-
-/**
- * Single point of entry for all outgoing and incoming calls. {@link UserCallIntentProcessor} serves
- * as a trampoline that captures call intents for individual users and forwards it to
- * the {@link PrimaryCallReceiver} which interacts with the rest of Telecom, both of which run only as
- * the primary user.
- */
-public class PrimaryCallReceiver extends BroadcastReceiver implements TelecomSystem.Component {
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        Log.startSession("PCR.oR");
-        synchronized (getTelecomSystem().getLock()) {
-            getTelecomSystem().getCallIntentProcessor().processIntent(intent);
-        }
-        Log.endSession();
-    }
-
-    @Override
-    public TelecomSystem getTelecomSystem() {
-        return TelecomSystem.getInstance();
-    }
-}
diff --git a/src/com/android/server/telecom/components/TelecomService.java b/src/com/android/server/telecom/components/TelecomService.java
index 9a09636..900bafa 100644
--- a/src/com/android/server/telecom/components/TelecomService.java
+++ b/src/com/android/server/telecom/components/TelecomService.java
@@ -33,6 +33,7 @@
 import com.android.server.telecom.AsyncRingtonePlayer;
 import com.android.server.telecom.BluetoothAdapterProxy;
 import com.android.server.telecom.BluetoothPhoneServiceImpl;
+import com.android.server.telecom.CallAudioRouteStateMachine;
 import com.android.server.telecom.CallerInfoAsyncQueryFactory;
 import com.android.server.telecom.CallsManager;
 import com.android.server.telecom.ClockProxy;
@@ -49,6 +50,8 @@
 import com.android.server.telecom.InCallWakeLockController;
 import com.android.server.telecom.ProximitySensorManager;
 import com.android.server.telecom.R;
+import com.android.server.telecom.RoleManagerAdapter;
+import com.android.server.telecom.RoleManagerAdapterImpl;
 import com.android.server.telecom.TelecomSystem;
 import com.android.server.telecom.TelecomWakeLock;
 import com.android.server.telecom.Timeouts;
@@ -167,20 +170,13 @@
                                             phoneAccountRegistrar);
                                 }
                             },
-                            new ConnectionServiceFocusManager
-                                    .ConnectionServiceFocusManagerFactory() {
-                                @Override
-                                public ConnectionServiceFocusManager create(
-                                        ConnectionServiceFocusManager.CallsManagerRequester requester,
-                                        Looper looper) {
-                                    return new ConnectionServiceFocusManager(requester, looper);
-                                }
-                            },
+                            ConnectionServiceFocusManager::new,
                             new Timeouts.Adapter(),
                             new AsyncRingtonePlayer(shouldPauseBetweenRingtoneRepeat),
                             new PhoneNumberUtilsAdapterImpl(),
                             new IncomingCallNotifier(context),
                             ToneGenerator::new,
+                            new CallAudioRouteStateMachine.Factory(),
                             new ClockProxy() {
                                 @Override
                                 public long currentTimeMillis() {
@@ -191,7 +187,8 @@
                                 public long elapsedRealtime() {
                                     return SystemClock.elapsedRealtime();
                                 }
-                            }));
+                            },
+                            new RoleManagerAdapterImpl(context)));
         }
         if (BluetoothAdapter.getDefaultAdapter() != null) {
             context.startService(new Intent(context, BluetoothPhoneService.class));
diff --git a/src/com/android/server/telecom/components/UserCallIntentProcessor.java b/src/com/android/server/telecom/components/UserCallIntentProcessor.java
index 0c8525f..ae4a7d8 100644
--- a/src/com/android/server/telecom/components/UserCallIntentProcessor.java
+++ b/src/com/android/server/telecom/components/UserCallIntentProcessor.java
@@ -159,7 +159,7 @@
         // Save the user handle of current user before forwarding the intent to primary user.
         intent.putExtra(CallIntentProcessor.KEY_INITIATING_USER, mUserHandle);
 
-        sendIntentToDestination(intent, isLocalInvocation);
+        sendIntentToDestination(intent, isLocalInvocation, callingPackageName);
     }
 
     private boolean isDefaultOrSystemDialer(String callingPackageName) {
@@ -189,27 +189,29 @@
     }
 
     /**
-     * Potentially trampolines the intent to the broadcast receiver that runs only as the primary
-     * user.  If the caller is local to the Telecom service, we send the intent to Telecom without
-     * rebroadcasting it.
+     * Potentially trampolines the intent to Telecom via TelecomServiceImpl.
+     * If the caller is local to the Telecom service, we send the intent to Telecom without
+     * sending it through TelecomServiceImpl.
      */
-    private boolean sendIntentToDestination(Intent intent, boolean isLocalInvocation) {
+    private boolean sendIntentToDestination(Intent intent, boolean isLocalInvocation,
+            String callingPackage) {
         intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, false);
         intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-        intent.setClass(mContext, PrimaryCallReceiver.class);
         if (isLocalInvocation) {
             // We are invoking this from TelecomServiceImpl, so TelecomSystem is available.  Don't
             // bother trampolining the intent, just sent it directly to the call intent processor.
             // TODO: We should not be using an intent here; this whole flows needs cleanup.
             Log.i(this, "sendIntentToDestination: send intent to Telecom directly.");
             synchronized (TelecomSystem.getInstance().getLock()) {
-                TelecomSystem.getInstance().getCallIntentProcessor().processIntent(intent);
+                TelecomSystem.getInstance().getCallIntentProcessor().processIntent(intent,
+                        callingPackage);
             }
         } else {
             // We're calling from the UserCallActivity, so the TelecomSystem is not in the same
             // process; we need to trampoline to TelecomSystem in the system server process.
             Log.i(this, "sendIntentToDestination: trampoline to Telecom.");
-            mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
+            TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
+            tm.handleCallIntent(intent);
         }
         return true;
     }
diff --git a/src/com/android/server/telecom/settings/BlockedNumbersActivity.java b/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
index ae7e661..1593e23 100644
--- a/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
+++ b/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
@@ -121,6 +121,7 @@
 
         mAddButton = (TextView) findViewById(R.id.add_blocked);
         mAddButton.setOnClickListener(this);
+        mAddButton.setContentDescription(getText(R.string.block_number));
 
         mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
         String[] fromColumns = {BlockedNumberContract.BlockedNumbers.COLUMN_ORIGINAL_NUMBER};
diff --git a/src/com/android/server/telecom/settings/BlockedNumbersUtil.java b/src/com/android/server/telecom/settings/BlockedNumbersUtil.java
index 4f45720..5acfe64 100644
--- a/src/com/android/server/telecom/settings/BlockedNumbersUtil.java
+++ b/src/com/android/server/telecom/settings/BlockedNumbersUtil.java
@@ -33,6 +33,7 @@
 import android.widget.Toast;
 
 import com.android.server.telecom.R;
+import com.android.server.telecom.SystemSettingsUtil;
 import com.android.server.telecom.ui.NotificationChannelManager;
 
 import java.util.Locale;
@@ -134,7 +135,8 @@
             carrierConfig = configManager.getDefaultConfig();
         }
         return carrierConfig.getBoolean(
-                CarrierConfigManager.KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL);
+                CarrierConfigManager.KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL)
+                || new SystemSettingsUtil().isEnhancedCallBlockingEnabled(context);
     }
 
     /**
diff --git a/src/com/android/server/telecom/settings/EnhancedCallBlockingFragment.java b/src/com/android/server/telecom/settings/EnhancedCallBlockingFragment.java
index 219c3e9..ecc019f 100644
--- a/src/com/android/server/telecom/settings/EnhancedCallBlockingFragment.java
+++ b/src/com/android/server/telecom/settings/EnhancedCallBlockingFragment.java
@@ -16,12 +16,17 @@
 
 package com.android.server.telecom.settings;
 
+import android.content.Context;
 import android.os.Bundle;
+import android.os.PersistableBundle;
 import android.preference.Preference;
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceScreen;
 import android.preference.SwitchPreference;
 import android.provider.BlockedNumberContract.SystemContract;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telecom.Log;
 import android.view.LayoutInflater;
 import android.view.MenuItem;
 import android.view.View;
@@ -31,16 +36,64 @@
 
 public class EnhancedCallBlockingFragment extends PreferenceFragment
         implements Preference.OnPreferenceChangeListener {
+    private static final String BLOCK_NUMBERS_NOT_IN_CONTACTS_KEY =
+            "block_numbers_not_in_contacts_setting";
+    private static final String BLOCK_RESTRICTED_NUMBERS_KEY =
+            "block_private_number_calls_setting";
+    private static final String BLOCK_UNKNOWN_NUMBERS_KEY =
+            "block_unknown_calls_setting";
+    private boolean mIsCombiningRestrictedAndUnknownOption = false;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         addPreferencesFromResource(R.xml.enhanced_call_blocking_settings);
 
+        maybeConfigureCallBlockingOptions();
+
         setOnPreferenceChangeListener(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED);
         setOnPreferenceChangeListener(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PRIVATE);
         setOnPreferenceChangeListener(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE);
         setOnPreferenceChangeListener(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNKNOWN);
+        if (!showPayPhoneBlocking()) {
+            Preference payPhoneOption = getPreferenceScreen().findPreference(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE);
+            getPreferenceScreen().removePreference(payPhoneOption);
+        }
+    }
+
+    private boolean showPayPhoneBlocking() {
+        CarrierConfigManager configManager =
+                (CarrierConfigManager) getContext()
+                        .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+        if (configManager == null) {
+            return false;
+        }
+
+        int subId = SubscriptionManager.getDefaultVoiceSubscriptionId();
+        PersistableBundle b = configManager.getConfigForSubId(subId);
+        if (b == null) {
+            return false;
+        }
+        return b.getBoolean(CarrierConfigManager.KEY_SHOW_BLOCKING_PAY_PHONE_OPTION_BOOL);
+    }
+
+    private void maybeConfigureCallBlockingOptions() {
+        PreferenceScreen screen = getPreferenceScreen();
+        boolean isShowingNotInContactsOption =
+                getResources().getBoolean(R.bool.show_option_to_block_callers_not_in_contacts);
+        if (!isShowingNotInContactsOption) {
+            Preference pref = findPreference(BLOCK_NUMBERS_NOT_IN_CONTACTS_KEY);
+            screen.removePreference(pref);
+            Log.i(this, "onCreate: removed block not in contacts preference.");
+        }
+
+        mIsCombiningRestrictedAndUnknownOption = getResources().getBoolean(
+                        R.bool.combine_options_to_block_restricted_and_unknown_callers);
+        if (mIsCombiningRestrictedAndUnknownOption) {
+            Preference pref = findPreference(BLOCK_RESTRICTED_NUMBERS_KEY);
+            screen.removePreference(pref);
+            Log.i(this, "onCreate: removed block restricted preference.");
+        }
     }
 
     /**
@@ -59,7 +112,9 @@
 
         updateEnhancedBlockPref(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED);
         updateEnhancedBlockPref(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PRIVATE);
-        updateEnhancedBlockPref(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE);
+        if (showPayPhoneBlocking()) {
+            updateEnhancedBlockPref(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE);
+        }
         updateEnhancedBlockPref(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNKNOWN);
     }
 
@@ -75,6 +130,13 @@
 
     @Override
     public boolean onPreferenceChange(Preference preference, Object objValue) {
+        if (mIsCombiningRestrictedAndUnknownOption
+                && preference.getKey().equals(BLOCK_UNKNOWN_NUMBERS_KEY)) {
+            Log.i(this, "onPreferenceChange: changing %s and %s to %b",
+                    preference.getKey(), BLOCK_RESTRICTED_NUMBERS_KEY, (boolean) objValue);
+            BlockedNumbersUtil.setEnhancedBlockSetting(getActivity(), BLOCK_RESTRICTED_NUMBERS_KEY,
+                    (boolean) objValue);
+        }
         BlockedNumbersUtil.setEnhancedBlockSetting(getActivity(), preference.getKey(),
                 (boolean) objValue);
         return true;
diff --git a/src/com/android/server/telecom/ui/CallRedirectionConfirmDialogActivity.java b/src/com/android/server/telecom/ui/CallRedirectionConfirmDialogActivity.java
new file mode 100644
index 0000000..32b0960
--- /dev/null
+++ b/src/com/android/server/telecom/ui/CallRedirectionConfirmDialogActivity.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2019 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.ui;
+
+import com.android.server.telecom.R;
+import com.android.server.telecom.TelecomBroadcastIntentProcessor;
+import com.android.server.telecom.components.TelecomBroadcastReceiver;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import android.telecom.Log;
+import android.view.LayoutInflater;
+import android.view.View.OnClickListener;
+import android.view.View;
+import android.widget.Button;
+
+/**
+ * Dialog activity used when there is an ongoing call redirected by the call redirection service.
+ * The dialog prompts the user to see if they want to place the redirected outgoing call.
+ */
+public class CallRedirectionConfirmDialogActivity extends Activity {
+    public static final String EXTRA_REDIRECTION_OUTGOING_CALL_ID =
+            "android.telecom.extra.REDIRECTION_OUTGOING_CALL_ID";
+    public static final String EXTRA_REDIRECTION_APP_NAME =
+            "android.telecom.extra.REDIRECTION_APP_NAME";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.i(this, "CallRedirectionConfirmDialogActivity onCreate.");
+        final CharSequence redirectionAppName = getIntent().getStringExtra(
+                EXTRA_REDIRECTION_APP_NAME);
+        showDialog(redirectionAppName);
+    }
+
+    private void showDialog(final CharSequence redirectionAppName) {
+        Log.i(this, "showDialog: confirming redirection with %s", redirectionAppName);
+
+        final AlertDialog confirmDialog = new AlertDialog.Builder(this).create();
+        LayoutInflater layoutInflater = LayoutInflater.from(this);
+        View dialogView = layoutInflater.inflate(R.layout.call_redirection_confirm_dialog, null);
+
+        Button buttonFirstLine = (Button) dialogView.findViewById(R.id.buttonFirstLine);
+        buttonFirstLine.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Intent proceedWithoutRedirectedCall = new Intent(
+                        TelecomBroadcastIntentProcessor.ACTION_PLACE_UNREDIRECTED_CALL,
+                        null, CallRedirectionConfirmDialogActivity.this,
+                        TelecomBroadcastReceiver.class);
+                proceedWithoutRedirectedCall.putExtra(EXTRA_REDIRECTION_OUTGOING_CALL_ID,
+                        getIntent().getStringExtra(EXTRA_REDIRECTION_OUTGOING_CALL_ID));
+                sendBroadcast(proceedWithoutRedirectedCall);
+                confirmDialog.dismiss();
+                finish();
+            }
+        });
+
+        Button buttonSecondLine = (Button) dialogView.findViewById(R.id.buttonSecondLine);
+        buttonSecondLine.setText(getString(R.string.alert_place_outgoing_call_with_redirection,
+                redirectionAppName));
+        buttonSecondLine.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Intent proceedWithRedirectedCall = new Intent(
+                        TelecomBroadcastIntentProcessor
+                                .ACTION_PLACE_REDIRECTED_CALL, null,
+                        CallRedirectionConfirmDialogActivity.this,
+                        TelecomBroadcastReceiver.class);
+                proceedWithRedirectedCall.putExtra(EXTRA_REDIRECTION_OUTGOING_CALL_ID,
+                        getIntent().getStringExtra(EXTRA_REDIRECTION_OUTGOING_CALL_ID));
+                sendBroadcast(proceedWithRedirectedCall);
+                confirmDialog.dismiss();
+                finish();
+            }
+        });
+
+        Button buttonThirdLine = (Button) dialogView.findViewById(R.id.buttonThirdLine);
+        buttonThirdLine.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                Intent cancelRedirectedCall = new Intent(
+                        TelecomBroadcastIntentProcessor.ACTION_CANCEL_REDIRECTED_CALL,
+                        null, CallRedirectionConfirmDialogActivity.this,
+                        TelecomBroadcastReceiver.class);
+                cancelRedirectedCall.putExtra(EXTRA_REDIRECTION_OUTGOING_CALL_ID,
+                        getIntent().getStringExtra(EXTRA_REDIRECTION_OUTGOING_CALL_ID));
+                sendBroadcast(cancelRedirectedCall);
+                confirmDialog.dismiss();
+                finish();
+            }
+        });
+
+        confirmDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
+            @Override
+            public void onCancel(DialogInterface dialog) {
+                Intent cancelRedirectedCall = new Intent(
+                        TelecomBroadcastIntentProcessor.ACTION_CANCEL_REDIRECTED_CALL,
+                        null, CallRedirectionConfirmDialogActivity.this,
+                        TelecomBroadcastReceiver.class);
+                cancelRedirectedCall.putExtra(EXTRA_REDIRECTION_OUTGOING_CALL_ID,
+                        getIntent().getStringExtra(EXTRA_REDIRECTION_OUTGOING_CALL_ID));
+                sendBroadcast(cancelRedirectedCall);
+                dialog.dismiss();
+                finish();
+            }
+        });
+
+        confirmDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+
+        confirmDialog.setCancelable(false);
+        confirmDialog.setCanceledOnTouchOutside(false);
+
+        confirmDialog.setView(dialogView);
+
+        confirmDialog.show();
+    }
+}
diff --git a/src/com/android/server/telecom/ui/CallRedirectionTimeoutDialogActivity.java b/src/com/android/server/telecom/ui/CallRedirectionTimeoutDialogActivity.java
new file mode 100644
index 0000000..5aa80c6
--- /dev/null
+++ b/src/com/android/server/telecom/ui/CallRedirectionTimeoutDialogActivity.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2019 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.ui;
+
+import com.android.server.telecom.R;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.telecom.Log;
+
+/**
+ * Dialog activity used when there is an ongoing call redirected by the call redirection service.
+ * The dialog prompts the user to inform the redirected outgoing call is canceled due to timeout.
+ */
+public class CallRedirectionTimeoutDialogActivity extends Activity {
+    public static final String EXTRA_REDIRECTION_APP_NAME =
+            "android.telecom.extra.REDIRECTION_APP_NAME";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.i(this, "CallRedirectionTimeoutDialogActivity onCreate.");
+        final CharSequence redirectionAppName = getIntent().getStringExtra(
+                EXTRA_REDIRECTION_APP_NAME);
+        showDialog(redirectionAppName);
+    }
+
+    private void showDialog(final CharSequence redirectionAppName) {
+        Log.i(this, "showDialog: timeout redirection with %s", redirectionAppName);
+        CharSequence message = getString(
+                R.string.alert_redirect_outgoing_call_timeout, redirectionAppName);
+        final AlertDialog errorDialog = new AlertDialog.Builder(this)
+                .setMessage(message)
+                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        dialog.dismiss();
+                        finish();
+                    }
+                })
+                .setOnCancelListener(new DialogInterface.OnCancelListener() {
+                    @Override
+                    public void onCancel(DialogInterface dialog) {
+                        dialog.dismiss();
+                        finish();
+                    }
+                })
+                .create();
+
+        errorDialog.show();
+    }
+}
diff --git a/src/com/android/server/telecom/ui/TelecomDeveloperMenu.java b/src/com/android/server/telecom/ui/TelecomDeveloperMenu.java
new file mode 100644
index 0000000..ae2e853
--- /dev/null
+++ b/src/com/android/server/telecom/ui/TelecomDeveloperMenu.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 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.ui;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.Switch;
+
+import com.android.server.telecom.R;
+import com.android.server.telecom.SystemSettingsUtil;
+
+/**
+ * Telecom Developer Settings Menu.
+ */
+public class TelecomDeveloperMenu extends Activity {
+
+    private Switch mEnhancedCallingSwitch;
+    private SystemSettingsUtil mSystemSettingsUtil;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mSystemSettingsUtil = new SystemSettingsUtil();
+        setContentView(R.layout.telecom_developer_menu);
+
+        mEnhancedCallingSwitch = findViewById(R.id.switchEnhancedCallBlocking);
+        mEnhancedCallingSwitch.setOnClickListener(l -> {
+            handleEnhancedCallingToggle();
+        });
+        loadPreferences();
+    }
+
+    private void handleEnhancedCallingToggle() {
+        mSystemSettingsUtil.setEnhancedCallBlockingEnabled(this,
+                mEnhancedCallingSwitch.isChecked());
+    }
+
+    private void loadPreferences() {
+        mEnhancedCallingSwitch.setChecked(mSystemSettingsUtil.isEnhancedCallBlockingEnabled(this));
+    }
+}
\ No newline at end of file
diff --git a/testapps/Android.bp b/testapps/Android.bp
new file mode 100644
index 0000000..c647b1e
--- /dev/null
+++ b/testapps/Android.bp
@@ -0,0 +1,27 @@
+//
+// Copyright (C) 2013 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.
+//
+
+android_test {
+    name: "TelecomTestApps",
+    static_libs: [
+        "android-support-v4",
+        "android-ex-camera2",
+        "guava",
+    ],
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+}
diff --git a/testapps/Android.mk b/testapps/Android.mk
deleted file mode 100644
index b600dca..0000000
--- a/testapps/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# Copyright (C) 2013 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-        android-support-v4 \
-        android-ex-camera2 \
-        guava
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := TelecomTestApps
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/testapps/AndroidManifest.xml b/testapps/AndroidManifest.xml
index 48451d1..e339356 100644
--- a/testapps/AndroidManifest.xml
+++ b/testapps/AndroidManifest.xml
@@ -19,9 +19,10 @@
           package="com.android.server.telecom.testapps">
 
     <uses-sdk
-        android:minSdkVersion="23"
-        android:targetSdkVersion="23" />
+        android:minSdkVersion="28"
+        android:targetSdkVersion="28" />
 
+    <uses-permission android:name="android.permission.ACCEPT_HANDOVER" />
     <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-permission android:name="android.permission.CALL_PHONE" />
@@ -237,5 +238,40 @@
         <receiver android:exported="false"
             android:process="com.android.server.telecom.testapps.SelfMangingCallingApp"
             android:name="com.android.server.telecom.testapps.SelfManagedCallNotificationReceiver" />
+
+        <receiver android:exported="true"
+                  android:name="com.android.server.telecom.testapps.NuisanceReportReceiver">
+            <intent-filter>
+                <action android:name="android.telecom.action.NUISANCE_CALL_STATUS_CHANGED" />
+            </intent-filter>
+        </receiver>
+
+        <service
+            android:name=".TestCallScreeningService"
+            android:permission="android.permission.BIND_SCREENING_SERVICE">
+            <intent-filter>
+                <action android:name="android.telecom.CallScreeningService"/>
+            </intent-filter>
+        </service>
+
+        <activity android:name=".CallScreeningActivity"
+                  android:configChanges="orientation|screenSize|keyboardHidden"
+                  android:excludeFromRecents="true"
+                  android:launchMode="singleInstance">
+        </activity>
+
+        <service
+                android:name=".TestCallRedirectionService"
+                android:permission="android.permission.BIND_CALL_REDIRECTION_SERVICE">
+            <intent-filter>
+                <action android:name="android.telecom.CallRedirectionService"/>
+            </intent-filter>
+        </service>
+
+        <activity android:name=".CallRedirectionActivity"
+                  android:configChanges="orientation|screenSize|keyboardHidden"
+                  android:excludeFromRecents="true"
+                  android:launchMode="singleInstance">
+        </activity>
     </application>
 </manifest>
diff --git a/testapps/res/layout/call_list_item.xml b/testapps/res/layout/call_list_item.xml
index c9f2ff7..ecaa237 100644
--- a/testapps/res/layout/call_list_item.xml
+++ b/testapps/res/layout/call_list_item.xml
@@ -39,4 +39,37 @@
             android:layout_height="wrap_content"
             android:textSize="25dp"
             android:text="TextView" />
+    <ImageView
+        android:id="@+id/callIdPhoto"
+        android:layout_gravity="left"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+    <TextView
+        android:id="@+id/callIdName"
+        android:layout_gravity="left"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="25dp"
+        android:text="TextView" />
+    <TextView
+        android:id="@+id/callIdDescription"
+        android:layout_gravity="left"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="25dp"
+        android:text="TextView" />
+    <TextView
+        android:id="@+id/callIdDetails"
+        android:layout_gravity="left"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="25dp"
+        android:text="TextView" />
+    <TextView
+        android:id="@+id/callIdType"
+        android:layout_gravity="left"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="25dp"
+        android:text="TextView" />
 </LinearLayout>
diff --git a/testapps/res/layout/self_managed_call_list_item.xml b/testapps/res/layout/self_managed_call_list_item.xml
index 66b5b21..6a31a50 100644
--- a/testapps/res/layout/self_managed_call_list_item.xml
+++ b/testapps/res/layout/self_managed_call_list_item.xml
@@ -65,13 +65,18 @@
         <Button
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:text="Speaker"
+            android:text="🔊"
             android:id="@+id/speakerButton" />
         <Button
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:text="Earpiece"
+            android:text="👂"
             android:id="@+id/earpieceButton" />
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="🎧"
+            android:id="@+id/bluetoothButton" />
         <CheckBox
             android:id="@+id/holdable"
             android:layout_width="wrap_content"
diff --git a/testapps/res/layout/self_managed_sample_main.xml b/testapps/res/layout/self_managed_sample_main.xml
index 68ae65c..28f4473 100644
--- a/testapps/res/layout/self_managed_sample_main.xml
+++ b/testapps/res/layout/self_managed_sample_main.xml
@@ -106,6 +106,11 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="Accept Handover"/>
+        <Button
+            android:id="@+id/requestCallScreeningRole"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Req CallScreen Role"/>
     </LinearLayout>
 
     <ListView
diff --git a/testapps/res/layout/testdialer_main.xml b/testapps/res/layout/testdialer_main.xml
index e6c56b7..9da3789 100644
--- a/testapps/res/layout/testdialer_main.xml
+++ b/testapps/res/layout/testdialer_main.xml
@@ -30,6 +30,16 @@
         android:layout_height="wrap_content"
         android:text="@string/placeCallButton" />
     <Button
+        android:id="@+id/report_nuisance_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="Report Nuisance" />
+    <Button
+        android:id="@+id/report_not_nuisance_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="Report Not Nuisance" />
+    <Button
         android:id="@+id/set_default_button"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
diff --git a/testapps/src/com/android/server/telecom/testapps/CallListAdapter.java b/testapps/src/com/android/server/telecom/testapps/CallListAdapter.java
index 85785d5..4de6eed 100644
--- a/testapps/src/com/android/server/telecom/testapps/CallListAdapter.java
+++ b/testapps/src/com/android/server/telecom/testapps/CallListAdapter.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Handler;
 import android.telecom.Call;
 import android.util.Log;
@@ -25,6 +26,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
+import android.widget.ImageView;
 import android.widget.TextView;
 
 public class CallListAdapter extends BaseAdapter {
@@ -90,9 +92,14 @@
             convertView = mLayoutInflater.inflate(R.layout.call_list_item, parent, false);
         }
 
-        TextView phoneNumber = (TextView) convertView.findViewById(R.id.phoneNumber);
-        TextView duration = (TextView) convertView.findViewById(R.id.duration);
-        TextView state = (TextView) convertView.findViewById(R.id.callState);
+        TextView phoneNumber = convertView.findViewById(R.id.phoneNumber);
+        TextView duration = convertView.findViewById(R.id.duration);
+        TextView state = convertView.findViewById(R.id.callState);
+        TextView callIdName = convertView.findViewById(R.id.callIdName);
+        TextView callIdDescription = convertView.findViewById(R.id.callIdDescription);
+        TextView callIdDetails = convertView.findViewById(R.id.callIdDetails);
+        TextView callIdType = convertView.findViewById(R.id.callIdType);
+        ImageView callIdPhoto = convertView.findViewById(R.id.callIdPhoto);
 
         Call call = mCallList.getCall(position);
         Uri handle = call.getDetails().getHandle();
@@ -105,10 +112,24 @@
 
         Log.i(TAG, "Call found: " + ((handle == null) ? "null" : handle.getSchemeSpecificPart())
                 + ", " + durationMs);
+        Log.i(TAG, "Call extras: " + extrasToString(call.getDetails().getExtras()));
+        Log.i(TAG, "Call intent extras: " + extrasToString(call.getDetails().getIntentExtras()));
 
         return convertView;
     }
 
+    private String extrasToString(Bundle bundle) {
+        StringBuilder sb = new StringBuilder("[");
+        for (String key : bundle.keySet()) {
+            sb.append(key);
+            sb.append(": ");
+            sb.append(bundle.get(key));
+            sb.append("\n");
+        }
+        sb.append("]");
+        return sb.toString();
+    }
+
     private static String getStateString(Call call) {
         switch (call.getState()) {
             case Call.STATE_ACTIVE:
diff --git a/testapps/src/com/android/server/telecom/testapps/CallRedirectionActivity.java b/testapps/src/com/android/server/telecom/testapps/CallRedirectionActivity.java
new file mode 100644
index 0000000..044e271
--- /dev/null
+++ b/testapps/src/com/android/server/telecom/testapps/CallRedirectionActivity.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 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.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.telecom.Log;
+
+public class CallRedirectionActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.i(this, "onCreate: CallRedirectionActivity");
+
+        AlertDialog alertDialog = new AlertDialog.Builder(this)
+                .setTitle("Test Call Redirection")
+                .setMessage("Decision for call redirection?")
+                .setNegativeButton("Timeout", new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        // No action is needed for timeout
+                        finish();
+                    }
+                })
+                .setPositiveButton("Redirect and confirm", new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        if (TestCallRedirectionService.getInstance() != null) {
+                            TestCallRedirectionService.getInstance().tryRedirectCallAndAskToConfirm();
+                        }
+                        finish();
+                    }
+                }).create();
+        alertDialog.show();
+    }
+}
\ No newline at end of file
diff --git a/testapps/src/com/android/server/telecom/testapps/CallScreeningActivity.java b/testapps/src/com/android/server/telecom/testapps/CallScreeningActivity.java
new file mode 100644
index 0000000..05ba500
--- /dev/null
+++ b/testapps/src/com/android/server/telecom/testapps/CallScreeningActivity.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 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.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.telecom.CallScreeningService;
+import android.view.WindowManager;
+
+public class CallScreeningActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        AlertDialog alertDialog = new AlertDialog.Builder(this)
+                .setTitle("Test Call Screening")
+                .setMessage("Allow the call?")
+                .setNegativeButton("Block", new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        if (TestCallScreeningService.getInstance() != null) {
+                            TestCallScreeningService.getInstance().blockCall();
+                        }
+                        finish();
+                    }
+                })
+                .setPositiveButton("Allow", new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        if (TestCallScreeningService.getInstance() != null) {
+                            TestCallScreeningService.getInstance().allowCall();
+                        }
+                        finish();
+                    }
+                }).create();
+        alertDialog.show();
+    }
+}
diff --git a/testapps/src/com/android/server/telecom/testapps/CallServiceNotifier.java b/testapps/src/com/android/server/telecom/testapps/CallServiceNotifier.java
index 758ae4f..1c84d29 100644
--- a/testapps/src/com/android/server/telecom/testapps/CallServiceNotifier.java
+++ b/testapps/src/com/android/server/telecom/testapps/CallServiceNotifier.java
@@ -19,6 +19,7 @@
 import com.android.server.telecom.testapps.R;
 
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -26,6 +27,7 @@
 import android.content.Intent;
 import android.graphics.Color;
 import android.graphics.drawable.Icon;
+import android.media.AudioAttributes;
 import android.net.Uri;
 import android.os.Bundle;
 import android.telecom.PhoneAccount;
@@ -45,6 +47,7 @@
  */
 public class CallServiceNotifier {
     private static final CallServiceNotifier INSTANCE = new CallServiceNotifier();
+    private static final String CHANNEL_ID = "channel1";
 
     public static final String CALL_PROVIDER_ID = "testapps_TestConnectionService_CALL_PROVIDER_ID";
     public static final String SIM_SUBSCRIPTION_ID =
@@ -86,6 +89,9 @@
      */
     public void updateNotification(Context context) {
         log("adding the notification ------------");
+        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Test Channel",
+                NotificationManager.IMPORTANCE_DEFAULT);
+        getNotificationManager(context).createNotificationChannel(channel);
         getNotificationManager(context).notify(CALL_NOTIFICATION_ID, getMainNotification(context));
         getNotificationManager(context).notify(
                 PHONE_ACCOUNT_NOTIFICATION_ID, getPhoneAccountNotification(context));
@@ -219,7 +225,7 @@
      * Creates a notification object for using the telecom APIs.
      */
     private Notification getPhoneAccountNotification(Context context) {
-        final Notification.Builder builder = new Notification.Builder(context);
+        final Notification.Builder builder = new Notification.Builder(context, CHANNEL_ID);
         // Both notifications have buttons and only the first one with buttons will show its
         // buttons.  Since the phone accounts notification is always first, setting false ensures
         // it can be dismissed to use the other notification.
@@ -244,7 +250,7 @@
      * Creates a notification object out of the current calls state.
      */
     private Notification getMainNotification(Context context) {
-        final Notification.Builder builder = new Notification.Builder(context);
+        final Notification.Builder builder = new Notification.Builder(context, CHANNEL_ID);
         builder.setOngoing(true);
         builder.setPriority(Notification.PRIORITY_HIGH);
         builder.setSmallIcon(android.R.drawable.stat_sys_phone_call);
diff --git a/testapps/src/com/android/server/telecom/testapps/SelfManagedCallListAdapter.java b/testapps/src/com/android/server/telecom/testapps/SelfManagedCallListAdapter.java
index 8eaa282..75ceb62 100644
--- a/testapps/src/com/android/server/telecom/testapps/SelfManagedCallListAdapter.java
+++ b/testapps/src/com/android/server/telecom/testapps/SelfManagedCallListAdapter.java
@@ -104,6 +104,16 @@
         }
     };
 
+    private View.OnClickListener mBluetoothListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            View parent = (View) v.getParent().getParent();
+            SelfManagedConnection connection = (SelfManagedConnection) parent.getTag();
+            connection.setAudioRoute(CallAudioState.ROUTE_BLUETOOTH);
+            notifyDataSetChanged();
+        }
+    };
+
     private View.OnClickListener mHoldableListener = new View.OnClickListener() {
         @Override
         public void onClick (View v) {
@@ -221,6 +231,8 @@
         speakerButton.setOnClickListener(mSpeakerListener);
         View earpieceButton = view.findViewById(R.id.earpieceButton);
         earpieceButton.setOnClickListener(mEarpieceListener);
+        View bluetoothButton = view.findViewById(R.id.bluetoothButton);
+        bluetoothButton.setOnClickListener(mBluetoothListener);
         View missedButton = view.findViewById(R.id.missedButton);
         missedButton.setOnClickListener(mMissedListener);
         missedButton.setVisibility(isRinging ? View.VISIBLE : View.GONE);
diff --git a/testapps/src/com/android/server/telecom/testapps/SelfManagedCallingActivity.java b/testapps/src/com/android/server/telecom/testapps/SelfManagedCallingActivity.java
index a7b1350..959b855 100644
--- a/testapps/src/com/android/server/telecom/testapps/SelfManagedCallingActivity.java
+++ b/testapps/src/com/android/server/telecom/testapps/SelfManagedCallingActivity.java
@@ -17,6 +17,10 @@
 package com.android.server.telecom.testapps;
 
 import android.app.Activity;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.media.AudioAttributes;
+import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.Bundle;
 import android.telecom.ConnectionRequest;
@@ -100,6 +104,7 @@
                         | WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
 
         getWindow().addFlags(flags);
+        configureNotificationChannel();
         setContentView(R.layout.self_managed_sample_main);
         mCheckIfPermittedBeforeCalling = (CheckBox) findViewById(
                 R.id.checkIfPermittedBeforeCalling);
@@ -114,12 +119,12 @@
         mPlaceIncomingCallButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                placeIncomingCall(false /* isHandoverFrom */);
+                placeIncomingCall();
             }
         });
         mHandoverFrom = (Button) findViewById(R.id.handoverFrom);
         mHandoverFrom.setOnClickListener((v -> {
-            placeIncomingCall(true /* isHandoverFrom */);
+            initiateHandover();
         }));
 
         mUseAcct1Button = findViewById(R.id.useAcct1Button);
@@ -171,7 +176,14 @@
         tm.placeCall(Uri.parse(mNumber.getText().toString()), extras);
     }
 
-    private void placeIncomingCall(boolean isHandoverFrom) {
+    private void initiateHandover() {
+        TelecomManager tm = TelecomManager.from(this);
+        PhoneAccountHandle phoneAccountHandle = getSelectedPhoneAccountHandle();
+        Uri address = Uri.parse(mNumber.getText().toString());
+        tm.acceptHandover(address, VideoProfile.STATE_BIDIRECTIONAL, phoneAccountHandle);
+    }
+
+    private void placeIncomingCall() {
         TelecomManager tm = TelecomManager.from(this);
         PhoneAccountHandle phoneAccountHandle = getSelectedPhoneAccountHandle();
 
@@ -191,9 +203,22 @@
             extras.putInt(TelecomManager.EXTRA_INCOMING_VIDEO_STATE,
                     VideoProfile.STATE_BIDIRECTIONAL);
         }
-        if (isHandoverFrom) {
-            extras.putBoolean(TelecomManager.EXTRA_IS_HANDOVER, true);
-        }
         tm.addNewIncomingCall(getSelectedPhoneAccountHandle(), extras);
     }
+
+    private void configureNotificationChannel() {
+        NotificationChannel channel = new NotificationChannel(
+                SelfManagedConnection.INCOMING_CALL_CHANNEL_ID, "Incoming Calls",
+                NotificationManager.IMPORTANCE_MAX);
+        channel.setShowBadge(false);
+        Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
+        channel.setSound(ringtoneUri, new AudioAttributes.Builder()
+                .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
+                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                .build());
+        channel.enableLights(true);
+
+        NotificationManager mgr = getSystemService(NotificationManager.class);
+        mgr.createNotificationChannel(channel);
+    }
 }
\ No newline at end of file
diff --git a/testapps/src/com/android/server/telecom/testapps/SelfManagedConnection.java b/testapps/src/com/android/server/telecom/testapps/SelfManagedConnection.java
index 8d0af04..ebd7423 100644
--- a/testapps/src/com/android/server/telecom/testapps/SelfManagedConnection.java
+++ b/testapps/src/com/android/server/telecom/testapps/SelfManagedConnection.java
@@ -22,7 +22,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Icon;
+import android.media.AudioAttributes;
 import android.media.MediaPlayer;
+import android.media.RingtoneManager;
+import android.net.Uri;
 import android.os.Bundle;
 import android.telecom.Call;
 import android.telecom.CallAudioState;
@@ -43,7 +46,7 @@
         public void onConnectionStateChanged(SelfManagedConnection connection) {}
         public void onConnectionRemoved(SelfManagedConnection connection) {}
     }
-
+    public static final String INCOMING_CALL_CHANNEL_ID = "INCOMING_CALL_CHANNEL_ID";
     public static final String EXTRA_PHONE_ACCOUNT_HANDLE =
             "com.android.server.telecom.testapps.extra.PHONE_ACCOUNT_HANDLE";
     public static final String CALL_NOTIFICATION = "com.android.server.telecom.testapps.CALL";
@@ -58,6 +61,7 @@
     private boolean mIsIncomingCallUiShowing;
     private Listener mListener;
     private boolean mIsHandover;
+    private Notification.Builder mNotificationBuilder;
 
     SelfManagedConnection(SelfManagedCallList callList, Context context, boolean isIncoming) {
         mCallList = callList;
@@ -93,7 +97,8 @@
         PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 1, intent, 0);
 
         // Build the notification as an ongoing high priority item.
-        final Notification.Builder builder = new Notification.Builder(mContext);
+        final Notification.Builder builder = new Notification.Builder(mContext,
+                INCOMING_CALL_CHANNEL_ID);
         builder.setOngoing(true);
         builder.setPriority(Notification.PRIORITY_HIGH);
 
@@ -131,9 +136,12 @@
                                 PendingIntent.FLAG_UPDATE_CURRENT))
                         .build());
 
+        Notification notification = builder.build();
+        notification.flags |= Notification.FLAG_INSISTENT;
         NotificationManager notificationManager = mContext.getSystemService(
                 NotificationManager.class);
-        notificationManager.notify(CALL_NOTIFICATION, mCallId, builder.build());
+        mNotificationBuilder = builder;
+        notificationManager.notify(CALL_NOTIFICATION, mCallId, notification);
     }
 
     @Override
@@ -172,6 +180,15 @@
         setConnectionDisconnected(DisconnectCause.LOCAL);
     }
 
+    @Override
+    public void onSilence() {
+        // Re-post our notification without a ringtone.
+        mNotificationBuilder.setOnlyAlertOnce(true);
+        NotificationManager notificationManager = mContext.getSystemService(
+                NotificationManager.class);
+        notificationManager.notify(CALL_NOTIFICATION, mCallId, mNotificationBuilder.build());
+    }
+
     public void setConnectionActive() {
         mMediaPlayer.start();
         setActive();
diff --git a/testapps/src/com/android/server/telecom/testapps/SelfManagedConnectionService.java b/testapps/src/com/android/server/telecom/testapps/SelfManagedConnectionService.java
index d5d79af..e6e35d8 100644
--- a/testapps/src/com/android/server/telecom/testapps/SelfManagedConnectionService.java
+++ b/testapps/src/com/android/server/telecom/testapps/SelfManagedConnectionService.java
@@ -24,9 +24,7 @@
 import android.telecom.Log;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
-import android.telecom.VideoProfile;
 
-import java.util.Objects;
 import java.util.Random;
 
 /**
@@ -45,13 +43,25 @@
             PhoneAccountHandle connectionManagerAccount,
             final ConnectionRequest request) {
 
-        return createSelfManagedConnection(request, false);
+        return createSelfManagedConnection(request, false, false /* isHandover */);
     }
 
     @Override
     public Connection onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount,
             ConnectionRequest request) {
-        return createSelfManagedConnection(request, true);
+        return createSelfManagedConnection(request, true, false /* isHandover */);
+    }
+
+    @Override
+    public Connection onCreateOutgoingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
+            ConnectionRequest request) {
+        return createSelfManagedConnection(request, false, true /* isHandover */);
+    }
+
+    @Override
+    public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
+            ConnectionRequest request) {
+        return createSelfManagedConnection(request, true, true /* isHandover */);
     }
 
     @Override
@@ -77,13 +87,15 @@
         mCallList.notifyConnectionServiceFocusGained();
     }
 
-    private Connection createSelfManagedConnection(ConnectionRequest request, boolean isIncoming) {
+    private Connection createSelfManagedConnection(ConnectionRequest request, boolean isIncoming,
+            boolean isHandover) {
         SelfManagedConnection connection = new SelfManagedConnection(mCallList,
                 getApplicationContext(), isIncoming);
         connection.setListener(mCallList.getConnectionListener());
         connection.setConnectionProperties(Connection.PROPERTY_SELF_MANAGED);
         connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
-        connection.setAudioModeIsVoip(true);
+        // Purposely do not set the audio mode to voip since we expect this to be the default:
+        // connection.setAudioModeIsVoip(true);
         connection.setVideoState(request.getVideoState());
         Random random = new Random();
         connection.setCallerDisplayName(TEST_NAMES[random.nextInt(TEST_NAMES.length)],
@@ -92,16 +104,17 @@
         if (isIncoming) {
             connection.setIsIncomingCallUiShowing(request.shouldShowIncomingCallUi());
             connection.setRinging();
+        } else {
+            connection.setDialing();
         }
         Bundle requestExtras = request.getExtras();
         if (requestExtras != null) {
             boolean isHoldable = requestExtras.getBoolean(EXTRA_HOLDABLE, false);
             Log.i(this, "createConnection: isHandover=%b, handoverFrom=%s, holdable=%b",
-                    requestExtras.getBoolean(TelecomManager.EXTRA_IS_HANDOVER),
+                    isHandover,
                     requestExtras.getString(TelecomManager.EXTRA_HANDOVER_FROM_PHONE_ACCOUNT),
                     isHoldable);
-            connection.setIsHandover(requestExtras.getBoolean(TelecomManager.EXTRA_IS_HANDOVER,
-                    false));
+            connection.setIsHandover(isHandover);
             if (isHoldable) {
                 connection.setConnectionCapabilities(connection.getConnectionCapabilities() |
                         Connection.CAPABILITY_HOLD | Connection.CAPABILITY_SUPPORT_HOLD);
diff --git a/testapps/src/com/android/server/telecom/testapps/TestCallRedirectionService.java b/testapps/src/com/android/server/telecom/testapps/TestCallRedirectionService.java
new file mode 100644
index 0000000..ce48b3e
--- /dev/null
+++ b/testapps/src/com/android/server/telecom/testapps/TestCallRedirectionService.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 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.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.net.Uri;
+import android.telecom.CallRedirectionService;
+import android.telecom.Log;
+import android.telecom.PhoneAccount;
+import android.telecom.PhoneAccountHandle;
+
+public class TestCallRedirectionService extends CallRedirectionService {
+
+    public static TestCallRedirectionService getInstance() {
+        return sTestCallRedirectionService;
+    }
+
+    private static TestCallRedirectionService sTestCallRedirectionService;
+
+    private static final Uri SAMPLE_HANDLE = Uri.fromParts(PhoneAccount.SCHEME_TEL, "0001112222",
+            null);
+
+    private static final PhoneAccountHandle SAMPLE_PHONE_ACCOUNT = new PhoneAccountHandle(
+            new ComponentName("com.android.server.telecom.testapps",
+                    "com.android.server.telecom.testapps.TestCallRedirectionService"),
+            "TELECOM_TEST_APP_PHONE_ACCOUNT_ID");
+
+    private PhoneAccountHandle mDestinationPhoneAccount = SAMPLE_PHONE_ACCOUNT;
+
+    /**
+     * Handles request from the system to redirect an outgoing call.
+     */
+    @Override
+    public void onPlaceCall(@NonNull Uri handle, @NonNull PhoneAccountHandle initialPhoneAccount,
+                            boolean allowInteractiveResponse) {
+        Log.i(this, "onPlaceCall: received call %s", handle);
+        sTestCallRedirectionService = this;
+        mDestinationPhoneAccount = initialPhoneAccount;
+        Intent intent = new Intent(this, CallRedirectionActivity.class);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        startActivity(intent);
+    }
+
+    public void tryRedirectCallAndAskToConfirm() {
+        // Provide call identification
+        redirectCall(SAMPLE_HANDLE, mDestinationPhoneAccount, true);
+    }
+}
diff --git a/testapps/src/com/android/server/telecom/testapps/TestCallScreeningService.java b/testapps/src/com/android/server/telecom/testapps/TestCallScreeningService.java
new file mode 100644
index 0000000..5f7f4d5
--- /dev/null
+++ b/testapps/src/com/android/server/telecom/testapps/TestCallScreeningService.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 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.content.Intent;
+import android.graphics.drawable.Icon;
+import android.telecom.Call;
+import android.telecom.CallScreeningService;
+import android.telecom.Log;
+
+public class TestCallScreeningService extends CallScreeningService {
+    private Call.Details mDetails;
+    private static TestCallScreeningService sTestCallScreeningService;
+
+    public static TestCallScreeningService getInstance() {
+        return sTestCallScreeningService;
+    }
+
+    /**
+     * Handles request from the system to screen an incoming call.
+     * @param callDetails Information about a new incoming call, see {@link Call.Details}.
+     */
+    @Override
+    public void onScreenCall(Call.Details callDetails) {
+        Log.i(this, "onScreenCall: received call %s", callDetails);
+        sTestCallScreeningService = this;
+
+        mDetails = callDetails;
+        if (callDetails.getCallDirection() == Call.Details.DIRECTION_INCOMING) {
+            Intent errorIntent = new Intent(this, CallScreeningActivity.class);
+            errorIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            startActivity(errorIntent);
+        }
+    }
+
+    public void blockCall() {
+        CallScreeningService.CallResponse
+                response = new CallScreeningService.CallResponse.Builder()
+                .setDisallowCall(true)
+                .setRejectCall(true)
+                .setSkipCallLog(false)
+                .setSkipNotification(true)
+                .build();
+        respondToCall(mDetails, response);
+    }
+
+    public void allowCall() {
+        CallScreeningService.CallResponse
+                response = new CallScreeningService.CallResponse.Builder()
+                .setDisallowCall(false)
+                .setRejectCall(false)
+                .setSkipCallLog(false)
+                .setSkipNotification(false)
+                .build();
+        respondToCall(mDetails, response);
+    }
+}
diff --git a/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java b/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java
index 52dcadb..1a2aac6 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java
@@ -16,12 +16,18 @@
 
 package com.android.server.telecom.testapps;
 
+import static android.media.AudioAttributes.CONTENT_TYPE_SPEECH;
+import static android.media.AudioAttributes.USAGE_VOICE_COMMUNICATION;
+
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
 import android.media.MediaPlayer;
+import android.media.ToneGenerator;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -57,6 +63,11 @@
 
     public static final String EXTRA_HANDLE = "extra_handle";
 
+    /**
+     * If an outgoing call ends with 2879 (BUSY), the test CS will indicate the call is busy.
+     */
+    public static final String BUSY_SUFFIX = "2879";
+
     private static final String LOG_TAG = TestConnectionService.class.getSimpleName();
 
     private static TestConnectionService INSTANCE;
@@ -204,8 +215,15 @@
         void startOutgoing() {
             setDialing();
             mHandler.postDelayed(() -> {
-                setActive();
-                activateCall(TestConnection.this);
+                if (getAddress().getSchemeSpecificPart().endsWith(BUSY_SUFFIX)) {
+                    setDisconnected(new DisconnectCause(DisconnectCause.REMOTE, "Line busy",
+                            "Line busy", "Line busy", ToneGenerator.TONE_SUP_BUSY));
+                    destroyCall(this);
+                    destroy();
+                } else {
+                    setActive();
+                    activateCall(TestConnection.this);
+                }
             }, 4000);
             if (mOriginalRequest.isRequestingRtt()) {
                 Log.i(LOG_TAG, "Is RTT call. Starting chatbot service.");
@@ -582,8 +600,16 @@
     }
 
     private MediaPlayer createMediaPlayer() {
+        AudioAttributes attributes = new AudioAttributes.Builder()
+                .setUsage(USAGE_VOICE_COMMUNICATION)
+                .setContentType(CONTENT_TYPE_SPEECH)
+                .build();
+
+        final int audioSessionId = ((AudioManager) getSystemService(
+                Context.AUDIO_SERVICE)).generateAudioSessionId();
         // Prepare the media player to play a tone when there is a call.
-        MediaPlayer mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.beep_boop);
+        MediaPlayer mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.beep_boop, attributes,
+                audioSessionId);
         mediaPlayer.setLooping(true);
         return mediaPlayer;
     }
diff --git a/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java b/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java
index 9851253..2a5b33a 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java
@@ -18,6 +18,7 @@
 
 import android.app.Activity;
 import android.bluetooth.BluetoothDevice;
+import android.content.ComponentName;
 import android.content.Intent;
 import android.os.Bundle;
 import android.telecom.Call;
@@ -209,11 +210,8 @@
 
         handoverButton.setOnClickListener((v) -> {
             Call call = mCallList.getCall(0);
-            Bundle extras = new Bundle();
-            extras.putParcelable(Call.EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE,
-                    getHandoverToPhoneAccountHandle());
-            extras.putInt(Call.EXTRA_HANDOVER_VIDEO_STATE, VideoProfile.STATE_BIDIRECTIONAL);
-            call.sendCallEvent(Call.EVENT_REQUEST_HANDOVER, extras);
+            call.handoverTo(getHandoverToPhoneAccountHandle(), VideoProfile.STATE_BIDIRECTIONAL,
+                    null);
         });
     }
 
@@ -263,17 +261,8 @@
     }
 
     private PhoneAccountHandle getHandoverToPhoneAccountHandle() {
-        TelecomManager tm = TelecomManager.from(this);
-
-        List<PhoneAccountHandle> handles = tm.getAllPhoneAccountHandles();
-        Optional<PhoneAccountHandle> found = handles.stream().filter(h -> {
-            PhoneAccount account = tm.getPhoneAccount(h);
-            Bundle extras = account.getExtras();
-            return extras != null && extras.getBoolean(PhoneAccount.EXTRA_SUPPORTS_HANDOVER_TO);
-        }).findFirst();
-        PhoneAccountHandle foundHandle = found.orElse(null);
-        Log.i(TestInCallUI.class.getSimpleName(), "getHandoverToPhoneAccountHandle() = " +
-            foundHandle);
-        return foundHandle;
+        return new PhoneAccountHandle(new ComponentName(
+                SelfManagedCallList.class.getPackage().getName(),
+                SelfManagedConnectionService.class.getName()), "1");
     }
 }
diff --git a/tests/Android.mk b/tests/Android.mk
deleted file mode 100644
index 5f083de..0000000
--- a/tests/Android.mk
+++ /dev/null
@@ -1,74 +0,0 @@
-#
-# Copyright (C) 2013 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-ex-camera2 \
-    guava \
-    mockito-target \
-    android-support-test \
-    platform-test-annotations
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    android-support-core-ui \
-    android-support-core-utils \
-    android-support-compat \
-    android-support-fragment
-
-LOCAL_SRC_FILES := \
-    $(call all-java-files-under, src) \
-    $(call all-java-files-under, ../src) \
-    $(call all-proto-files-under, ../proto)
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/../proto/
-LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
-
-LOCAL_RESOURCE_DIR := \
-    $(LOCAL_PATH)/res \
-    $(LOCAL_PATH)/../res
-
-LOCAL_JAVA_LIBRARIES := \
-    android.test.mock \
-    android.test.base \
-    android.test.runner \
-    telephony-common
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_AAPT_FLAGS := \
-    --auto-add-overlay \
-    --extra-packages com.android.server.telecom
-
-LOCAL_JACK_FLAGS := --multi-dex native
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_PACKAGE_NAME := TelecomUnitTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.server.telecom.*
-LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := com.android.server.telecom.tests.*
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-include frameworks/base/packages/SettingsLib/common.mk
-
-include $(BUILD_PACKAGE)
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 0e79fce..22f5348 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -34,6 +34,7 @@
 
     <!-- Used to access TelephonyManager APIs -->
     <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
 
     <application android:label="@string/app_name"
                  android:debuggable="true">
@@ -51,7 +52,7 @@
         adb shell am instrument -w -e class com.android.server.telecom.tests.unit.FooUnitTest \
                                com.android.server.telecom.tests/android.test.InstrumentationTestRunner
     -->
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
             android:targetPackage="com.android.server.telecom.tests"
             android:label="Telecomm application tests"
             android:debuggable="true"/>
diff --git a/tests/AndroidTest.xml b/tests/AndroidTest.xml
index d3db2e3..3fb2a84 100644
--- a/tests/AndroidTest.xml
+++ b/tests/AndroidTest.xml
@@ -24,7 +24,7 @@
     <option name="test-tag" value="TelecomUnitTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.server.telecom.tests" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
         <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/tests/src/com/android/server/telecom/tests/AnalyticsTests.java b/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
index 9d64f18..1fad3f7 100644
--- a/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
+++ b/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
@@ -16,10 +16,18 @@
 
 package com.android.server.telecom.tests;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+
 import android.content.Context;
 import android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
 import android.telecom.CallAudioState;
 import android.telecom.Connection;
 import android.telecom.DisconnectCause;
@@ -31,11 +39,12 @@
 import android.telecom.TelecomManager;
 import android.telecom.VideoCallImpl;
 import android.telecom.VideoProfile;
-import android.support.test.filters.FlakyTest;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Base64;
 
+import androidx.test.filters.FlakyTest;
+
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.telecom.Analytics;
 import com.android.server.telecom.CallAudioRouteStateMachine;
@@ -59,16 +68,6 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-
 @RunWith(JUnit4.class)
 public class AnalyticsTests extends TelecomSystemTest {
     @Override
diff --git a/tests/src/com/android/server/telecom/tests/AsyncBlockCheckFilterTest.java b/tests/src/com/android/server/telecom/tests/AsyncBlockCheckFilterTest.java
index 9b2b3fb..91ddf5a 100644
--- a/tests/src/com/android/server/telecom/tests/AsyncBlockCheckFilterTest.java
+++ b/tests/src/com/android/server/telecom/tests/AsyncBlockCheckFilterTest.java
@@ -16,10 +16,14 @@
 
 package com.android.server.telecom.tests;
 
+import static android.provider.BlockedNumberContract.STATUS_BLOCKED_IN_LIST;
+import static android.provider.BlockedNumberContract.STATUS_NOT_BLOCKED;
+
 import android.content.Context;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.PersistableBundle;
+import android.provider.CallLog;
 import android.telecom.TelecomManager;
 import android.telephony.CarrierConfigManager;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -49,7 +53,6 @@
 
 @RunWith(JUnit4.class)
 public class AsyncBlockCheckFilterTest extends TelecomTestCase {
-    @Mock private Context mContext;
     @Mock private BlockCheckerAdapter mBlockCheckerAdapter;
     @Mock private Call mCall;
     @Mock private CallFilterResultCallback mCallback;
@@ -60,8 +63,12 @@
     private static final CallFilteringResult BLOCK_RESULT = new CallFilteringResult(
             false, // shouldAllowCall
             true, //shouldReject
-            false, //shouldAddToCallLog
-            false // shouldShowNotification
+            true, //shouldAddToCallLog
+            false, // shouldShowNotification
+            CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER, //blockReason
+            null, // callScreeningAppName
+            null //callScreeningComponentName
+
     );
 
     private static final CallFilteringResult PASS_RESULT = new CallFilteringResult(
@@ -72,7 +79,7 @@
     );
 
     private static final Uri TEST_HANDLE = Uri.parse("tel:1235551234");
-    private static final int TEST_TIMEOUT = 100;
+    private static final int TEST_TIMEOUT = 1000;
 
     @Override
     @Before
@@ -80,7 +87,7 @@
         super.setUp();
         when(mCall.getHandle()).thenReturn(TEST_HANDLE);
         mFilter = new AsyncBlockCheckFilter(mContext, mBlockCheckerAdapter,
-                mCallerInfoLookupHelper);
+                mCallerInfoLookupHelper, null);
     }
 
     @SmallTest
@@ -89,9 +96,9 @@
         final CountDownLatch latch = new CountDownLatch(1);
         doAnswer(invocation -> {
             latch.countDown();
-            return true;
+            return STATUS_BLOCKED_IN_LIST;
         }).when(mBlockCheckerAdapter)
-                .isBlocked(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()),
+                .getBlockStatus(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()),
                         any(Bundle.class));
 
         setEnhancedBlockingEnabled(false);
@@ -108,9 +115,9 @@
         final CountDownLatch latch = new CountDownLatch(1);
         doAnswer(invocation -> {
             latch.countDown();
-            return true;
+            return STATUS_BLOCKED_IN_LIST;
         }).when(mBlockCheckerAdapter)
-                .isBlocked(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()),
+                .getBlockStatus(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()),
                         any(Bundle.class));
 
         setEnhancedBlockingEnabled(true);
@@ -128,9 +135,9 @@
         final CountDownLatch latch = new CountDownLatch(1);
         doAnswer(invocation -> {
             latch.countDown();
-            return false;
+            return STATUS_NOT_BLOCKED;
         }).when(mBlockCheckerAdapter)
-                .isBlocked(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()),
+                .getBlockStatus(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()),
                         any(Bundle.class));
 
         setEnhancedBlockingEnabled(false);
@@ -147,9 +154,9 @@
         final CountDownLatch latch = new CountDownLatch(1);
         doAnswer(invocation -> {
             latch.countDown();
-            return false;
+            return STATUS_NOT_BLOCKED;
         }).when(mBlockCheckerAdapter)
-                .isBlocked(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()),
+                .getBlockStatus(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()),
                         any(Bundle.class));
 
         setEnhancedBlockingEnabled(true);
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index e304d34..95ca3f3 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -20,6 +20,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
@@ -52,10 +53,11 @@
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
-import android.support.test.filters.FlakyTest;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
 
+import androidx.test.filters.FlakyTest;
+
 import com.android.internal.telecom.IInCallAdapter;
 import com.android.internal.telephony.CallerInfo;
 
@@ -66,6 +68,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
@@ -75,8 +78,6 @@
 import java.util.concurrent.CyclicBarrier;
 import java.util.concurrent.TimeUnit;
 
-import org.mockito.ArgumentCaptor;
-
 /**
  * Performs various basic call tests in Telecom.
  */
@@ -331,12 +332,17 @@
         int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
         String callId = startOutgoingPhoneCallWithNoPhoneAccount("650-555-1212",
                 mConnectionServiceFixtureA);
+        mTelecomSystem.getCallsManager().getLatestPreAccountSelectionFuture().join();
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
         assertEquals(Call.STATE_SELECT_PHONE_ACCOUNT,
                 mInCallServiceFixtureX.getCall(callId).getState());
         assertEquals(Call.STATE_SELECT_PHONE_ACCOUNT,
                 mInCallServiceFixtureY.getCall(callId).getState());
         mInCallServiceFixtureX.mInCallAdapter.phoneAccountSelected(callId,
                 mPhoneAccountA0.getAccountHandle(), false);
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
+        verifyAndProcessOutgoingCallBroadcast(mPhoneAccountA0.getAccountHandle());
 
         IdPair ids = outgoingCallPhoneAccountSelected(mPhoneAccountA0.getAccountHandle(),
                 startingNumConnections, startingNumCalls, mConnectionServiceFixtureA);
@@ -548,8 +554,10 @@
         // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
         IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
         IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323",
                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
         verify(mConnectionServiceFixtureA.getTestDouble())
                 .hold(eq(outgoing.mConnectionId), any());
         mConnectionServiceFixtureA.mConnectionById.get(outgoing.mConnectionId).state =
@@ -585,10 +593,15 @@
                 .setMicrophoneMute(eq(false), any(String.class), any(Integer.class));
 
         mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER, null);
+        waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
+                .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
         verify(audioManager, timeout(TEST_TIMEOUT))
                 .setSpeakerphoneOn(true);
         mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_EARPIECE, null);
-        verify(audioManager, timeout(TEST_TIMEOUT))
+        waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
+                .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
+        // setSpeakerPhoneOn(false) gets called once during the call initiation phase
+        verify(audioManager, timeout(TEST_TIMEOUT).atLeast(2))
                 .setSpeakerphoneOn(false);
 
         mConnectionServiceFixtureA.
@@ -784,7 +797,7 @@
                 anyString(),
                 eq(BlockedNumberContract.SystemContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER),
                 eq(phoneNumber),
-                isNull(Bundle.class))).thenAnswer(answer);
+                nullable(Bundle.class))).thenAnswer(answer);
     }
 
     private void verifyNoBlockChecks() {
@@ -912,12 +925,12 @@
                 Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL);
         com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
                 .iterator().next();
-        assert(call.isVideoCallingSupported());
+        assert(call.isVideoCallingSupportedByPhoneAccount());
         assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState());
 
         // Change the phone account to one which supports video calling.
         call.setTargetPhoneAccount(mPhoneAccountA1.getAccountHandle());
-        assert(call.isVideoCallingSupported());
+        assert(call.isVideoCallingSupportedByPhoneAccount());
         assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState());
     }
 
@@ -935,12 +948,12 @@
                 Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL);
         com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
                 .iterator().next();
-        assert(call.isVideoCallingSupported());
+        assert(call.isVideoCallingSupportedByPhoneAccount());
         assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState());
 
         // Change the phone account to one which does not support video calling.
         call.setTargetPhoneAccount(mPhoneAccountA2.getAccountHandle());
-        assert(!call.isVideoCallingSupported());
+        assert(!call.isVideoCallingSupportedByPhoneAccount());
         assertEquals(VideoProfile.STATE_AUDIO_ONLY, call.getVideoState());
     }
 
@@ -1045,8 +1058,13 @@
                 mConnectionServiceFixtureA);
 
         // Should have reverted back to earpiece.
-        assertEquals(CallAudioState.ROUTE_EARPIECE,
-                mInCallServiceFixtureX.mCallAudioState.getRoute());
+        assertTrueWithTimeout(new Predicate<Void>() {
+            @Override
+            public boolean apply(Void aVoid) {
+                return mInCallServiceFixtureX.mCallAudioState.getRoute()
+                        == CallAudioState.ROUTE_EARPIECE;
+            }
+        });
     }
 
     /**
@@ -1098,6 +1116,7 @@
      */
     @LargeTest
     @Test
+    @FlakyTest
     public void testUnmuteDuringEmergencyCall() throws Exception {
         // Make an outgoing call and turn ON mute.
         IdPair outgoingCall = startAndMakeActiveOutgoingCall("650-555-1212",
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
index cb7671a..2129ffa 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
@@ -18,16 +18,15 @@
 
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothProfile;
 import android.content.BroadcastReceiver;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.os.Parcel;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.server.telecom.BluetoothAdapterProxy;
 import com.android.server.telecom.BluetoothHeadsetProxy;
-import com.android.server.telecom.TelecomSystem;
 import com.android.server.telecom.bluetooth.BluetoothDeviceManager;
 import com.android.server.telecom.bluetooth.BluetoothRouteManager;
 import com.android.server.telecom.bluetooth.BluetoothStateReceiver;
@@ -41,15 +40,21 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
 
 @RunWith(JUnit4.class)
 public class BluetoothDeviceManagerTest extends TelecomTestCase {
     @Mock BluetoothRouteManager mRouteManager;
     @Mock BluetoothHeadsetProxy mHeadsetProxy;
     @Mock BluetoothAdapterProxy mAdapterProxy;
+    @Mock BluetoothHearingAid mBluetoothHearingAid;
 
     BluetoothDeviceManager mBluetoothDeviceManager;
     BluetoothProfile.ServiceListener serviceListenerUnderTest;
@@ -58,18 +63,24 @@
     private BluetoothDevice device1;
     private BluetoothDevice device2;
     private BluetoothDevice device3;
+    private BluetoothDevice device4;
 
     @Override
     @Before
     public void setUp() throws Exception {
         super.setUp();
         device1 = makeBluetoothDevice("00:00:00:00:00:01");
+        // hearing aid
         device2 = makeBluetoothDevice("00:00:00:00:00:02");
         device3 = makeBluetoothDevice("00:00:00:00:00:03");
+        // hearing aid
+        device4 = makeBluetoothDevice("00:00:00:00:00:04");
+
+        when(mBluetoothHearingAid.getHiSyncId(device2)).thenReturn(100L);
+        when(mBluetoothHearingAid.getHiSyncId(device4)).thenReturn(100L);
 
         mContext = mComponentContextFixture.getTestDouble().getApplicationContext();
-        mBluetoothDeviceManager = new BluetoothDeviceManager(mContext, mAdapterProxy,
-                new TelecomSystem.SyncRoot() { });
+        mBluetoothDeviceManager = new BluetoothDeviceManager(mContext, mAdapterProxy);
         mBluetoothDeviceManager.setBluetoothRouteManager(mRouteManager);
 
         ArgumentCaptor<BluetoothProfile.ServiceListener> serviceCaptor =
@@ -82,29 +93,30 @@
                 null /* route mgr not needed here */);
 
         mBluetoothDeviceManager.setHeadsetServiceForTesting(mHeadsetProxy);
+        mBluetoothDeviceManager.setHearingAidServiceForTesting(mBluetoothHearingAid);
     }
 
     @SmallTest
     @Test
     public void testSingleDeviceConnectAndDisconnect() {
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, false));
         assertEquals(1, mBluetoothDeviceManager.getNumConnectedDevices());
-        assertEquals(device1.getAddress(),
-                mBluetoothDeviceManager.getMostRecentlyConnectedDevice(null));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device1));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device1, false));
         assertEquals(0, mBluetoothDeviceManager.getNumConnectedDevices());
-        assertNull(mBluetoothDeviceManager.getMostRecentlyConnectedDevice(null));
     }
 
     @SmallTest
     @Test
     public void testAddDeviceFailsWhenServicesAreNull() {
         mBluetoothDeviceManager.setHeadsetServiceForTesting(null);
+        mBluetoothDeviceManager.setHearingAidServiceForTesting(null);
 
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, false));
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, true));
 
         assertEquals(0, mBluetoothDeviceManager.getNumConnectedDevices());
     }
@@ -113,60 +125,107 @@
     @Test
     public void testMultiDeviceConnectAndDisconnect() {
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, false));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, true));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device1));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device1, false));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3));
-        receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3, false));
         assertEquals(2, mBluetoothDeviceManager.getNumConnectedDevices());
-        assertEquals(device3.getAddress(),
-                mBluetoothDeviceManager.getMostRecentlyConnectedDevice(null));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device3));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device3, false));
         assertEquals(1, mBluetoothDeviceManager.getNumConnectedDevices());
-        assertEquals(device2.getAddress(),
-                mBluetoothDeviceManager.getMostRecentlyConnectedDevice(null));
     }
 
     @SmallTest
     @Test
-    public void testExclusionaryGetRecentDevices() {
+    public void testHearingAidDedup() {
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, false));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, true));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_DISCONNECTED, device1));
-        receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3));
-        receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2));
-        assertEquals(2, mBluetoothDeviceManager.getNumConnectedDevices());
-        assertEquals(device2.getAddress(),
-                mBluetoothDeviceManager.getMostRecentlyConnectedDevice(device3.getAddress()));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device4, true));
+        assertEquals(3, mBluetoothDeviceManager.getNumConnectedDevices());
+        assertEquals(2, mBluetoothDeviceManager.getUniqueConnectedDevices().size());
     }
 
     @SmallTest
     @Test
     public void testHeadsetServiceDisconnect() {
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1));
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, false));
         receiverUnderTest.onReceive(mContext,
-                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2));
-        serviceListenerUnderTest.onServiceDisconnected(0);
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3, false));
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, true));
+        serviceListenerUnderTest.onServiceDisconnected(BluetoothProfile.HEADSET);
 
+        verify(mRouteManager).onActiveDeviceChanged(isNull(), eq(false));
         verify(mRouteManager).onDeviceLost(device1.getAddress());
-        verify(mRouteManager).onDeviceLost(device2.getAddress());
+        verify(mRouteManager).onDeviceLost(device3.getAddress());
+        verify(mRouteManager, never()).onDeviceLost(device2.getAddress());
         assertNull(mBluetoothDeviceManager.getHeadsetService());
-        assertEquals(0, mBluetoothDeviceManager.getNumConnectedDevices());
+        assertEquals(1, mBluetoothDeviceManager.getNumConnectedDevices());
     }
 
-    private Intent buildConnectionActionIntent(int state, BluetoothDevice device) {
-        Intent i = new Intent(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
+    @SmallTest
+    @Test
+    public void testHearingAidServiceDisconnect() {
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, false));
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3, false));
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, true));
+        serviceListenerUnderTest.onServiceDisconnected(BluetoothProfile.HEARING_AID);
+
+        verify(mRouteManager).onActiveDeviceChanged(isNull(), eq(true));
+        verify(mRouteManager).onDeviceLost(device2.getAddress());
+        verify(mRouteManager, never()).onDeviceLost(device1.getAddress());
+        verify(mRouteManager, never()).onDeviceLost(device3.getAddress());
+        assertNull(mBluetoothDeviceManager.getHearingAidService());
+        assertEquals(2, mBluetoothDeviceManager.getNumConnectedDevices());
+    }
+
+    @SmallTest
+    @Test
+    public void testConnectDisconnectAudioHeadset() {
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, false));
+        when(mHeadsetProxy.setActiveDevice(nullable(BluetoothDevice.class))).thenReturn(true);
+        mBluetoothDeviceManager.connectAudio(device1.getAddress());
+        verify(mHeadsetProxy).setActiveDevice(device1);
+        verify(mHeadsetProxy).connectAudio();
+        verify(mBluetoothHearingAid, never()).setActiveDevice(nullable(BluetoothDevice.class));
+
+        mBluetoothDeviceManager.disconnectAudio();
+        verify(mHeadsetProxy).disconnectAudio();
+    }
+
+    @SmallTest
+    @Test
+    public void testConnectDisconnectAudioHearingAid() {
+        receiverUnderTest.onReceive(mContext,
+                buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, true));
+        mBluetoothDeviceManager.connectAudio(device2.getAddress());
+        verify(mBluetoothHearingAid).setActiveDevice(device2);
+        verify(mHeadsetProxy, never()).connectAudio();
+        verify(mHeadsetProxy, never()).setActiveDevice(nullable(BluetoothDevice.class));
+
+        when(mBluetoothHearingAid.getActiveDevices()).thenReturn(Arrays.asList(device2, null));
+
+        mBluetoothDeviceManager.disconnectAudio();
+        verify(mBluetoothHearingAid).setActiveDevice(null);
+        verify(mHeadsetProxy).disconnectAudio();
+    }
+
+    private Intent buildConnectionActionIntent(int state, BluetoothDevice device,
+            boolean isHearingAid) {
+        Intent i = new Intent(isHearingAid
+                ? BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED
+                : BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
         i.putExtra(BluetoothHeadset.EXTRA_STATE, state);
         i.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
         return i;
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothPhoneServiceTest.java b/tests/src/com/android/server/telecom/tests/BluetoothPhoneServiceTest.java
index a5feab7..a960d91 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothPhoneServiceTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothPhoneServiceTest.java
@@ -309,17 +309,18 @@
 
         mBluetoothPhoneService.mBinder.queryPhoneState();
         verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE),
-                eq(""), eq(128));
+                eq(""), eq(128), nullable(String.class));
         when(parentCall.wasConferencePreviouslyMerged()).thenReturn(true);
         mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(parentCall);
         verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128));
+                eq(""), eq(128), nullable(String.class));
         when(mMockCallsManager.getHeldCall()).thenReturn(null);
         // Spurious call to onIsConferencedChanged.
         mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(parentCall);
         // Make sure the call has only occurred collectively 2 times (not on the third)
         verify(mMockBluetoothHeadset, times(2)).phoneStateChanged(any(int.class),
-                any(int.class), any(int.class), nullable(String.class), any(int.class));
+                any(int.class), any(int.class), nullable(String.class), any(int.class),
+                nullable(String.class));
     }
 
     @MediumTest
@@ -611,7 +612,7 @@
         mBluetoothPhoneService.mBinder.queryPhoneState();
 
         verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
-                eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown));
+                eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
     }
 
     @MediumTest
@@ -632,7 +633,7 @@
 
         mBluetoothPhoneService.mBinder.queryPhoneState();
         verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128));
+                eq(""), eq(128), nullable(String.class));
     }
 
     @MediumTest
@@ -681,7 +682,8 @@
                 CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD);
 
         verify(mMockCallsManager).disconnectCall(eq(activeCall));
-        verify(mMockCallsManager).unholdCall(eq(heldCall));
+        // Call unhold will occur as part of CallsManager auto-unholding the background call on its
+        // own.
         assertEquals(didProcess, true);
     }
 
@@ -771,7 +773,7 @@
 
         verify(parentCall).swapConference();
         verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE), eq(""),
-                eq(128));
+                eq(128), nullable(String.class));
         assertEquals(didProcess, true);
     }
 
@@ -785,7 +787,7 @@
         mBluetoothPhoneService.mCallsManagerListener.onCallAdded(ringingCall);
 
         verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
-                eq("555000"), eq(PhoneNumberUtils.TOA_Unknown));
+                eq("555000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
 
     }
 
@@ -807,7 +809,7 @@
         mBluetoothPhoneService.mCallsManagerListener.onCallAdded(parentCall);
 
         verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE),
-                eq(""), eq(128));
+                eq(""), eq(128), nullable(String.class));
 
     }
 
@@ -820,7 +822,7 @@
         mBluetoothPhoneService.mCallsManagerListener.onCallRemoved(activeCall);
 
         verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128));
+                eq(""), eq(128), nullable(String.class));
     }
 
     @MediumTest
@@ -838,7 +840,7 @@
                 CallState.ACTIVE, CallState.ON_HOLD);
 
         verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt());
+                anyString(), anyInt(), nullable(String.class));
     }
 
     @MediumTest
@@ -850,7 +852,7 @@
                 CallState.CONNECTING, CallState.DIALING);
 
         verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt());
+                anyString(), anyInt(), nullable(String.class));
     }
 
     @MediumTest
@@ -861,8 +863,10 @@
         mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(outgoingCall,
                 CallState.NEW, CallState.DIALING);
 
-        verify(mMockBluetoothHeadset).phoneStateChanged(0, 0, CALL_STATE_DIALING, "", 128);
-        verify(mMockBluetoothHeadset).phoneStateChanged(0, 0, CALL_STATE_ALERTING, "", 128);
+        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_DIALING),
+                eq(""), eq(128), nullable(String.class));
+        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_ALERTING),
+                eq(""), eq(128), nullable(String.class));
     }
 
     @MediumTest
@@ -873,16 +877,16 @@
         mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(disconnectedCall,
                 CallState.DISCONNECTING, CallState.DISCONNECTED);
         verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_DISCONNECTED),
-                eq(""), eq(128));
+                eq(""), eq(128), nullable(String.class));
 
         doReturn(false).when(mMockCallsManager).hasOnlyDisconnectedCalls();
         mBluetoothPhoneService.mCallsManagerListener.onDisconnectedTonePlaying(true);
         verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_DISCONNECTED),
-                eq(""), eq(128));
+                eq(""), eq(128), nullable(String.class));
 
         mBluetoothPhoneService.mCallsManagerListener.onDisconnectedTonePlaying(false);
         verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128));
+                eq(""), eq(128), nullable(String.class));
     }
 
     @MediumTest
@@ -893,7 +897,7 @@
         mBluetoothPhoneService.mCallsManagerListener.onCallAdded(ringingCall);
 
         verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
-                eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown));
+                eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
 
         //Switch to active
         doReturn(null).when(mMockCallsManager).getRingingCall();
@@ -903,7 +907,7 @@
                 CallState.RINGING, CallState.ACTIVE);
 
         verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
-                eq(""), eq(128));
+                eq(""), eq(128), nullable(String.class));
     }
 
     @MediumTest
@@ -916,7 +920,7 @@
                 CallState.ACTIVE, CallState.ON_HOLD);
 
         verify(mMockBluetoothHeadset, never()).phoneStateChanged(eq(0), eq(2), eq(CALL_STATE_HELD),
-                eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown));
+                eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
     }
 
     @MediumTest
@@ -942,18 +946,18 @@
         // CDMA "conference"
         mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(activeCall);
         verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt());
+                anyString(), anyInt(), nullable(String.class));
         mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(heldCall);
         verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt());
+                anyString(), anyInt(), nullable(String.class));
         mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(parentCall);
         verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
-                anyString(), anyInt());
+                anyString(), anyInt(), nullable(String.class));
 
         calls.add(heldCall);
         mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(parentCall);
         verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE),
-                eq(""), eq(128));
+                eq(""), eq(128), nullable(String.class));
     }
 
     @MediumTest
@@ -967,7 +971,7 @@
         mBluetoothPhoneService.mBluetoothAdapterReceiver.onReceive(mContext, intent);
 
         verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
-                eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown));
+                eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
     }
 
     private void addCallCapability(Call call, int capability) {
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
index 5b45828..93c2909 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
@@ -18,6 +18,7 @@
 
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothHearingAid;
 import android.content.ContentResolver;
 import android.os.Parcel;
 import android.telecom.Log;
@@ -37,13 +38,14 @@
 import org.mockito.Mock;
 
 import java.util.Arrays;
-import java.util.Objects;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -55,9 +57,11 @@
     static final BluetoothDevice DEVICE1 = makeBluetoothDevice("00:00:00:00:00:01");
     static final BluetoothDevice DEVICE2 = makeBluetoothDevice("00:00:00:00:00:02");
     static final BluetoothDevice DEVICE3 = makeBluetoothDevice("00:00:00:00:00:03");
+    static final BluetoothDevice HEARING_AID_DEVICE = makeBluetoothDevice("00:00:00:00:00:04");
 
     @Mock private BluetoothDeviceManager mDeviceManager;
     @Mock private BluetoothHeadsetProxy mHeadsetProxy;
+    @Mock private BluetoothHearingAid mBluetoothHearingAid;
     @Mock private Timeouts.Adapter mTimeoutsAdapter;
     @Mock private BluetoothRouteManager.BluetoothStateListener mListener;
 
@@ -72,7 +76,7 @@
     public void testConnectHfpRetryWhileNotConnected() {
         BluetoothRouteManager sm = setupStateMachine(
                 BluetoothRouteManager.AUDIO_OFF_STATE_NAME, null);
-        setupConnectedDevices(new BluetoothDevice[]{DEVICE1}, null);
+        setupConnectedDevices(new BluetoothDevice[]{DEVICE1}, null, null, null);
         when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
                 nullable(ContentResolver.class))).thenReturn(0L);
         when(mHeadsetProxy.connectAudio()).thenReturn(false);
@@ -91,10 +95,45 @@
 
     @SmallTest
     @Test
+    public void testAmbiguousActiveDevice() {
+        BluetoothRouteManager sm = setupStateMachine(
+                BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX, DEVICE1);
+        setupConnectedDevices(new BluetoothDevice[]{DEVICE1},
+                new BluetoothDevice[]{HEARING_AID_DEVICE}, DEVICE1, HEARING_AID_DEVICE);
+        sm.onActiveDeviceChanged(DEVICE1, false);
+        sm.onActiveDeviceChanged(HEARING_AID_DEVICE, true);
+        executeRoutingAction(sm, BluetoothRouteManager.BT_AUDIO_LOST, DEVICE1.getAddress());
+
+        verifyConnectionAttempt(HEARING_AID_DEVICE, 0);
+        verifyConnectionAttempt(DEVICE1, 0);
+        assertEquals(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX
+                        + ":" + HEARING_AID_DEVICE.getAddress(),
+                sm.getCurrentState().getName());
+        sm.quitNow();
+    }
+
+    @SmallTest
+    @Test
+    public void testAudioOnDeviceWithScoOffActiveDevice() {
+        BluetoothRouteManager sm = setupStateMachine(
+                BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX, DEVICE1);
+        setupConnectedDevices(new BluetoothDevice[]{DEVICE1}, null, DEVICE1, null);
+        when(mHeadsetProxy.getAudioState(DEVICE1))
+                .thenReturn(BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
+        executeRoutingAction(sm, BluetoothRouteManager.BT_AUDIO_LOST, DEVICE1.getAddress());
+
+        verifyConnectionAttempt(DEVICE1, 0);
+        assertEquals(BluetoothRouteManager.AUDIO_OFF_STATE_NAME,
+                sm.getCurrentState().getName());
+        sm.quitNow();
+    }
+
+    @SmallTest
+    @Test
     public void testConnectHfpRetryWhileConnectedToAnotherDevice() {
         BluetoothRouteManager sm = setupStateMachine(
                 BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX, DEVICE1);
-        setupConnectedDevices(new BluetoothDevice[]{DEVICE1, DEVICE2}, null);
+        setupConnectedDevices(new BluetoothDevice[]{DEVICE1, DEVICE2}, null, null, null);
         when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
                 nullable(ContentResolver.class))).thenReturn(0L);
         when(mHeadsetProxy.connectAudio()).thenReturn(false);
@@ -126,22 +165,28 @@
         return sm;
     }
 
-    private void setupConnectedDevices(BluetoothDevice[] devices, BluetoothDevice activeDevice) {
-        when(mDeviceManager.getNumConnectedDevices()).thenReturn(devices.length);
-        when(mDeviceManager.getConnectedDevices()).thenReturn(Arrays.asList(devices));
-        when(mHeadsetProxy.getConnectedDevices()).thenReturn(Arrays.asList(devices));
-        if (activeDevice != null) {
-            when(mHeadsetProxy.getAudioState(eq(activeDevice)))
-                    .thenReturn(BluetoothHeadset.STATE_AUDIO_CONNECTED);
-        }
-        doAnswer(invocation -> {
-            BluetoothDevice first = getFirstExcluding(devices,
-                    (String) invocation.getArguments()[0]);
-            return first == null ? null : first.getAddress();
-        }).when(mDeviceManager).getMostRecentlyConnectedDevice(nullable(String.class));
-        for (BluetoothDevice device : devices) {
-            when(mDeviceManager.getDeviceFromAddress(device.getAddress())).thenReturn(device);
-        }
+    private void setupConnectedDevices(BluetoothDevice[] hfpDevices,
+            BluetoothDevice[] hearingAidDevices,
+            BluetoothDevice hfpActiveDevice, BluetoothDevice hearingAidActiveDevice) {
+        if (hfpDevices == null) hfpDevices = new BluetoothDevice[]{};
+        if (hearingAidDevices == null) hearingAidDevices = new BluetoothDevice[]{};
+
+        when(mDeviceManager.getNumConnectedDevices()).thenReturn(
+                hfpDevices.length + hearingAidDevices.length);
+        List<BluetoothDevice> allDevices = Stream.concat(
+                Arrays.stream(hfpDevices), Arrays.stream(hearingAidDevices))
+                .collect(Collectors.toList());
+
+        when(mDeviceManager.getConnectedDevices()).thenReturn(allDevices);
+        when(mHeadsetProxy.getConnectedDevices()).thenReturn(Arrays.asList(hfpDevices));
+        when(mHeadsetProxy.getActiveDevice()).thenReturn(hfpActiveDevice);
+        when(mHeadsetProxy.getAudioState(hfpActiveDevice))
+                .thenReturn(BluetoothHeadset.STATE_AUDIO_CONNECTED);
+
+        when(mBluetoothHearingAid.getConnectedDevices())
+                .thenReturn(Arrays.asList(hearingAidDevices));
+        when(mBluetoothHearingAid.getActiveDevices())
+                .thenReturn(Arrays.asList(hearingAidActiveDevice, null));
     }
 
     static void executeRoutingAction(BluetoothRouteManager brm, int message, String
@@ -165,6 +210,7 @@
     private void resetMocks() {
         reset(mDeviceManager, mListener, mHeadsetProxy, mTimeoutsAdapter);
         when(mDeviceManager.getHeadsetService()).thenReturn(mHeadsetProxy);
+        when(mDeviceManager.getHearingAidService()).thenReturn(mBluetoothHearingAid);
         when(mHeadsetProxy.connectAudio()).thenReturn(true);
         when(mHeadsetProxy.setActiveDevice(nullable(BluetoothDevice.class))).thenReturn(true);
         when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
@@ -174,17 +220,6 @@
     }
 
     private void verifyConnectionAttempt(BluetoothDevice device, int numTimes) {
-        verify(mHeadsetProxy, times(numTimes)).setActiveDevice(device);
-        verify(mHeadsetProxy, atLeast(numTimes)).connectAudio();
-    }
-
-    private static BluetoothDevice getFirstExcluding(
-            BluetoothDevice[] devices, String excludeAddress) {
-        for (BluetoothDevice x : devices) {
-            if (!Objects.equals(excludeAddress, x.getAddress())) {
-                return x;
-            }
-        }
-        return null;
+        verify(mDeviceManager, times(numTimes)).connectAudio(device.getAddress());
     }
 }
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java b/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java
index e7cd6ee..2584f33 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java
@@ -18,9 +18,12 @@
 
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothHearingAid;
 import android.content.ContentResolver;
+import android.telecom.Log;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.internal.os.SomeArgs;
 import com.android.server.telecom.BluetoothHeadsetProxy;
 import com.android.server.telecom.TelecomSystem;
 import com.android.server.telecom.Timeouts;
@@ -36,19 +39,20 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
-import java.util.Objects;
 
 import static com.android.server.telecom.tests.BluetoothRouteManagerTest.DEVICE1;
 import static com.android.server.telecom.tests.BluetoothRouteManagerTest.DEVICE2;
 import static com.android.server.telecom.tests.BluetoothRouteManagerTest.DEVICE3;
 import static com.android.server.telecom.tests.BluetoothRouteManagerTest.executeRoutingAction;
 import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -56,7 +60,7 @@
 public class BluetoothRouteTransitionTests extends TelecomTestCase {
     private enum ListenerUpdate {
         DEVICE_LIST_CHANGED, ACTIVE_DEVICE_PRESENT, ACTIVE_DEVICE_GONE,
-        AUDIO_CONNECTED, AUDIO_DISCONNECTED
+        AUDIO_CONNECTED, AUDIO_DISCONNECTED, UNEXPECTED_STATE_CHANGE
     }
 
     private static class BluetoothRouteTestParametersBuilder {
@@ -73,6 +77,7 @@
         private BluetoothDevice[] connectedDevices;
         // the active device as returned by BluetoothHeadset#getActiveDevice
         private BluetoothDevice activeDevice = null;
+        private List<BluetoothDevice> hearingAidBtDevices = Collections.emptyList();
 
         public BluetoothRouteTestParametersBuilder setName(String name) {
             this.name = name;
@@ -141,6 +146,12 @@
             return this;
         }
 
+        public BluetoothRouteTestParametersBuilder setHearingAidBtDevices(
+                List<BluetoothDevice> hearingAidBtDevices) {
+            this.hearingAidBtDevices = hearingAidBtDevices;
+            return this;
+        }
+
         public BluetoothRouteTestParameters build() {
             return new BluetoothRouteTestParameters(name,
                     initialBluetoothState,
@@ -153,7 +164,8 @@
                     connectedDevices,
                     messageDevice,
                     audioOnDevice,
-                    activeDevice);
+                    activeDevice,
+                    hearingAidBtDevices);
 
         }
     }
@@ -172,13 +184,15 @@
         public BluetoothDevice[] connectedDevices; // array of connected devices
         // the active device as returned by BluetoothHeadset#getActiveDevice
         private BluetoothDevice activeDevice = null;
+        private List<BluetoothDevice> hearingAidBtDevices;
 
         public BluetoothRouteTestParameters(String name, String initialBluetoothState,
                 BluetoothDevice initialDevice, int messageType, ListenerUpdate[]
                 expectedListenerUpdates, int expectedBluetoothInteraction, BluetoothDevice
                 expectedConnectionDevice, String expectedFinalStateName,
                 BluetoothDevice[] connectedDevices, BluetoothDevice messageDevice,
-                BluetoothDevice audioOnDevice, BluetoothDevice activeDevice) {
+                BluetoothDevice audioOnDevice, BluetoothDevice activeDevice,
+                List<BluetoothDevice> hearingAidBtDevices) {
             this.name = name;
             this.initialBluetoothState = initialBluetoothState;
             this.initialDevice = initialDevice;
@@ -191,6 +205,7 @@
             this.messageDevice = messageDevice;
             this.audioOnDevice = audioOnDevice;
             this.activeDevice = activeDevice;
+            this.hearingAidBtDevices = hearingAidBtDevices;
         }
 
         @Override
@@ -207,6 +222,7 @@
                     ", expectedFinalStateName='" + expectedFinalStateName + '\'' +
                     ", connectedDevices=" + Arrays.toString(connectedDevices) +
                     ", activeDevice='" + activeDevice + '\'' +
+                    ", hearingAidBtDevices ='" + hearingAidBtDevices + '\'' +
                     '}';
         }
     }
@@ -220,6 +236,7 @@
     private final BluetoothRouteTestParameters mParams;
     @Mock private BluetoothDeviceManager mDeviceManager;
     @Mock private BluetoothHeadsetProxy mHeadsetProxy;
+    @Mock private BluetoothHearingAid mBluetoothHearingAid;
     @Mock private Timeouts.Adapter mTimeoutsAdapter;
     @Mock private BluetoothRouteManager.BluetoothStateListener mListener;
 
@@ -241,21 +258,41 @@
 
         setupConnectedDevices(mParams.connectedDevices,
                 mParams.audioOnDevice, mParams.activeDevice);
-        sm.setActiveDeviceCacheForTesting(mParams.activeDevice);
+        sm.setActiveDeviceCacheForTesting(mParams.activeDevice,
+                mParams.hearingAidBtDevices.contains(mParams.messageDevice));
+        if (mParams.initialDevice != null) {
+            doAnswer(invocation -> {
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = Log.createSubsession();
+                args.arg2 = mParams.initialDevice.getAddress();
+                when(mHeadsetProxy.getActiveDevice()).thenReturn(null);
+                sm.sendMessage(BluetoothRouteManager.BT_AUDIO_LOST, args);
+                return true;
+            }).when(mDeviceManager).disconnectAudio();
+        }
 
         // Go through the utility methods for these two messages
         if (mParams.messageType == BluetoothRouteManager.NEW_DEVICE_CONNECTED) {
             sm.onDeviceAdded(mParams.messageDevice.getAddress());
-            sm.onActiveDeviceChanged(mParams.messageDevice);
+            sm.onActiveDeviceChanged(mParams.messageDevice,
+                    mParams.hearingAidBtDevices.contains(mParams.messageDevice));
         } else if (mParams.messageType == BluetoothRouteManager.LOST_DEVICE) {
+            sm.onActiveDeviceChanged(null,
+                    mParams.hearingAidBtDevices.contains(mParams.messageDevice));
+            if (mParams.hearingAidBtDevices.contains(mParams.messageDevice)) {
+                when(mBluetoothHearingAid.getActiveDevices()).thenReturn(Arrays.asList(null, null));
+            } else {
+                when(mHeadsetProxy.getActiveDevice()).thenReturn(null);
+            }
             sm.onDeviceLost(mParams.messageDevice.getAddress());
-            sm.onActiveDeviceChanged(null);
         } else {
             executeRoutingAction(sm, mParams.messageType,
                     mParams.messageDevice == null ? null : mParams.messageDevice.getAddress());
         }
 
         waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
+        waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
+        waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
         assertEquals(mParams.expectedFinalStateName, sm.getCurrentState().getName());
 
         for (ListenerUpdate lu : mParams.expectedListenerUpdates) {
@@ -280,19 +317,15 @@
 
         switch (mParams.expectedBluetoothInteraction) {
             case NONE:
-                verify(mHeadsetProxy, never()).connectAudio();
-                verify(mHeadsetProxy, never()).setActiveDevice(nullable(BluetoothDevice.class));
-                verify(mHeadsetProxy, never()).disconnectAudio();
+                verify(mDeviceManager, never()).connectAudio(nullable(String.class));
                 break;
             case CONNECT:
-                verify(mHeadsetProxy).connectAudio();
-                verify(mHeadsetProxy).setActiveDevice(mParams.expectedConnectionDevice);
-                verify(mHeadsetProxy, never()).disconnectAudio();
+                verify(mDeviceManager).connectAudio(mParams.expectedConnectionDevice.getAddress());
+                verify(mDeviceManager, never()).disconnectAudio();
                 break;
             case DISCONNECT:
-                verify(mHeadsetProxy, never()).connectAudio();
-                verify(mHeadsetProxy, never()).setActiveDevice(nullable(BluetoothDevice.class));
-                verify(mHeadsetProxy).disconnectAudio();
+                verify(mDeviceManager, never()).connectAudio(nullable(String.class));
+                verify(mDeviceManager).disconnectAudio();
                 break;
         }
 
@@ -307,22 +340,22 @@
         when(mHeadsetProxy.getConnectedDevices()).thenReturn(Arrays.asList(devices));
         when(mHeadsetProxy.getActiveDevice()).thenReturn(activeDevice);
         if (audioOnDevice != null) {
-            when(mHeadsetProxy.getAudioState(eq(audioOnDevice)))
+            when(mHeadsetProxy.getActiveDevice()).thenReturn(audioOnDevice);
+            when(mHeadsetProxy.getAudioState(audioOnDevice))
                     .thenReturn(BluetoothHeadset.STATE_AUDIO_CONNECTED);
         }
-        doAnswer(invocation -> {
-            BluetoothDevice first = getFirstExcluding(devices,
-                    (String) invocation.getArguments()[0]);
-            return first == null ? null : first.getAddress();
-        }).when(mDeviceManager).getMostRecentlyConnectedDevice(nullable(String.class));
-        for (BluetoothDevice device : devices) {
-            when(mDeviceManager.getDeviceFromAddress(device.getAddress())).thenReturn(device);
-        }
     }
 
     private BluetoothRouteManager setupStateMachine(String initialState,
             BluetoothDevice initialDevice) {
         resetMocks();
+        when(mDeviceManager.getHeadsetService()).thenReturn(mHeadsetProxy);
+        when(mDeviceManager.getHearingAidService()).thenReturn(mBluetoothHearingAid);
+        when(mDeviceManager.connectAudio(nullable(String.class))).thenReturn(true);
+        when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
+                nullable(ContentResolver.class))).thenReturn(100000L);
+        when(mTimeoutsAdapter.getBluetoothPendingTimeoutMillis(
+                nullable(ContentResolver.class))).thenReturn(100000L);
         BluetoothRouteManager sm = new BluetoothRouteManager(mContext,
                 new TelecomSystem.SyncRoot() { }, mDeviceManager, mTimeoutsAdapter);
         sm.setListener(mListener);
@@ -333,24 +366,7 @@
     }
 
     private void resetMocks() {
-        reset(mDeviceManager, mListener, mHeadsetProxy, mTimeoutsAdapter);
-        when(mDeviceManager.getHeadsetService()).thenReturn(mHeadsetProxy);
-        when(mHeadsetProxy.connectAudio()).thenReturn(true);
-        when(mHeadsetProxy.setActiveDevice(nullable(BluetoothDevice.class))).thenReturn(true);
-        when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
-                nullable(ContentResolver.class))).thenReturn(100000L);
-        when(mTimeoutsAdapter.getBluetoothPendingTimeoutMillis(
-                nullable(ContentResolver.class))).thenReturn(100000L);
-    }
-
-    private static BluetoothDevice getFirstExcluding(
-            BluetoothDevice[] devices, String excludeAddress) {
-        for (BluetoothDevice x : devices) {
-            if (!Objects.equals(excludeAddress, x.getAddress())) {
-                return x;
-            }
-        }
-        return null;
+        clearInvocations(mDeviceManager, mListener, mHeadsetProxy, mTimeoutsAdapter);
     }
 
     @Parameterized.Parameters(name = "{0}")
@@ -390,7 +406,7 @@
                 .setInitialDevice(DEVICE2)
                 .setAudioOnDevice(DEVICE2)
                 .setConnectedDevices(DEVICE2, DEVICE1)
-                .setMessageType(BluetoothRouteManager.HFP_IS_ON)
+                .setMessageType(BluetoothRouteManager.BT_AUDIO_IS_ON)
                 .setMessageDevice(DEVICE2)
                 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED)
                 .setExpectedBluetoothInteraction(NONE)
@@ -404,7 +420,7 @@
                 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX)
                 .setInitialDevice(DEVICE2)
                 .setConnectedDevices(DEVICE2)
-                .setMessageType(BluetoothRouteManager.HFP_LOST)
+                .setMessageType(BluetoothRouteManager.BT_AUDIO_LOST)
                 .setMessageDevice(DEVICE2)
                 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED)
                 .setExpectedBluetoothInteraction(NONE)
@@ -418,7 +434,7 @@
                 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX)
                 .setInitialDevice(DEVICE2)
                 .setConnectedDevices(DEVICE2, DEVICE1, DEVICE3)
-                .setMessageType(BluetoothRouteManager.HFP_LOST)
+                .setMessageType(BluetoothRouteManager.BT_AUDIO_LOST)
                 .setMessageDevice(DEVICE2)
                 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED)
                 .setExpectedBluetoothInteraction(NONE)
@@ -503,7 +519,7 @@
                 .setInitialDevice(DEVICE2)
                 .setConnectedDevices(DEVICE2, DEVICE1)
                 .setAudioOnDevice(DEVICE1)
-                .setMessageType(BluetoothRouteManager.HFP_IS_ON)
+                .setMessageType(BluetoothRouteManager.BT_AUDIO_IS_ON)
                 .setMessageDevice(DEVICE1)
                 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED)
                 .setExpectedBluetoothInteraction(NONE)
@@ -526,6 +542,18 @@
                 .build());
 
         result.add(new BluetoothRouteTestParametersBuilder()
+                .setName("Audio disconnect comes with a null device")
+                .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX)
+                .setInitialDevice(DEVICE2)
+                .setConnectedDevices(DEVICE2)
+                .setMessageType(BluetoothRouteManager.BT_AUDIO_LOST)
+                .setMessageDevice(null)
+                .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED)
+                .setExpectedBluetoothInteraction(NONE)
+                .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME)
+                .build());
+
+        result.add(new BluetoothRouteTestParametersBuilder()
                 .setName("Device gets disconnected while pending. No fallback.")
                 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX)
                 .setInitialDevice(DEVICE2)
@@ -539,6 +567,19 @@
                 .build());
 
         result.add(new BluetoothRouteTestParametersBuilder()
+                .setName("Device gets audio-off while in another device's audio on state")
+                .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX)
+                .setInitialDevice(DEVICE2)
+                .setConnectedDevices(DEVICE2, DEVICE1)
+                .setMessageType(BluetoothRouteManager.BT_AUDIO_LOST)
+                .setMessageDevice(DEVICE1)
+                .setExpectedListenerUpdates(ListenerUpdate.UNEXPECTED_STATE_CHANGE)
+                .setExpectedBluetoothInteraction(NONE)
+                .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX
+                        + ":" + DEVICE2)
+                .build());
+
+        result.add(new BluetoothRouteTestParametersBuilder()
                 .setName("Audio routing requests HFP disconnection while a device is active")
                 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX)
                 .setInitialDevice(DEVICE2)
@@ -565,7 +606,7 @@
                 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_OFF_STATE_NAME)
                 .setInitialDevice(null)
                 .setConnectedDevices(DEVICE2, DEVICE3)
-                .setMessageType(BluetoothRouteManager.HFP_IS_ON)
+                .setMessageType(BluetoothRouteManager.BT_AUDIO_IS_ON)
                 .setMessageDevice(DEVICE3)
                 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED)
                 .setExpectedBluetoothInteraction(NONE)
@@ -573,6 +614,19 @@
                         + ":" + DEVICE3)
                 .build());
 
+        result.add(new BluetoothRouteTestParametersBuilder()
+                .setName("Hearing aid device disconnects with headset present")
+                .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX)
+                .setInitialDevice(DEVICE2)
+                .setConnectedDevices(DEVICE2, DEVICE3)
+                .setHearingAidBtDevices(Collections.singletonList(DEVICE2))
+                .setMessageType(BluetoothRouteManager.LOST_DEVICE)
+                .setMessageDevice(DEVICE2)
+                .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED,
+                        ListenerUpdate.DEVICE_LIST_CHANGED)
+                .setExpectedBluetoothInteraction(NONE)
+                .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME)
+                .build());
         return result;
     }
 }
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java b/tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java
index 5e23dcc..01add22 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java
@@ -77,7 +77,7 @@
             InCallTonePlayer mockInCallTonePlayer = mock(InCallTonePlayer.class);
             doAnswer((invocation2) -> {
                 mCallAudioManager.setIsTonePlaying(true);
-                return null;
+                return true;
             }).when(mockInCallTonePlayer).startTone();
             return mockInCallTonePlayer;
         }).when(mPlayerFactory).createPlayer(anyInt());
@@ -198,13 +198,16 @@
         Call call = createIncomingCall();
         when(call.can(android.telecom.Call.Details.CAPABILITY_SPEED_UP_MT_AUDIO))
                 .thenReturn(true);
+        when(call.getState()).thenReturn(CallState.ANSWERED);
 
         ArgumentCaptor<CallAudioModeStateMachine.MessageArgs> captor =
                 ArgumentCaptor.forClass(CallAudioModeStateMachine.MessageArgs.class);
         // Answer the incoming call
-        mCallAudioManager.onIncomingCallAnswered(call);
+        mCallAudioManager.onCallStateChanged(call, CallState.RINGING, CallState.ANSWERED);
         verify(mCallAudioModeStateMachine).sendMessageWithArgs(
-                eq(CallAudioModeStateMachine.MT_AUDIO_SPEEDUP_FOR_RINGING_CALL), captor.capture());
+                eq(CallAudioModeStateMachine.NEW_ACTIVE_OR_DIALING_CALL), captor.capture());
+        verify(mCallAudioModeStateMachine).sendMessageWithArgs(
+                eq(CallAudioModeStateMachine.NO_MORE_RINGING_CALLS), captor.capture());
         CallAudioModeStateMachine.MessageArgs correctArgs =
                 new CallAudioModeStateMachine.MessageArgs(
                         true, // hasActiveOrDialingCalls
@@ -217,7 +220,7 @@
         assertMessageArgEquality(correctArgs, captor.getValue());
         assertMessageArgEquality(correctArgs, captor.getValue());
         when(call.getState()).thenReturn(CallState.ACTIVE);
-        mCallAudioManager.onCallStateChanged(call, CallState.RINGING, CallState.ACTIVE);
+        mCallAudioManager.onCallStateChanged(call, CallState.ANSWERED, CallState.ACTIVE);
 
         disconnectCall(call);
         stopTone();
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java
index f253d19..56f585f 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java
@@ -22,6 +22,7 @@
 import com.android.server.telecom.CallAudioManager;
 import com.android.server.telecom.CallAudioModeStateMachine;
 import com.android.server.telecom.CallAudioRouteStateMachine;
+import com.android.server.telecom.SystemStateHelper;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -30,9 +31,11 @@
 import org.mockito.Mock;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -40,6 +43,7 @@
 public class CallAudioModeStateMachineTest extends TelecomTestCase {
     private static final int TEST_TIMEOUT = 1000;
 
+    @Mock private SystemStateHelper mSystemStateHelper;
     @Mock private AudioManager mAudioManager;
     @Mock private CallAudioManager mCallAudioManager;
 
@@ -52,7 +56,8 @@
     @SmallTest
     @Test
     public void testNoFocusWhenRingerSilenced() throws Throwable {
-        CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mAudioManager);
+        CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper,
+                mAudioManager);
         sm.setCallAudioManager(mCallAudioManager);
         sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING);
         waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
@@ -83,8 +88,47 @@
 
     @SmallTest
     @Test
+    public void testNoRingWhenDeviceIsAtEar() {
+        CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper,
+                mAudioManager);
+        sm.setCallAudioManager(mCallAudioManager);
+        sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING);
+        sm.sendMessage(CallAudioModeStateMachine.NEW_HOLDING_CALL,
+                new CallAudioModeStateMachine.MessageArgs(
+                        false, // hasActiveOrDialingCalls
+                        false, // hasRingingCalls
+                        true, // hasHoldingCalls
+                        false, // isTonePlaying
+                        false, // foregroundCallIsVoip
+                        null // session
+                ));
+        waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
+        assertEquals(CallAudioModeStateMachine.TONE_HOLD_STATE_NAME, sm.getCurrentStateName());
+        when(mSystemStateHelper.isDeviceAtEar()).thenReturn(true);
+
+        resetMocks();
+        sm.sendMessage(CallAudioModeStateMachine.NEW_RINGING_CALL,
+                new CallAudioModeStateMachine.MessageArgs(
+                        false, // hasActiveOrDialingCalls
+                        true, // hasRingingCalls
+                        true, // hasHoldingCalls
+                        false, // isTonePlaying
+                        false, // foregroundCallIsVoip
+                        null // session
+                ));
+        waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
+
+        verify(mAudioManager, never()).requestAudioFocusForCall(anyInt(), anyInt());
+        verify(mAudioManager, never()).setMode(anyInt());
+        verify(mCallAudioManager, never()).startRinging();
+        verify(mCallAudioManager).startCallWaiting(nullable(String.class));
+    }
+
+    @SmallTest
+    @Test
     public void testRegainFocusWhenHfpIsConnectedSilenced() throws Throwable {
-        CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mAudioManager);
+        CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper,
+                mAudioManager);
         sm.setCallAudioManager(mCallAudioManager);
         sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING);
         waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
@@ -117,7 +161,7 @@
         sm.sendMessage(CallAudioModeStateMachine.RINGER_MODE_CHANGE);
         waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
 
-        verify(mCallAudioManager).startRinging();
+        verify(mCallAudioManager, times(2)).startRinging();
         verify(mAudioManager).requestAudioFocusForCall(AudioManager.STREAM_RING,
                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
         verify(mAudioManager).setMode(AudioManager.MODE_RINGTONE);
@@ -127,6 +171,6 @@
 
 
     private void resetMocks() {
-        reset(mCallAudioManager, mAudioManager);
+        clearInvocations(mCallAudioManager, mAudioManager);
     }
 }
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioModeTransitionTests.java b/tests/src/com/android/server/telecom/tests/CallAudioModeTransitionTests.java
index b8b4859..81339ed 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioModeTransitionTests.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioModeTransitionTests.java
@@ -16,11 +16,13 @@
 
 package com.android.server.telecom.tests;
 
+import android.content.Context;
 import android.media.AudioManager;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.server.telecom.CallAudioManager;
 import com.android.server.telecom.CallAudioModeStateMachine;
+import com.android.server.telecom.SystemStateHelper;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -35,6 +37,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
@@ -95,6 +98,7 @@
 
     private static final int TEST_TIMEOUT = 1000;
 
+    @Mock private SystemStateHelper mSystemStateHelper;
     @Mock private AudioManager mAudioManager;
     @Mock private CallAudioManager mCallAudioManager;
     private final ModeTestParameters mParams;
@@ -112,7 +116,8 @@
     @Test
     @SmallTest
     public void modeTransitionTest() {
-        CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mAudioManager);
+        CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper,
+                mAudioManager);
         sm.setCallAudioManager(mCallAudioManager);
         sm.sendMessage(mParams.initialAudioState);
         waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
@@ -163,11 +168,11 @@
 
         switch (mParams.expectedCallWaitingInteraction) {
             case NO_CHANGE:
-                verify(mCallAudioManager, never()).startCallWaiting();
+                verify(mCallAudioManager, never()).startCallWaiting(nullable(String.class));
                 verify(mCallAudioManager, never()).stopCallWaiting();
                 break;
             case ON:
-                verify(mCallAudioManager).startCallWaiting();
+                verify(mCallAudioManager).startCallWaiting(nullable(String.class));
                 break;
             case OFF:
                 verify(mCallAudioManager).stopCallWaiting();
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
index 9c90d3e..7f289b8 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
@@ -538,12 +538,35 @@
         initializationTestHelper(expectedState, CallAudioRouteStateMachine.EARPIECE_FORCE_DISABLED);
     }
 
+    @SmallTest
+    @Test
+    public void testInitializationWithAvailableButInactiveBtDevice() {
+        CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE,
+                CallAudioState.ROUTE_SPEAKER | CallAudioState.ROUTE_BLUETOOTH
+                        | CallAudioState.ROUTE_EARPIECE);
+        when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(true);
+        when(mockBluetoothRouteManager.hasBtActiveDevice()).thenReturn(false);
+
+        CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine(
+                mContext,
+                mockCallsManager,
+                mockBluetoothRouteManager,
+                mockWiredHeadsetManager,
+                mockStatusBarNotifier,
+                mAudioServiceFactory,
+                CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED);
+        stateMachine.initialize();
+        assertEquals(expectedState, stateMachine.getCurrentCallAudioState());
+    }
+
     private void initializationTestHelper(CallAudioState expectedState,
             int earpieceControl) {
         when(mockWiredHeadsetManager.isPluggedIn()).thenReturn(
                 (expectedState.getSupportedRouteMask() & CallAudioState.ROUTE_WIRED_HEADSET) != 0);
         when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(
                 (expectedState.getSupportedRouteMask() & CallAudioState.ROUTE_BLUETOOTH) != 0);
+        when(mockBluetoothRouteManager.hasBtActiveDevice()).thenReturn(
+                (expectedState.getSupportedRouteMask() & CallAudioState.ROUTE_BLUETOOTH) != 0);
 
         CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine(
                 mContext,
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java
index 19630b1..e63fe9b 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java
@@ -16,6 +16,18 @@
 
 package com.android.server.telecom.tests;
 
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.bluetooth.BluetoothDevice;
 import android.content.Context;
 import android.media.AudioManager;
@@ -26,7 +38,6 @@
 
 import com.android.server.telecom.Call;
 import com.android.server.telecom.CallAudioManager;
-import com.android.server.telecom.CallAudioModeStateMachine;
 import com.android.server.telecom.CallAudioRouteStateMachine;
 import com.android.server.telecom.CallsManager;
 import com.android.server.telecom.ConnectionServiceWrapper;
@@ -41,6 +52,7 @@
 import org.junit.runners.Parameterized;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
@@ -48,21 +60,6 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import java.util.concurrent.CountDownLatch;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.ArgumentMatchers.same;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 @RunWith(Parameterized.class)
 public class CallAudioRouteTransitionTests extends TelecomTestCase {
@@ -191,16 +188,16 @@
     private void setupMocksForParams(final CallAudioRouteStateMachine sm,
             RoutingTestParameters params) {
         // Set up bluetooth and speakerphone state
-        when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(
-                params.initialRoute == CallAudioState.ROUTE_BLUETOOTH);
-        when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(
-                (params.availableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0
-                        || (params.expectedAvailableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0);
-        when(mockBluetoothRouteManager.getConnectedDevices())
-                .thenReturn(params.availableBluetoothDevices);
+        doReturn(params.initialRoute == CallAudioState.ROUTE_BLUETOOTH)
+                .when(mockBluetoothRouteManager).isBluetoothAudioConnectedOrPending();
+        doReturn((params.availableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0
+                || (params.expectedAvailableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0)
+                .when(mockBluetoothRouteManager).isBluetoothAvailable();
+        doReturn(params.availableBluetoothDevices)
+                .when(mockBluetoothRouteManager).getConnectedDevices();
         if (params.initialBluetoothDevice != null) {
-            when(mockBluetoothRouteManager.getBluetoothAudioConnectedDevice())
-                    .thenReturn(params.initialBluetoothDevice);
+            doReturn(params.initialBluetoothDevice)
+                    .when(mockBluetoothRouteManager).getBluetoothAudioConnectedDevice();
         }
 
 
@@ -264,9 +261,8 @@
         }
         waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);
 
-        // Reset mocks to discard stuff from initialization
-        resetMocks();
-        setupMocksForParams(stateMachine, mParams);
+        // Clear invocations on mocks to discard stuff from initialization
+        clearInvocations();
 
         sendActionToStateMachine(stateMachine);
 
@@ -337,11 +333,11 @@
         stateMachine.setCallAudioManager(mockCallAudioManager);
 
         // Set up bluetooth and speakerphone state
-        when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(
-                (mParams.availableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0
-                || (mParams.expectedAvailableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0);
-        when(mockBluetoothRouteManager.getConnectedDevices())
-                .thenReturn(mParams.availableBluetoothDevices);
+        doReturn((mParams.availableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0 ||
+                (mParams.expectedAvailableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0)
+                .when(mockBluetoothRouteManager).isBluetoothAvailable();
+        doReturn(mParams.availableBluetoothDevices)
+                .when(mockBluetoothRouteManager).getConnectedDevices();
         when(mockAudioManager.isSpeakerphoneOn()).thenReturn(
                 mParams.initialRoute == CallAudioState.ROUTE_SPEAKER);
         when(fakeCall.getSupportedAudioRoutes()).thenReturn(mParams.callSupportedRoutes);
@@ -511,7 +507,7 @@
                 CallAudioState.ROUTE_BLUETOOTH, // initialRoute
                 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
                 OPTIONAL, // speakerInteraction
-                OFF, // bluetoothInteraction
+                NONE, // bluetoothInteraction
                 SPECIAL_DISCONNECT_BT_ACTION, // action
                 CallAudioState.ROUTE_EARPIECE, // expectedRoute
                 CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes
@@ -523,7 +519,7 @@
                 CallAudioState.ROUTE_BLUETOOTH, // initialRoute
                 CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou
                 OPTIONAL, // speakerInteraction
-                OFF, // bluetoothInteraction
+                NONE, // bluetoothInteraction
                 SPECIAL_DISCONNECT_BT_ACTION, // action
                 CallAudioState.ROUTE_WIRED_HEADSET, // expectedRoute
                 CallAudioState.ROUTE_WIRED_HEADSET, // expectedAvailableRoutes
@@ -715,7 +711,7 @@
                 CallAudioState.ROUTE_BLUETOOTH, // initialRoute
                 CallAudioState.ROUTE_BLUETOOTH,  // availableRoutes
                 ON, // speakerInteraction
-                OFF, // bluetoothInteraction
+                NONE, // bluetoothInteraction
                 SPECIAL_DISCONNECT_BT_ACTION, // action
                 CallAudioState.ROUTE_SPEAKER, // expectedRoute
                 CallAudioState.ROUTE_SPEAKER, // expectedAvailableRoutes
@@ -727,7 +723,7 @@
                 CallAudioState.ROUTE_BLUETOOTH, // initialRoute
                 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
                 OPTIONAL, // speakerInteraction
-                OFF, // bluetoothInteraction
+                NONE, // bluetoothInteraction
                 CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_GONE, // action
                 CallAudioState.ROUTE_EARPIECE, // expectedRoute
                 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // expectedAvailabl
@@ -777,16 +773,8 @@
                 any(Call.class), any(CallAudioState.class));
     }
 
-    private void resetMocks() {
-        reset(mockAudioManager, mockBluetoothRouteManager, mockCallsManager,
+    private void clearInvocations() {
+        Mockito.clearInvocations(mockAudioManager, mockBluetoothRouteManager, mockCallsManager,
                 mockConnectionServiceWrapper);
-        fakeCall = mock(Call.class);
-        when(mockCallsManager.getForegroundCall()).thenReturn(fakeCall);
-        when(fakeCall.getConnectionService()).thenReturn(mockConnectionServiceWrapper);
-        when(fakeCall.isAlive()).thenReturn(true);
-        when(fakeCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_ALL);
-        when(mockCallsManager.getLock()).thenReturn(mLock);
-        doNothing().when(mockConnectionServiceWrapper).onCallAudioStateChanged(any(Call.class),
-                any(CallAudioState.class));
     }
-}
+}
\ No newline at end of file
diff --git a/tests/src/com/android/server/telecom/tests/CallExtrasTest.java b/tests/src/com/android/server/telecom/tests/CallExtrasTest.java
index 44578c5..b97f819 100644
--- a/tests/src/com/android/server/telecom/tests/CallExtrasTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallExtrasTest.java
@@ -16,6 +16,11 @@
 
 package com.android.server.telecom.tests;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
 import android.os.Bundle;
 import android.telecom.Call;
 import android.telecom.Conference;
@@ -25,6 +30,8 @@
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
 
+import androidx.test.filters.FlakyTest;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -34,11 +41,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
 /**
  * Tests the {@link Connection} and {@link Call} extras functionality.
  */
@@ -398,6 +400,7 @@
      * @throws Exception
      */
     @LargeTest
+    @FlakyTest(bugId = 117751305)
     @Test
     public void testConferenceExtraOperations() throws Exception {
         ParcelableCall call = makeConferenceCall();
diff --git a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
index 690a38a..751e8fb 100644
--- a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
@@ -17,6 +17,20 @@
 package com.android.server.telecom.tests;
 
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.content.ComponentName;
 import android.content.ContentProvider;
 import android.content.ContentValues;
@@ -34,7 +48,6 @@
 import android.os.UserManager;
 import android.provider.CallLog;
 import android.provider.CallLog.Calls;
-import android.support.test.filters.FlakyTest;
 import android.telecom.DisconnectCause;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
@@ -44,6 +57,8 @@
 import android.test.suitebuilder.annotation.MediumTest;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import androidx.test.filters.FlakyTest;
+
 import com.android.server.telecom.Call;
 import com.android.server.telecom.CallLogManager;
 import com.android.server.telecom.CallState;
@@ -52,20 +67,6 @@
 import com.android.server.telecom.PhoneAccountRegistrar;
 import com.android.server.telecom.TelephonyUtil;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -538,6 +539,7 @@
     }
 
     @MediumTest
+    @FlakyTest(bugId = 117751305)
     @Test
     public void testLogCallDirectionIncomingWithMultiUserCapability() {
         when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class)))
diff --git a/tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java b/tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java
new file mode 100644
index 0000000..169c56a
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2018 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 android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.IBinder;
+import android.os.UserHandle;
+import android.telecom.GatewayInfo;
+import android.telecom.PhoneAccountHandle;
+import android.telephony.TelephonyManager;
+import com.android.internal.telecom.ICallRedirectionService;
+import com.android.server.telecom.Call;
+import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.PhoneAccountRegistrar;
+import com.android.server.telecom.SystemStateHelper;
+import com.android.server.telecom.TelecomSystem;
+import com.android.server.telecom.Timeouts;
+
+import com.android.server.telecom.callredirection.CallRedirectionProcessor;
+import com.android.server.telecom.callredirection.CallRedirectionProcessorHelper;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+
+import org.junit.Before;
+
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(JUnit4.class)
+public class CallRedirectionProcessorTest extends TelecomTestCase {
+    @Mock private Context mContext;
+    @Mock private CallsManager mCallsManager;
+    @Mock private PhoneAccountRegistrar mPhoneAccountRegistrar;
+    @Mock private PhoneAccountHandle mPhoneAccountHandle;
+    private TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };
+
+    @Mock private Call mCall;
+
+    @Mock private PackageManager mPackageManager;
+    @Mock private TelephonyManager mTelephonyManager;
+    @Mock private IBinder mBinder;
+    @Mock private ICallRedirectionService mCallRedirectionService;
+
+    @Mock private SystemStateHelper mSystemStateHelper;
+    @Mock private CallRedirectionProcessorHelper mCallRedirectionProcessorHelper;
+
+    @Mock private Uri mHandle;
+    @Mock private GatewayInfo mGatewayInfo;
+    @Mock private UserHandle mUserHandle;
+    @Mock private ContentResolver mContentResolver;
+
+    @Mock private Timeouts.Adapter mTimeoutsAdapter;
+
+    private static final String USER_DEFINED_PKG_NAME = "user_defined_pkg";
+    private static final String USER_DEFINED_CLS_NAME = "user_defined_cls";
+    private static final String CARRIER_PKG_NAME = "carrier_pkg";
+    private static final String CARRIER_CLS_NAME = "carrier_cls";
+
+    private static final long HANDLER_TIMEOUT_DELAY = 5000;
+    private static final long USER_DEFINED_SHORT_TIMEOUT_MS = 1200;
+    private static final long CARRIER_SHORT_TIMEOUT_MS = 400;
+    private static final long CODE_EXECUTION_DELAY = 500;
+
+    // TODO integerate with a test user-defined service
+    private static final ComponentName USER_DEFINED_SERVICE_TEST_COMPONENT_NAME =
+            new ComponentName(USER_DEFINED_PKG_NAME, USER_DEFINED_CLS_NAME);
+    // TODO integerate with a test carrier service
+    private static final ComponentName CARRIER_SERVICE_TEST_COMPONENT_NAME =
+            new ComponentName(CARRIER_PKG_NAME, CARRIER_CLS_NAME);
+
+    private static final boolean SPEAKER_PHONE_ON = true;
+    private static final int VIDEO_STATE = 0;
+
+    private CallRedirectionProcessor mProcessor;
+
+    @Override
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        when(mCall.getTargetPhoneAccount()).thenReturn(mPhoneAccountHandle);
+        when(mCallsManager.getCurrentUserHandle()).thenReturn(UserHandle.CURRENT);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mContext.getContentResolver()).thenReturn(mContentResolver);
+        doReturn(mCallRedirectionService).when(mBinder).queryLocalInterface(anyString());
+        when(mCallsManager.getSystemStateHelper()).thenReturn(mSystemStateHelper);
+        when(mCallsManager.getTimeoutsAdapter()).thenReturn(mTimeoutsAdapter);
+        when(mTimeoutsAdapter.getUserDefinedCallRedirectionTimeoutMillis(mContentResolver))
+                .thenReturn(USER_DEFINED_SHORT_TIMEOUT_MS);
+        when(mTimeoutsAdapter.getCarrierCallRedirectionTimeoutMillis(mContentResolver))
+                .thenReturn(CARRIER_SHORT_TIMEOUT_MS);
+        when(mCallsManager.getLock()).thenReturn(mLock);
+        when(mCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
+        when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
+        when(mTelephonyManager.getNetworkCountryIso()).thenReturn("");
+        when(mContext.bindServiceAsUser(nullable(Intent.class), nullable(ServiceConnection.class),
+                anyInt(), eq(UserHandle.CURRENT))).thenReturn(true);
+    }
+
+    private void setIsInCarMode(boolean isInCarMode) {
+        when(mSystemStateHelper.isCarMode()).thenReturn(isInCarMode);
+    }
+
+    private void enableUserDefinedCallRedirectionService() {
+        when(mCallRedirectionProcessorHelper.getUserDefinedCallRedirectionService()).thenReturn(
+                USER_DEFINED_SERVICE_TEST_COMPONENT_NAME);
+    }
+
+    private void enableCarrierCallRedirectionService() {
+        when(mCallRedirectionProcessorHelper.getCarrierCallRedirectionService(
+                any(PhoneAccountHandle.class))).thenReturn(CARRIER_SERVICE_TEST_COMPONENT_NAME);
+    }
+
+    private void disableUserDefinedCallRedirectionService() {
+        when(mCallRedirectionProcessorHelper.getUserDefinedCallRedirectionService()).thenReturn(
+                null);
+    }
+
+    private void disableCarrierCallRedirectionService() {
+        when(mCallRedirectionProcessorHelper.getCarrierCallRedirectionService(any())).thenReturn(
+                null);
+    }
+
+    private void startProcessWithNoGateWayInfo() {
+        mProcessor = new CallRedirectionProcessor(mContext, mCallsManager, mCall, mHandle,
+                mPhoneAccountRegistrar, null, SPEAKER_PHONE_ON, VIDEO_STATE);
+        mProcessor.setCallRedirectionServiceHelper(mCallRedirectionProcessorHelper);
+    }
+
+    private void startProcessWithGateWayInfo() {
+        mProcessor = new CallRedirectionProcessor(mContext, mCallsManager, mCall, mHandle,
+                mPhoneAccountRegistrar, mGatewayInfo, SPEAKER_PHONE_ON, VIDEO_STATE);
+        mProcessor.setCallRedirectionServiceHelper(mCallRedirectionProcessorHelper);
+    }
+
+    @Test
+    public void testNoUserDefinedServiceNoCarrierSerivce() {
+        startProcessWithNoGateWayInfo();
+        disableUserDefinedCallRedirectionService();
+        disableCarrierCallRedirectionService();
+        mProcessor.performCallRedirection();
+        verify(mContext, times(0)).bindServiceAsUser(any(Intent.class),
+                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), eq(mHandle),
+                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
+                eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION));
+    }
+
+    @Test
+    public void testCarrierServiceTimeoutNoUserDefinedService() throws Exception {
+        startProcessWithNoGateWayInfo();
+        // To make sure tests are not flaky, clean all the previous handler messages
+        waitForHandlerAction(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY);
+        disableUserDefinedCallRedirectionService();
+        enableCarrierCallRedirectionService();
+        mProcessor.performCallRedirection();
+        verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
+                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+        verify(mCallsManager, times(0)).onCallRedirectionComplete(eq(mCall), any(),
+                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
+                eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION));
+        waitForHandlerActionDelayed(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY,
+                CARRIER_SHORT_TIMEOUT_MS + CODE_EXECUTION_DELAY);
+        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), any(),
+                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
+                eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION));
+    }
+
+    @Test
+    public void testUserDefinedServiceTimeoutNoCarrierService() throws Exception {
+        startProcessWithNoGateWayInfo();
+        // To make sure tests are not flaky, clean all the previous handler messages
+        waitForHandlerAction(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY);
+        enableUserDefinedCallRedirectionService();
+        disableCarrierCallRedirectionService();
+        mProcessor.performCallRedirection();
+        verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
+                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+        verify(mCallsManager, times(0)).onCallRedirectionComplete(eq(mCall), any(),
+                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
+                eq(false), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
+
+        // Test it is waiting for a User-defined timeout, not a Carrier timeout
+        Thread.sleep(CARRIER_SHORT_TIMEOUT_MS + CODE_EXECUTION_DELAY);
+        verify(mCallsManager, times(0)).onCallRedirectionComplete(eq(mCall), any(),
+                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
+                eq(false), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
+
+        // Wait for the rest of user-defined timeout time.
+        waitForHandlerActionDelayed(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY,
+                USER_DEFINED_SHORT_TIMEOUT_MS - CARRIER_SHORT_TIMEOUT_MS + CODE_EXECUTION_DELAY);
+        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), any(),
+                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
+                eq(true), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
+    }
+
+    @Test
+    public void testUserDefinedServiceTimeoutAndCarrierServiceTimeout() throws Exception {
+        startProcessWithNoGateWayInfo();
+        // To make sure tests are not flaky, clean all the previous handler messages
+        waitForHandlerAction(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY);
+        enableUserDefinedCallRedirectionService();
+        enableCarrierCallRedirectionService();
+        mProcessor.performCallRedirection();
+
+        verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
+                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+        verify(mCallsManager, times(0)).onCallRedirectionComplete(eq(mCall), any(),
+                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
+                eq(false), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
+
+        // Test it is waiting for a User-defined timeout, not a Carrier timeout
+        Thread.sleep(CARRIER_SHORT_TIMEOUT_MS + CODE_EXECUTION_DELAY);
+        verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
+                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+        verify(mCallsManager, times(0)).onCallRedirectionComplete(eq(mCall), any(),
+                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
+                eq(false), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
+
+        // Wait for the rest of user-defined timeout time.
+        waitForHandlerActionDelayed(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY,
+                USER_DEFINED_SHORT_TIMEOUT_MS - CARRIER_SHORT_TIMEOUT_MS + CODE_EXECUTION_DELAY);
+        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), any(),
+                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
+                eq(true), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
+
+        // Wait for another carrier timeout time, but should not expect any carrier service request
+        // is triggered.
+        Thread.sleep(CARRIER_SHORT_TIMEOUT_MS + CODE_EXECUTION_DELAY);
+        verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
+                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), any(),
+                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
+                eq(true), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
+    }
+
+    @Test
+    public void testProcessGatewayCall() {
+        startProcessWithGateWayInfo();
+        enableUserDefinedCallRedirectionService();
+        enableCarrierCallRedirectionService();
+        mProcessor.performCallRedirection();
+        verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
+                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+        verify(mCallsManager, times(0)).onCallRedirectionComplete(eq(mCall), any(),
+                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
+                eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION));
+        waitForHandlerActionDelayed(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY,
+                CARRIER_SHORT_TIMEOUT_MS + CODE_EXECUTION_DELAY);
+        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), eq(mHandle),
+                eq(mPhoneAccountHandle), eq(mGatewayInfo), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
+                eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION));
+    }
+}
diff --git a/tests/src/com/android/server/telecom/tests/CallScreeningServiceControllerTest.java b/tests/src/com/android/server/telecom/tests/CallScreeningServiceControllerTest.java
new file mode 100644
index 0000000..1a01a95
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/CallScreeningServiceControllerTest.java
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2018 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 android.Manifest;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.net.Uri;
+import android.os.PersistableBundle;
+import android.os.UserHandle;
+import android.provider.CallLog;
+import android.telecom.TelecomManager;
+import android.telephony.CarrierConfigManager;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.internal.telephony.CallerInfo;
+import com.android.server.telecom.Call;
+import com.android.server.telecom.CallScreeningServiceHelper;
+import com.android.server.telecom.CallerInfoLookupHelper;
+import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.ParcelableCallUtils;
+import com.android.server.telecom.PhoneAccountRegistrar;
+import com.android.server.telecom.RoleManagerAdapter;
+import com.android.server.telecom.TelecomServiceImpl;
+import com.android.server.telecom.TelecomSystem;
+import com.android.server.telecom.callfiltering.CallFilterResultCallback;
+import com.android.server.telecom.callfiltering.CallFilteringResult;
+import com.android.server.telecom.callfiltering.CallScreeningServiceController;
+
+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 java.util.Collections;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(JUnit4.class)
+public class CallScreeningServiceControllerTest extends TelecomTestCase {
+
+    @Mock Context mContext;
+    @Mock Call mCall;
+    @Mock private CallFilterResultCallback mCallback;
+    @Mock CallsManager mCallsManager;
+    @Mock RoleManagerAdapter mRoleManagerAdapter;
+    @Mock CarrierConfigManager mCarrierConfigManager;
+    @Mock private TelecomManager mTelecomManager;
+    @Mock PackageManager mPackageManager;
+    @Mock ParcelableCallUtils.Converter mParcelableCallUtilsConverter;
+    @Mock PhoneAccountRegistrar mPhoneAccountRegistrar;
+    @Mock private CallerInfoLookupHelper mCallerInfoLookupHelper;
+
+    CallScreeningServiceHelper.AppLabelProxy mAppLabelProxy =
+            new CallScreeningServiceHelper.AppLabelProxy() {
+        @Override
+        public CharSequence getAppLabel(String packageName) {
+            return APP_NAME;
+        }
+    };
+
+    private ResolveInfo mResolveInfo;
+    private TelecomServiceImpl.SettingsSecureAdapter mSettingsSecureAdapter =
+            spy(new CallScreeningServiceFilterTest.SettingsSecureAdapterFake());
+    private TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };
+
+    private static final String CALL_ID = "u89prgt9ps78y5";
+    private static final Uri TEST_HANDLE = Uri.parse("tel:1235551234");
+    private static final String DEFAULT_DIALER_PACKAGE = "com.android.dialer";
+    private static final String PKG_NAME = "com.android.services.telecom.tests";
+    private static final String CLS_NAME = "CallScreeningService";
+    private static final String APP_NAME = "Screeny McScreenface";
+    private static final ComponentName CARRIER_DEFINED_CALL_SCREENING = new ComponentName(
+            "com.android.carrier", "com.android.carrier.callscreeningserviceimpl");
+    private static final ComponentName DEFAULT_DIALER_CALL_SCREENING = new ComponentName(
+            "com.android.dialer", "com.android.dialer.callscreeningserviceimpl");
+    private static final ComponentName USER_CHOSEN_CALL_SCREENING = new ComponentName(
+            "com.android.userchosen", "com.android.userchosen.callscreeningserviceimpl");
+
+    private static final CallFilteringResult PASS_RESULT = new CallFilteringResult(
+            true, // shouldAllowCall
+            false, // shouldReject
+            true, // shouldAddToCallLog
+            true // shouldShowNotification
+    );
+
+    public static class SettingsSecureAdapterFake implements
+            TelecomServiceImpl.SettingsSecureAdapter {
+        @Override
+        public void putStringForUser(ContentResolver resolver, String name, String value,
+                                     int userHandle) {
+
+        }
+
+        @Override
+        public String getStringForUser(ContentResolver resolver, String name, int userHandle) {
+            return USER_CHOSEN_CALL_SCREENING.flattenToString();
+        }
+    }
+
+    @Override
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        when(mRoleManagerAdapter.getCallCompanionApps()).thenReturn(Collections.emptyList());
+        when(mRoleManagerAdapter.getDefaultCallScreeningApp()).thenReturn(null);
+        when(mRoleManagerAdapter.getCarModeDialerApp()).thenReturn(null);
+        when(mCallsManager.getRoleManagerAdapter()).thenReturn(mRoleManagerAdapter);
+        when(mCallsManager.getCurrentUserHandle()).thenReturn(UserHandle.CURRENT);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mCall.getId()).thenReturn(CALL_ID);
+
+        setCarrierDefinedCallScreeningApplication();
+        when(TelecomManager.from(mContext)).thenReturn(mTelecomManager);
+        when(mTelecomManager.getDefaultDialerPackage()).thenReturn(DEFAULT_DIALER_PACKAGE);
+
+        mResolveInfo =  new ResolveInfo() {{
+            serviceInfo = new ServiceInfo();
+            serviceInfo.packageName = PKG_NAME;
+            serviceInfo.name = CLS_NAME;
+            serviceInfo.permission = Manifest.permission.BIND_SCREENING_SERVICE;
+        }};
+
+        when(mPackageManager.queryIntentServicesAsUser(nullable(Intent.class), anyInt(), anyInt()))
+                .thenReturn(Collections.singletonList(mResolveInfo));
+        when(mParcelableCallUtilsConverter.toParcelableCall(
+                eq(mCall), anyBoolean(), eq(mPhoneAccountRegistrar))).thenReturn(null);
+        when(mContext.bindServiceAsUser(nullable(Intent.class), nullable(ServiceConnection.class),
+                anyInt(), eq(UserHandle.CURRENT))).thenReturn(true);
+        when(mCall.getHandle()).thenReturn(TEST_HANDLE);
+    }
+
+    @SmallTest
+    @Test
+    public void testAllAllowCall() {
+        when(mRoleManagerAdapter.getDefaultCallScreeningApp()).thenReturn(
+                USER_CHOSEN_CALL_SCREENING.getPackageName());
+        CallScreeningServiceController controller = new CallScreeningServiceController(mContext,
+                mCallsManager, mPhoneAccountRegistrar,
+                mParcelableCallUtilsConverter, mLock,
+                mSettingsSecureAdapter, mCallerInfoLookupHelper, mAppLabelProxy);
+
+        controller.startFilterLookup(mCall, mCallback);
+
+        controller.onCallScreeningFilterComplete(mCall, PASS_RESULT,
+                CARRIER_DEFINED_CALL_SCREENING.getPackageName());
+
+        CallerInfoLookupHelper.OnQueryCompleteListener queryListener = verifyLookupStart();
+        CallerInfo callerInfo = new CallerInfo();
+        callerInfo.contactExists = false;
+        queryListener.onCallerInfoQueryComplete(TEST_HANDLE, callerInfo);
+
+        controller.onCallScreeningFilterComplete(mCall, PASS_RESULT,
+                DEFAULT_DIALER_CALL_SCREENING.getPackageName());
+        controller.onCallScreeningFilterComplete(mCall, PASS_RESULT, USER_CHOSEN_CALL_SCREENING
+                .getPackageName());
+
+        verify(mContext, times(3)).bindServiceAsUser(any(Intent.class), any(ServiceConnection
+                        .class),
+                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+                eq(UserHandle.CURRENT));
+
+        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
+    }
+
+    @SmallTest
+    @Test
+    public void testCarrierAllowCallAndContactExists() {
+        CallScreeningServiceController controller = new CallScreeningServiceController(mContext,
+                mCallsManager,
+                mPhoneAccountRegistrar, mParcelableCallUtilsConverter, mLock,
+                mSettingsSecureAdapter, mCallerInfoLookupHelper, mAppLabelProxy);
+
+        controller.startFilterLookup(mCall, mCallback);
+
+        controller.onCallScreeningFilterComplete(mCall, PASS_RESULT,
+                CARRIER_DEFINED_CALL_SCREENING.getPackageName());
+
+        CallerInfoLookupHelper.OnQueryCompleteListener queryListener = verifyLookupStart();
+        CallerInfo callerInfo = new CallerInfo();
+        callerInfo.contactExists = true;
+        queryListener.onCallerInfoQueryComplete(TEST_HANDLE, callerInfo);
+
+        verify(mContext, times(1)).bindServiceAsUser(any(Intent.class), any(ServiceConnection
+                        .class),
+                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+                eq(UserHandle.CURRENT));
+
+        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
+    }
+
+    @SmallTest
+    @Test
+    public void testCarrierCallScreeningRejectCall() {
+        CallScreeningServiceController controller = new CallScreeningServiceController(mContext,
+                mCallsManager,
+                mPhoneAccountRegistrar, mParcelableCallUtilsConverter, mLock,
+                mSettingsSecureAdapter, mCallerInfoLookupHelper, mAppLabelProxy);
+
+        controller.startFilterLookup(mCall, mCallback);
+
+        controller.onCallScreeningFilterComplete(mCall, new CallFilteringResult(
+                false, // shouldAllowCall
+                true, // shouldReject
+                false, // shouldAddToCallLog
+                true, // shouldShowNotification
+                CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE,
+                APP_NAME,
+                CARRIER_DEFINED_CALL_SCREENING.flattenToString()
+        ), CARRIER_DEFINED_CALL_SCREENING.getPackageName());
+
+        verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
+                any(ServiceConnection.class),
+                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+                eq(UserHandle.CURRENT));
+
+        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(new CallFilteringResult(
+                false, // shouldAllowCall
+                true, // shouldReject
+                false, // shouldAddToCallLog
+                true, // shouldShowNotification
+                CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, //callBlockReason
+                APP_NAME, //callScreeningAppName
+                CARRIER_DEFINED_CALL_SCREENING.flattenToString() //callScreeningComponentName
+        )));
+    }
+
+    @SmallTest
+    @Test
+    public void testDefaultDialerRejectCall() {
+        when(mRoleManagerAdapter.getDefaultCallScreeningApp()).thenReturn(
+                USER_CHOSEN_CALL_SCREENING.getPackageName());
+        CallScreeningServiceController controller = new CallScreeningServiceController(mContext,
+                mCallsManager,
+                mPhoneAccountRegistrar, mParcelableCallUtilsConverter, mLock,
+                mSettingsSecureAdapter, mCallerInfoLookupHelper, mAppLabelProxy);
+
+        controller.startFilterLookup(mCall, mCallback);
+
+        controller.onCallScreeningFilterComplete(mCall, PASS_RESULT,
+                CARRIER_DEFINED_CALL_SCREENING.getPackageName());
+
+        CallerInfoLookupHelper.OnQueryCompleteListener queryListener = verifyLookupStart();
+        CallerInfo callerInfo = new CallerInfo();
+        callerInfo.contactExists = false;
+        queryListener.onCallerInfoQueryComplete(TEST_HANDLE, callerInfo);
+
+        controller.onCallScreeningFilterComplete(mCall, new CallFilteringResult(
+                false, // shouldAllowCall
+                true, // shouldReject
+                false, // shouldAddToCallLog
+                true, // shouldShowNotification
+                CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE,
+                APP_NAME,
+                DEFAULT_DIALER_CALL_SCREENING.flattenToString()
+        ), DEFAULT_DIALER_CALL_SCREENING.getPackageName());
+
+        verify(mContext, times(3)).bindServiceAsUser(any(Intent.class),
+                any(ServiceConnection.class),
+                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+                eq(UserHandle.CURRENT));
+
+        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(new CallFilteringResult(
+                false, // shouldAllowCall
+                true, // shouldReject
+                true, // shouldAddToCallLog (we don't allow services to skip call log)
+                true, // shouldShowNotification
+                CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, //callBlockReason
+                APP_NAME, //callScreeningAppName
+                DEFAULT_DIALER_CALL_SCREENING.flattenToString() //callScreeningComponentName
+        )));
+    }
+
+    @SmallTest
+    @Test
+    public void testUserChosenRejectCall() {
+        when(mRoleManagerAdapter.getDefaultCallScreeningApp()).thenReturn(
+                USER_CHOSEN_CALL_SCREENING.getPackageName());
+        CallScreeningServiceController controller = new CallScreeningServiceController(mContext,
+                mCallsManager,
+                mPhoneAccountRegistrar, mParcelableCallUtilsConverter, mLock,
+                mSettingsSecureAdapter, mCallerInfoLookupHelper, mAppLabelProxy);
+
+        controller.startFilterLookup(mCall, mCallback);
+
+        controller.onCallScreeningFilterComplete(mCall, PASS_RESULT,
+                CARRIER_DEFINED_CALL_SCREENING.getPackageName());
+
+        CallerInfoLookupHelper.OnQueryCompleteListener queryListener = verifyLookupStart();
+        CallerInfo callerInfo = new CallerInfo();
+        callerInfo.contactExists = false;
+        queryListener.onCallerInfoQueryComplete(TEST_HANDLE, callerInfo);
+
+        controller.onCallScreeningFilterComplete(mCall, PASS_RESULT,
+                DEFAULT_DIALER_CALL_SCREENING.getPackageName());
+        controller.onCallScreeningFilterComplete(mCall, new CallFilteringResult(
+                false, // shouldAllowCall
+                true, // shouldReject
+                false, // shouldAddToCallLog
+                true, // shouldShowNotification
+                CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE,
+                APP_NAME,
+                USER_CHOSEN_CALL_SCREENING.flattenToString()
+        ), USER_CHOSEN_CALL_SCREENING.getPackageName());
+
+        verify(mContext, times(3)).bindServiceAsUser(any(Intent.class),
+                any(ServiceConnection.class),
+                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+                eq(UserHandle.CURRENT));
+
+        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(new CallFilteringResult(
+                false, // shouldAllowCall
+                true, // shouldReject
+                true, // shouldAddToCallLog (we don't allow services to skip call log)
+                true, // shouldShowNotification
+                CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, //callBlockReason
+                APP_NAME, //callScreeningAppName
+                USER_CHOSEN_CALL_SCREENING.flattenToString() //callScreeningComponentName
+        )));
+    }
+
+    private CallerInfoLookupHelper.OnQueryCompleteListener verifyLookupStart() {
+        return verifyLookupStart(TEST_HANDLE);
+    }
+
+    private CallerInfoLookupHelper.OnQueryCompleteListener verifyLookupStart(Uri handle) {
+
+        ArgumentCaptor<CallerInfoLookupHelper.OnQueryCompleteListener> captor =
+                ArgumentCaptor.forClass(CallerInfoLookupHelper.OnQueryCompleteListener.class);
+        verify(mCallerInfoLookupHelper).startLookup(eq(handle), captor.capture());
+        return captor.getValue();
+    }
+
+    private void setCarrierDefinedCallScreeningApplication() {
+        String carrierDefined = CARRIER_DEFINED_CALL_SCREENING.flattenToString();
+        PersistableBundle bundle = new PersistableBundle();
+        bundle.putString(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING,
+                carrierDefined);
+        when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
+                .thenReturn(mCarrierConfigManager);
+        when(mCarrierConfigManager.getConfig()).thenReturn(bundle);
+    }
+}
diff --git a/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java b/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java
index a319fad..1679e52 100644
--- a/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java
@@ -18,27 +18,32 @@
 
 import android.Manifest;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.graphics.drawable.Icon;
 import android.os.IBinder;
+import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.provider.CallLog;
 import android.telecom.CallScreeningService;
 import android.telecom.ParcelableCall;
+import android.telecom.TelecomManager;
+import android.telephony.CarrierConfigManager;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.internal.telecom.ICallScreeningAdapter;
 import com.android.internal.telecom.ICallScreeningService;
 import com.android.server.telecom.Call;
 import com.android.server.telecom.CallsManager;
-import com.android.server.telecom.DefaultDialerCache;
 import com.android.server.telecom.ParcelableCallUtils;
 import com.android.server.telecom.PhoneAccountRegistrar;
-import com.android.server.telecom.callfiltering.CallFilterResultCallback;
+import com.android.server.telecom.TelecomServiceImpl;
 import com.android.server.telecom.callfiltering.CallFilteringResult;
 import com.android.server.telecom.callfiltering.CallScreeningServiceFilter;
 import com.android.server.telecom.TelecomSystem;
@@ -60,6 +65,7 @@
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -68,22 +74,35 @@
     @Mock Context mContext;
     @Mock CallsManager mCallsManager;
     @Mock PhoneAccountRegistrar mPhoneAccountRegistrar;
-    @Mock DefaultDialerCache mDefaultDialerCache;
     @Mock ParcelableCallUtils.Converter mParcelableCallUtilsConverter;
     private TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };
 
     @Mock Call mCall;
-    @Mock CallFilterResultCallback mCallback;
+    @Mock CallScreeningServiceFilter.CallScreeningFilterResultCallback mCallback;
 
     @Mock PackageManager mPackageManager;
     @Mock IBinder mBinder;
     @Mock ICallScreeningService mCallScreeningService;
+    @Mock CarrierConfigManager mCarrierConfigManager;
+    @Mock private TelecomManager mTelecomManager;
+    private TelecomServiceImpl.SettingsSecureAdapter mSettingsSecureAdapter =
+        spy(new SettingsSecureAdapterFake());
 
     private static final String PKG_NAME = "com.android.services.telecom.tests";
+    private static final String APP_NAME = "TeleTestApp";
     private static final String CLS_NAME = "CallScreeningService";
     private static final ComponentName COMPONENT_NAME = new ComponentName(PKG_NAME, CLS_NAME);
     private static final String CALL_ID = "u89prgt9ps78y5";
-
+    private static final String DEFAULT_DIALER_PACKAGE = "com.android.dialer";
+    private static final ComponentName CARRIER_DEFINED_CALL_SCREENING = new ComponentName(
+        "com.android.carrier", "com.android.carrier.callscreeningserviceimpl");
+    private static final String CARRIER_DEFINED_CALL_SCREENING_APP_NAME = "GMob";
+    private static final ComponentName DEFAULT_DIALER_CALL_SCREENING = new ComponentName(
+        "com.android.dialer", "com.android.dialer.callscreeningserviceimpl");
+    private static final String DEFAULT_DIALER_APP_NAME = "Dialer";
+    private static final ComponentName USER_CHOSEN_CALL_SCREENING = new ComponentName(
+        "com.android.userchosen", "com.android.userchosen.callscreeningserviceimpl");
+    private static final String USER_CHOSEN_CALL_SCREENING_APP_NAME = "UserChosen";
     private ResolveInfo mResolveInfo;
 
     private static final CallFilteringResult PASS_RESULT = new CallFilteringResult(
@@ -95,6 +114,20 @@
 
     private CallScreeningServiceFilter mFilter;
 
+    public static class SettingsSecureAdapterFake implements
+        TelecomServiceImpl.SettingsSecureAdapter {
+        @Override
+        public void putStringForUser(ContentResolver resolver, String name, String value,
+            int userHandle) {
+
+        }
+
+        @Override
+        public String getStringForUser(ContentResolver resolver, String name, int userHandle) {
+            return USER_CHOSEN_CALL_SCREENING.flattenToString();
+        }
+    }
+
     @Override
     @Before
     public void setUp() throws Exception {
@@ -112,10 +145,8 @@
         }};
 
         mFilter = new CallScreeningServiceFilter(mContext, mCallsManager, mPhoneAccountRegistrar,
-                mDefaultDialerCache, mParcelableCallUtilsConverter, mLock);
+                mParcelableCallUtilsConverter, mLock, mSettingsSecureAdapter);
 
-        when(mDefaultDialerCache.getDefaultDialerApplication(eq(UserHandle.USER_CURRENT)))
-                .thenReturn(PKG_NAME);
         when(mPackageManager.queryIntentServicesAsUser(nullable(Intent.class), anyInt(), anyInt()))
                 .thenReturn(Collections.singletonList(mResolveInfo));
         when(mParcelableCallUtilsConverter.toParcelableCall(
@@ -126,11 +157,9 @@
 
     @SmallTest
     @Test
-    public void testNoDefaultDialer() {
-        when(mDefaultDialerCache.getDefaultDialerApplication(eq(UserHandle.USER_CURRENT)))
-                .thenReturn(null);
-        mFilter.startFilterLookup(mCall, mCallback);
-        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
+    public void testNoPackageName() {
+        mFilter.startCallScreeningFilter(mCall, mCallback, null, null);
+        verify(mCallback).onCallScreeningFilterComplete(eq(mCall), eq(PASS_RESULT), eq(null));
     }
 
     @SmallTest
@@ -138,24 +167,24 @@
     public void testNoResolveEntries() {
         when(mPackageManager.queryIntentServicesAsUser(nullable(Intent.class), anyInt(), anyInt()))
                 .thenReturn(Collections.emptyList());
-        mFilter.startFilterLookup(mCall, mCallback);
-        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
+        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME);
+        verify(mCallback).onCallScreeningFilterComplete(eq(mCall), eq(PASS_RESULT), eq(PKG_NAME));
     }
 
     @SmallTest
     @Test
     public void testBadResolveEntry() {
         mResolveInfo.serviceInfo = null;
-        mFilter.startFilterLookup(mCall, mCallback);
-        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
+        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME);
+        verify(mCallback).onCallScreeningFilterComplete(eq(mCall), eq(PASS_RESULT), eq(PKG_NAME));
     }
 
     @SmallTest
     @Test
     public void testPermissionlessFilterService() {
         mResolveInfo.serviceInfo.permission = null;
-        mFilter.startFilterLookup(mCall, mCallback);
-        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
+        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME);
+        verify(mCallback).onCallScreeningFilterComplete(eq(mCall), eq(PASS_RESULT), eq(PKG_NAME));
     }
 
     @SmallTest
@@ -163,8 +192,8 @@
     public void testContextFailToBind() {
         when(mContext.bindServiceAsUser(nullable(Intent.class), nullable(ServiceConnection.class),
                 anyInt(), eq(UserHandle.CURRENT))).thenReturn(false);
-        mFilter.startFilterLookup(mCall, mCallback);
-        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
+        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME);
+        verify(mCallback).onCallScreeningFilterComplete(eq(mCall), eq(PASS_RESULT), eq(PKG_NAME));
     }
 
     @SmallTest
@@ -172,41 +201,117 @@
     public void testExceptionInScreeningService() throws Exception {
         doThrow(new RemoteException()).when(mCallScreeningService).screenCall(
                 nullable(ICallScreeningAdapter.class), nullable(ParcelableCall.class));
-        mFilter.startFilterLookup(mCall, mCallback);
+        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME);
         ServiceConnection serviceConnection = verifyBindingIntent();
         serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
-        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
+        verify(mCallback).onCallScreeningFilterComplete(eq(mCall), eq(PASS_RESULT), eq(PKG_NAME));
     }
 
     @SmallTest
     @Test
     public void testAllowCall() throws Exception {
-        mFilter.startFilterLookup(mCall, mCallback);
+        mFilter.startCallScreeningFilter(mCall, mCallback, PKG_NAME, APP_NAME);
         ServiceConnection serviceConnection = verifyBindingIntent();
         serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
         ICallScreeningAdapter csAdapter = getCallScreeningAdapter();
         csAdapter.allowCall(CALL_ID);
-        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
+        verify(mCallback).onCallScreeningFilterComplete(eq(mCall), eq(PASS_RESULT), eq(PKG_NAME));
     }
 
     @SmallTest
     @Test
-    public void testDisallowCall() throws Exception {
-        mFilter.startFilterLookup(mCall, mCallback);
+    public void testDisallowCallForCarrierDefined() throws Exception {
+        mResolveInfo.serviceInfo.packageName = CARRIER_DEFINED_CALL_SCREENING.getPackageName();
+        mResolveInfo.serviceInfo.name = CARRIER_DEFINED_CALL_SCREENING.getClassName();
+        setCarrierDefinedCallScreeningApplication();
+        when(TelecomManager.from(mContext)).thenReturn(mTelecomManager);
+        when(mTelecomManager.getDefaultDialerPackage()).thenReturn(DEFAULT_DIALER_PACKAGE);
+
+        mFilter.startCallScreeningFilter(mCall, mCallback,
+                CARRIER_DEFINED_CALL_SCREENING.getPackageName(),
+                CARRIER_DEFINED_CALL_SCREENING_APP_NAME);
         ServiceConnection serviceConnection = verifyBindingIntent();
         serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
         ICallScreeningAdapter csAdapter = getCallScreeningAdapter();
         csAdapter.disallowCall(CALL_ID,
                 true, // shouldReject
                 false, // shouldAddToCallLog
-                true // shouldShowNotification
+                true, // shouldShowNotification
+                CARRIER_DEFINED_CALL_SCREENING
         );
-        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(new CallFilteringResult(
+        verify(mCallback).onCallScreeningFilterComplete(eq(mCall), eq(new CallFilteringResult(
                 false, // shouldAllowCall
                 true, // shouldReject
                 false, // shouldAddToCallLog
-                true // shouldShowNotification
-        )));
+                true, // shouldShowNotification
+                CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, //callBlockReason
+                CARRIER_DEFINED_CALL_SCREENING_APP_NAME, //callScreeningAppName
+                CARRIER_DEFINED_CALL_SCREENING.flattenToString() //callScreeningComponentName
+        )), eq(CARRIER_DEFINED_CALL_SCREENING.getPackageName()));
+    }
+
+    @SmallTest
+    @Test
+    public void testDisallowCallForDefaultDialer() throws Exception {
+        mResolveInfo.serviceInfo.packageName = DEFAULT_DIALER_CALL_SCREENING.getPackageName();
+        mResolveInfo.serviceInfo.name = DEFAULT_DIALER_CALL_SCREENING.getClassName();
+        setCarrierDefinedCallScreeningApplication();
+        when(TelecomManager.from(mContext)).thenReturn(mTelecomManager);
+        when(mTelecomManager.getDefaultDialerPackage()).thenReturn(DEFAULT_DIALER_PACKAGE);
+
+        mFilter.startCallScreeningFilter(mCall, mCallback,
+                DEFAULT_DIALER_CALL_SCREENING.getPackageName(),
+                DEFAULT_DIALER_APP_NAME);
+        ServiceConnection serviceConnection = verifyBindingIntent();
+        serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
+        ICallScreeningAdapter csAdapter = getCallScreeningAdapter();
+        csAdapter.disallowCall(CALL_ID,
+            true, // shouldReject
+            false, // shouldAddToCallLog
+            true, // shouldShowNotification
+            DEFAULT_DIALER_CALL_SCREENING
+        );
+        verify(mCallback).onCallScreeningFilterComplete(eq(mCall), eq(new CallFilteringResult(
+            false, // shouldAllowCall
+            true, // shouldReject
+            true, // shouldAddToCallLog
+            true, // shouldShowNotification
+            CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, //callBlockReason
+            DEFAULT_DIALER_APP_NAME, //callScreeningAppName
+            DEFAULT_DIALER_CALL_SCREENING.flattenToString() //callScreeningComponentName
+        )), eq(DEFAULT_DIALER_CALL_SCREENING.getPackageName()));
+    }
+
+    @SmallTest
+    @Test
+    public void testDisallowCallForUserChosen() throws Exception {
+        mResolveInfo.serviceInfo.packageName = USER_CHOSEN_CALL_SCREENING.getPackageName();
+        mResolveInfo.serviceInfo.name = USER_CHOSEN_CALL_SCREENING.getClassName();
+        setCarrierDefinedCallScreeningApplication();
+        when(TelecomManager.from(mContext)).thenReturn(mTelecomManager);
+        when(mTelecomManager.getDefaultDialerPackage()).thenReturn(DEFAULT_DIALER_PACKAGE);
+
+        mFilter.startCallScreeningFilter(mCall, mCallback,
+                USER_CHOSEN_CALL_SCREENING.getPackageName(),
+                USER_CHOSEN_CALL_SCREENING_APP_NAME);
+        ServiceConnection serviceConnection = verifyBindingIntent();
+        serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
+        ICallScreeningAdapter csAdapter = getCallScreeningAdapter();
+        csAdapter.disallowCall(CALL_ID,
+            true, // shouldReject
+            false, // shouldAddToCallLog
+            true, // shouldShowNotification
+            USER_CHOSEN_CALL_SCREENING
+        );
+        verify(mCallback).onCallScreeningFilterComplete(eq(mCall), eq(new CallFilteringResult(
+            false, // shouldAllowCall
+            true, // shouldReject
+            true, // shouldAddToCallLog
+            true, // shouldShowNotification
+            CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, //callBlockReason
+            USER_CHOSEN_CALL_SCREENING_APP_NAME, //callScreeningAppName
+            USER_CHOSEN_CALL_SCREENING.flattenToString() //callScreeningComponentName
+        )), eq(USER_CHOSEN_CALL_SCREENING.getPackageName()));
     }
 
     private ServiceConnection verifyBindingIntent() {
@@ -219,8 +324,9 @@
 
         Intent capturedIntent = intentCaptor.getValue();
         assertEquals(CallScreeningService.SERVICE_INTERFACE, capturedIntent.getAction());
-        assertEquals(PKG_NAME, capturedIntent.getPackage());
-        assertEquals(COMPONENT_NAME, capturedIntent.getComponent());
+        assertEquals(mResolveInfo.serviceInfo.packageName, capturedIntent.getPackage());
+        assertEquals(new ComponentName(mResolveInfo.serviceInfo.packageName, mResolveInfo
+                .serviceInfo.name), capturedIntent.getComponent());
 
         return serviceCaptor.getValue();
     }
@@ -231,4 +337,14 @@
         verify(mCallScreeningService).screenCall(captor.capture(), nullable(ParcelableCall.class));
         return captor.getValue();
     }
+
+    private void setCarrierDefinedCallScreeningApplication() {
+        String carrierDefined = CARRIER_DEFINED_CALL_SCREENING.flattenToString();
+        PersistableBundle bundle = new PersistableBundle();
+        bundle.putString(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING,
+            carrierDefined);
+        when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
+            .thenReturn(mCarrierConfigManager);
+        when(mCarrierConfigManager.getConfig()).thenReturn(bundle);
+    }
 }
diff --git a/tests/src/com/android/server/telecom/tests/CallerInfoLookupHelperTest.java b/tests/src/com/android/server/telecom/tests/CallerInfoLookupHelperTest.java
index 74d07d8..e26d7e5 100644
--- a/tests/src/com/android/server/telecom/tests/CallerInfoLookupHelperTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallerInfoLookupHelperTest.java
@@ -16,14 +16,26 @@
 
 package com.android.server.telecom.tests;
 
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.support.test.InstrumentationRegistry;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.telecom.Logging.Session;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.InstrumentationRegistry;
 
 import com.android.internal.telephony.CallerInfo;
 import com.android.internal.telephony.CallerInfoAsyncQuery;
@@ -43,17 +55,6 @@
 import java.io.InputStream;
 import java.util.concurrent.CountDownLatch;
 
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 @RunWith(JUnit4.class)
 public class CallerInfoLookupHelperTest extends TelecomTestCase {
     @Mock Context mContext;
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
index ed2f6b1..df19ce8 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -16,13 +16,18 @@
 
 package com.android.server.telecom.tests;
 
+import static junit.framework.TestCase.fail;
+
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyChar;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
@@ -31,26 +36,32 @@
 
 import android.content.ComponentName;
 import android.net.Uri;
+import android.os.Bundle;
+import android.os.Process;
 import android.os.SystemClock;
 import android.telecom.Connection;
+import android.telecom.Log;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
 import android.telephony.TelephonyManager;
 import android.test.suitebuilder.annotation.MediumTest;
-
 import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.internal.telephony.CallerInfo;
 import com.android.server.telecom.AsyncRingtonePlayer;
 import com.android.server.telecom.Call;
 import com.android.server.telecom.CallAudioManager;
+import com.android.server.telecom.CallAudioModeStateMachine;
+import com.android.server.telecom.CallAudioRouteStateMachine;
 import com.android.server.telecom.CallState;
-import com.android.server.telecom.CallerInfoAsyncQueryFactory;
+import com.android.server.telecom.CallerInfoLookupHelper;
 import com.android.server.telecom.CallsManager;
 import com.android.server.telecom.ClockProxy;
 import com.android.server.telecom.ConnectionServiceFocusManager;
 import com.android.server.telecom.ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory;
 import com.android.server.telecom.ConnectionServiceWrapper;
-import com.android.server.telecom.ContactsAsyncHelper;
 import com.android.server.telecom.DefaultDialerCache;
 import com.android.server.telecom.EmergencyCallHelper;
 import com.android.server.telecom.HeadsetMediaButton;
@@ -65,7 +76,8 @@
 import com.android.server.telecom.PhoneNumberUtilsAdapter;
 import com.android.server.telecom.ProximitySensorManager;
 import com.android.server.telecom.ProximitySensorManagerFactory;
-import com.android.server.telecom.SystemStateProvider;
+import com.android.server.telecom.RoleManagerAdapter;
+import com.android.server.telecom.SystemStateHelper;
 import com.android.server.telecom.TelecomSystem;
 import com.android.server.telecom.Timeouts;
 import com.android.server.telecom.WiredHeadsetManager;
@@ -81,20 +93,29 @@
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
 
 @RunWith(JUnit4.class)
 public class CallsManagerTest extends TelecomTestCase {
+    private static final int TEST_TIMEOUT = 5000;  // milliseconds
     private static final PhoneAccountHandle SIM_1_HANDLE = new PhoneAccountHandle(
             ComponentName.unflattenFromString("com.foo/.Blah"), "Sim1");
     private static final PhoneAccountHandle SIM_2_HANDLE = new PhoneAccountHandle(
             ComponentName.unflattenFromString("com.foo/.Blah"), "Sim2");
+    private static final PhoneAccountHandle VOIP_1_HANDLE = new PhoneAccountHandle(
+            ComponentName.unflattenFromString("com.voip/.Stuff"), "Voip1");
     private static final PhoneAccountHandle SELF_MANAGED_HANDLE = new PhoneAccountHandle(
-            ComponentName.unflattenFromString("com.foo/.Self"), "Self");
+            ComponentName.unflattenFromString("com.baz/.Self"), "Self");
     private static final PhoneAccount SIM_1_ACCOUNT = new PhoneAccount.Builder(SIM_1_HANDLE, "Sim1")
             .setCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION
                     | PhoneAccount.CAPABILITY_CALL_PROVIDER)
@@ -112,10 +133,17 @@
             .setIsEnabled(true)
             .build();
     private static final Uri TEST_ADDRESS = Uri.parse("tel:555-1212");
+    private static final Uri TEST_ADDRESS2 = Uri.parse("tel:555-1213");
+    private static final Uri TEST_ADDRESS3 = Uri.parse("tel:555-1214");
+    private static final Map<Uri, PhoneAccountHandle> CONTACT_PREFERRED_ACCOUNT =
+            new HashMap<Uri, PhoneAccountHandle>() {{
+                put(TEST_ADDRESS2, SIM_1_HANDLE);
+                put(TEST_ADDRESS3, SIM_2_HANDLE);
+    }};
 
+    private static int sCallId = 1;
     private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };
-    @Mock private ContactsAsyncHelper mContactsAsyncHelper;
-    @Mock private CallerInfoAsyncQueryFactory mCallerInfoAsyncQueryFactory;
+    @Mock private CallerInfoLookupHelper mCallerInfoLookupHelper;
     @Mock private MissedCallNotifier mMissedCallNotifier;
     @Mock private PhoneAccountRegistrar mPhoneAccountRegistrar;
     @Mock private HeadsetMediaButton mHeadsetMediaButton;
@@ -128,7 +156,7 @@
     @Mock private CallAudioManager.AudioServiceFactory mAudioServiceFactory;
     @Mock private BluetoothRouteManager mBluetoothRouteManager;
     @Mock private WiredHeadsetManager mWiredHeadsetManager;
-    @Mock private SystemStateProvider mSystemStateProvider;
+    @Mock private SystemStateHelper mSystemStateHelper;
     @Mock private DefaultDialerCache mDefaultDialerCache;
     @Mock private Timeouts.Adapter mTimeoutsAdapter;
     @Mock private AsyncRingtonePlayer mAsyncRingtonePlayer;
@@ -139,7 +167,12 @@
     @Mock private InCallControllerFactory mInCallControllerFactory;
     @Mock private InCallController mInCallController;
     @Mock private ConnectionServiceFocusManager mConnectionSvrFocusMgr;
+    @Mock private CallAudioRouteStateMachine mCallAudioRouteStateMachine;
+    @Mock private CallAudioRouteStateMachine.Factory mCallAudioRouteStateMachineFactory;
+    @Mock private CallAudioModeStateMachine mCallAudioModeStateMachine;
+    @Mock private CallAudioModeStateMachine.Factory mCallAudioModeStateMachineFactory;
     @Mock private BluetoothStateReceiver mBluetoothStateReceiver;
+    @Mock private RoleManagerAdapter mRoleManagerAdapter;
 
     private CallsManager mCallsManager;
 
@@ -156,14 +189,18 @@
                 mProximitySensorManager);
         when(mInCallControllerFactory.create(any(), any(), any(), any(), any(), any(),
                 any())).thenReturn(mInCallController);
+        when(mCallAudioRouteStateMachineFactory.create(any(), any(), any(), any(), any(), any(),
+                anyInt())).thenReturn(mCallAudioRouteStateMachine);
+        when(mCallAudioModeStateMachineFactory.create(any(), any()))
+                .thenReturn(mCallAudioModeStateMachine);
         when(mClockProxy.currentTimeMillis()).thenReturn(System.currentTimeMillis());
         when(mClockProxy.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime());
-        when(mConnSvrFocusManagerFactory.create(any(), any())).thenReturn(mConnectionSvrFocusMgr);
+        when(mConnSvrFocusManagerFactory.create(any())).thenReturn(mConnectionSvrFocusMgr);
+        doNothing().when(mRoleManagerAdapter).setCurrentUserHandle(any());
         mCallsManager = new CallsManager(
                 mComponentContextFixture.getTestDouble().getApplicationContext(),
                 mLock,
-                mContactsAsyncHelper,
-                mCallerInfoAsyncQueryFactory,
+                mCallerInfoLookupHelper,
                 mMissedCallNotifier,
                 mPhoneAccountRegistrar,
                 mHeadsetMediaButtonFactory,
@@ -173,7 +210,7 @@
                 mAudioServiceFactory,
                 mBluetoothRouteManager,
                 mWiredHeadsetManager,
-                mSystemStateProvider,
+                mSystemStateHelper,
                 mDefaultDialerCache,
                 mTimeoutsAdapter,
                 mAsyncRingtonePlayer,
@@ -182,7 +219,10 @@
                 mToneGeneratorFactory,
                 mClockProxy,
                 mBluetoothStateReceiver,
-                mInCallControllerFactory);
+                mCallAudioRouteStateMachineFactory,
+                mCallAudioModeStateMachineFactory,
+                mInCallControllerFactory,
+                mRoleManagerAdapter);
 
         when(mPhoneAccountRegistrar.getPhoneAccount(
                 eq(SELF_MANAGED_HANDLE), any())).thenReturn(SELF_MANAGED_ACCOUNT);
@@ -215,8 +255,6 @@
                 mCallsManager,
                 mLock,
                 null /* ConnectionServiceRepository */,
-                mContactsAsyncHelper,
-                mCallerInfoAsyncQueryFactory,
                 mPhoneNumberUtilsAdapter,
                 TEST_ADDRESS,
                 null /* GatewayInfo */,
@@ -249,6 +287,21 @@
         assertEquals(2, phoneAccountHandles.size());
     }
 
+    private void setupCallerInfoLookupHelper() {
+        doAnswer(invocation -> {
+            Uri handle = invocation.getArgument(0);
+            CallerInfoLookupHelper.OnQueryCompleteListener listener = invocation.getArgument(1);
+            CallerInfo info = new CallerInfo();
+            if (CONTACT_PREFERRED_ACCOUNT.get(handle) != null) {
+                PhoneAccountHandle pah = CONTACT_PREFERRED_ACCOUNT.get(handle);
+                info.preferredPhoneAccountComponent = pah.getComponentName();
+                info.preferredPhoneAccountId = pah.getId();
+            }
+            listener.onCallerInfoQueryComplete(handle, info);
+            return null;
+        }).when(mCallerInfoLookupHelper).startLookup(any(Uri.class),
+                any(CallerInfoLookupHelper.OnQueryCompleteListener.class));
+    }
     /**
      * Tests finding the outgoing call phone account where the call is being placed on a
      * self-managed ConnectionService.
@@ -257,8 +310,10 @@
     @MediumTest
     @Test
     public void testFindOutgoingCallPhoneAccountSelfManaged() throws Exception {
+        setupCallerInfoLookupHelper();
         List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
-                SELF_MANAGED_HANDLE, TEST_ADDRESS, false /* isVideo */, null /* userHandle */);
+                SELF_MANAGED_HANDLE, TEST_ADDRESS, false /* isVideo */, null /* userHandle */)
+                .get();
         assertEquals(1, accounts.size());
         assertEquals(SELF_MANAGED_HANDLE, accounts.get(0));
     }
@@ -271,6 +326,7 @@
     @MediumTest
     @Test
     public void testFindOutgoingCallAccountDefault() throws Exception {
+        setupCallerInfoLookupHelper();
         when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
                 SIM_1_HANDLE);
         when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
@@ -278,7 +334,8 @@
                 new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
 
         List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
-                null /* phoneAcct */, TEST_ADDRESS, false /* isVideo */, null /* userHandle */);
+                null /* phoneAcct */, TEST_ADDRESS, false /* isVideo */, null /* userHandle */)
+                .get();
 
         // Should have found just the default.
         assertEquals(1, accounts.size());
@@ -293,6 +350,7 @@
     @MediumTest
     @Test
     public void testFindOutgoingCallAccountNoDefault() throws Exception {
+        setupCallerInfoLookupHelper();
         when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
                 null);
         when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
@@ -300,7 +358,8 @@
                 new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
 
         List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
-                null /* phoneAcct */, TEST_ADDRESS, false /* isVideo */, null /* userHandle */);
+                null /* phoneAcct */, TEST_ADDRESS, false /* isVideo */, null /* userHandle */)
+                .get();
 
         assertEquals(2, accounts.size());
         assertTrue(accounts.contains(SIM_1_HANDLE));
@@ -315,6 +374,7 @@
     @MediumTest
     @Test
     public void testFindOutgoingCallAccountVideo() throws Exception {
+        setupCallerInfoLookupHelper();
         when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
                 null);
         when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
@@ -322,7 +382,8 @@
                 new ArrayList<>(Arrays.asList(SIM_2_HANDLE)));
 
         List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
-                null /* phoneAcct */, TEST_ADDRESS, true /* isVideo */, null /* userHandle */);
+                null /* phoneAcct */, TEST_ADDRESS, true /* isVideo */, null /* userHandle */)
+                .get();
 
         assertEquals(1, accounts.size());
         assertTrue(accounts.contains(SIM_2_HANDLE));
@@ -336,6 +397,7 @@
     @MediumTest
     @Test
     public void testFindOutgoingCallAccountVideoNotAvailable() throws Exception {
+        setupCallerInfoLookupHelper();
         when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
                 null);
         // When querying for video capable accounts, return nothing.
@@ -347,7 +409,8 @@
                 any(), eq(0 /* none specified */))).thenReturn(
                 new ArrayList<>(Arrays.asList(SIM_1_HANDLE)));
         List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
-                null /* phoneAcct */, TEST_ADDRESS, true /* isVideo */, null /* userHandle */);
+                null /* phoneAcct */, TEST_ADDRESS, true /* isVideo */, null /* userHandle */)
+                .get();
 
         // Should have found one.
         assertEquals(1, accounts.size());
@@ -361,6 +424,7 @@
     @MediumTest
     @Test
     public void testUseSpecifiedAccount() throws Exception {
+        setupCallerInfoLookupHelper();
         when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
                 null);
         when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
@@ -368,13 +432,34 @@
                 new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
 
         List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
-                SIM_2_HANDLE, TEST_ADDRESS, false /* isVideo */, null /* userHandle */);
+                SIM_2_HANDLE, TEST_ADDRESS, false /* isVideo */, null /* userHandle */).get();
 
         assertEquals(1, accounts.size());
         assertTrue(accounts.contains(SIM_2_HANDLE));
     }
 
     /**
+     * Tests that we will use the provided target phone account if it exists.
+     * @throws Exception
+     */
+    @MediumTest
+    @Test
+    public void testUseContactSpecificAcct() throws Exception {
+        setupCallerInfoLookupHelper();
+        when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
+                null);
+        when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
+                any(), anyInt())).thenReturn(
+                new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
+
+        List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
+                null, TEST_ADDRESS2, false /* isVideo */, Process.myUserHandle()).get();
+
+        assertEquals(1, accounts.size());
+        assertTrue(accounts.contains(SIM_1_HANDLE));
+    }
+
+    /**
      * Verifies that an active call will result in playing a DTMF tone when requested.
      * @throws Exception
      */
@@ -439,17 +524,14 @@
     @SmallTest
     @Test
     public void testUnholdCallWhenOngoingCallCanNotBeHeldAndFromDifferentConnectionService() {
-        ConnectionServiceWrapper connSvr1 = Mockito.mock(ConnectionServiceWrapper.class);
-        ConnectionServiceWrapper connSvr2 = Mockito.mock(ConnectionServiceWrapper.class);
-
         // GIVEN a CallsManager with ongoing call, and this call can not be held
-        Call ongoingCall = addSpyCallWithConnectionService(connSvr1);
+        Call ongoingCall = addSpyCall(SIM_1_HANDLE);
         doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
         doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
         when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
 
         // and a held call which has different ConnectionService
-        Call heldCall = addSpyCallWithConnectionService(connSvr2);
+        Call heldCall = addSpyCall(VOIP_1_HANDLE);
 
         // WHEN unhold the held call
         mCallsManager.unholdCall(heldCall);
@@ -464,17 +546,39 @@
 
     @SmallTest
     @Test
-    public void testUnholdCallWhenOngoingCallCanNotBeHeldAndHasSameConnectionService() {
-        ConnectionServiceWrapper connSvr = Mockito.mock(ConnectionServiceWrapper.class);
+    public void testUnholdCallWhenOngoingEmergCallCanNotBeHeldAndFromDifferentConnectionService() {
+        // GIVEN a CallsManager with ongoing call, and this call can not be held, but it also an
+        // emergency call.
+        Call ongoingCall = addSpyCall(SIM_1_HANDLE);
+        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
+        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
+        doReturn(true).when(ongoingCall).isEmergencyCall();
+        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
 
+        // and a held call which has different ConnectionService
+        Call heldCall = addSpyCall(VOIP_1_HANDLE);
+
+        // WHEN unhold the held call
+        mCallsManager.unholdCall(heldCall);
+
+        // THEN the ongoing call will not be disconnected (because its an emergency call)
+        verify(ongoingCall, never()).disconnect(any());
+
+        // and held call is not un-held
+        verify(heldCall, never()).unhold(any());
+    }
+
+    @SmallTest
+    @Test
+    public void testUnholdCallWhenOngoingCallCanNotBeHeldAndHasSameConnectionService() {
         // GIVEN a CallsManager with ongoing call, and this call can not be held
-        Call ongoingCall = addSpyCallWithConnectionService(connSvr);
+        Call ongoingCall = addSpyCall(SIM_1_HANDLE);
         doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
         doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
         when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
 
-        // and a held call which has different ConnectionService
-        Call heldCall = addSpyCallWithConnectionService(connSvr);
+        // and a held call which has the same ConnectionService
+        Call heldCall = addSpyCall(SIM_2_HANDLE);
 
         // WHEN unhold the held call
         mCallsManager.unholdCall(heldCall);
@@ -511,15 +615,13 @@
     @SmallTest
     @Test
     public void testAnswerCallWhenOngoingHasSameConnectionService() {
-        ConnectionServiceWrapper connSvr = Mockito.mock(ConnectionServiceWrapper.class);
-
         // GIVEN a CallsManager with ongoing call, and this call can not be held
-        Call ongoingCall = addSpyCallWithConnectionService(connSvr);
+        Call ongoingCall = addSpyCall(SIM_1_HANDLE);
         doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
         when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
 
         // WHEN answer an incoming call
-        Call incomingCall = addSpyCallWithConnectionService(connSvr);
+        Call incomingCall = addSpyCall(VOIP_1_HANDLE);
         mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);
 
         // THEN nothing happened on the ongoing call and the focus request for incoming call is sent
@@ -532,17 +634,14 @@
     @SmallTest
     @Test
     public void testAnswerCallWhenOngoingHasDifferentConnectionService() {
-        ConnectionServiceWrapper connSvr1 = Mockito.mock(ConnectionServiceWrapper.class);
-        ConnectionServiceWrapper connSvr2 = Mockito.mock(ConnectionServiceWrapper.class);
-
         // GIVEN a CallsManager with ongoing call, and this call can not be held
-        Call ongoingCall = addSpyCallWithConnectionService(connSvr1);
+        Call ongoingCall = addSpyCall(SIM_1_HANDLE);
         doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
         doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
         when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
 
         // WHEN answer an incoming call
-        Call incomingCall = addSpyCallWithConnectionService(connSvr2);
+        Call incomingCall = addSpyCall(VOIP_1_HANDLE);
         mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);
 
         // THEN the ongoing call is disconnected and the focus request for incoming call is sent
@@ -555,24 +654,47 @@
 
     @SmallTest
     @Test
-    public void testAnswerCallWhenMultipleHeldCallsExisted() {
-        ConnectionServiceWrapper connSvr1 = Mockito.mock(ConnectionServiceWrapper.class);
-        ConnectionServiceWrapper connSvr2 = Mockito.mock(ConnectionServiceWrapper.class);
-
-        // Given an ongoing call and held call with the ConnectionService connSvr1. The
-        // ConnectionService connSvr1 can handle one held call
-        Call ongoingCall = addSpyCallWithConnectionService(connSvr1);
+    public void testAnswerCallWhenOngoingHasDifferentConnectionServiceButIsEmerg() {
+        // GIVEN a CallsManager with ongoing call, and this call can not be held
+        Call ongoingCall = addSpyCall(SIM_1_HANDLE);
         doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
         doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
-        Call heldCall = addSpyCallWithConnectionService(connSvr1);
+        doReturn(true).when(ongoingCall).isEmergencyCall();
+        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
+
+        // WHEN answer an incoming call
+        Call incomingCall = addSpyCall(VOIP_1_HANDLE);
+        mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);
+
+        // THEN the ongoing call is not disconnected
+        verify(ongoingCall, never()).disconnect();
+
+        // and the incoming call is not answered, but is rejected instead.
+        verify(incomingCall, never()).answer(VideoProfile.STATE_AUDIO_ONLY);
+        verify(incomingCall).reject(eq(false), any(), any());
+    }
+
+    @SmallTest
+    @Test
+    public void testAnswerCallWhenMultipleHeldCallsExisted() {
+        // Given an ongoing call and held call with the ConnectionService connSvr1. The
+        // ConnectionService connSvr1 can handle one held call
+        Call ongoingCall = addSpyCall(SIM_1_HANDLE);
+        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
+        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
+        doReturn(CallState.ACTIVE).when(ongoingCall).getState();
+        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
+
+        Call heldCall = addSpyCall(SIM_1_HANDLE);
         doReturn(CallState.ON_HOLD).when(heldCall).getState();
 
         // and other held call has difference ConnectionService
-        Call heldCall2 = addSpyCallWithConnectionService(connSvr2);
+        Call heldCall2 = addSpyCall(VOIP_1_HANDLE);
         doReturn(CallState.ON_HOLD).when(heldCall2).getState();
 
         // WHEN answer an incoming call which ConnectionService is connSvr1
-        Call incomingCall = addSpyCallWithConnectionService(connSvr1);
+        Call incomingCall = addSpyCall(SIM_1_HANDLE);
+        doReturn(true).when(incomingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
         mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);
 
         // THEN the previous held call is disconnected
@@ -609,18 +731,34 @@
 
     @SmallTest
     @Test
-    public void testSetActiveCallWhenOngoingCallCanNotBeHeldAndFromDifferentConnectionService() {
-        ConnectionServiceWrapper connSvr1 = Mockito.mock(ConnectionServiceWrapper.class);
-        ConnectionServiceWrapper connSvr2 = Mockito.mock(ConnectionServiceWrapper.class);
+    public void testAnswerAlreadyActiveCall() {
+        // GIVEN a CallsManager with no ongoing call.
 
+        // WHEN answer an already active call
+        Call incomingCall = addSpyCall();
+        mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);
+
+        // THEN the focus request for incoming call is sent
+        verifyFocusRequestAndExecuteCallback(incomingCall);
+
+        // and the incoming call is answered.
+        verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
+
+        // and the incoming call's state is still ACTIVE
+        assertEquals(CallState.ACTIVE, incomingCall.getState());
+    }
+
+    @SmallTest
+    @Test
+    public void testSetActiveCallWhenOngoingCallCanNotBeHeldAndFromDifferentConnectionService() {
         // GIVEN a CallsManager with ongoing call, and this call can not be held
-        Call ongoingCall = addSpyCallWithConnectionService(connSvr1);
+        Call ongoingCall = addSpyCall(SIM_1_HANDLE);
         doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
         doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
         doReturn(ongoingCall).when(mConnectionSvrFocusMgr).getCurrentFocusCall();
 
         // and a new self-managed call which has different ConnectionService
-        Call newCall = addSpyCallWithConnectionService(connSvr2);
+        Call newCall = addSpyCall(VOIP_1_HANDLE);
         doReturn(true).when(newCall).isSelfManaged();
 
         // WHEN active the new call
@@ -637,16 +775,14 @@
     @SmallTest
     @Test
     public void testSetActiveCallWhenOngoingCallCanNotBeHeldAndHasSameConnectionService() {
-        ConnectionServiceWrapper connSvr = Mockito.mock(ConnectionServiceWrapper.class);
-
         // GIVEN a CallsManager with ongoing call, and this call can not be held
-        Call ongoingCall = addSpyCallWithConnectionService(connSvr);
+        Call ongoingCall = addSpyCall(SIM_1_HANDLE);
         doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
         doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
         when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
 
         // and a new self-managed call which has the same ConnectionService
-        Call newCall = addSpyCallWithConnectionService(connSvr);
+        Call newCall = addSpyCall(SIM_1_HANDLE);
         doReturn(true).when(newCall).isSelfManaged();
 
         // WHEN active the new call
@@ -684,25 +820,285 @@
         assertEquals(CallState.ACTIVE, newCall.getState());
     }
 
-    private Call addSpyCallWithConnectionService(ConnectionServiceWrapper connSvr) {
-        Call call = addSpyCall();
-        doReturn(connSvr).when(call).getConnectionService();
-        return call;
+    @SmallTest
+    @Test
+    public void testDisconnectDialingCallOnIncoming() {
+        // GIVEN a CallsManager with a self-managed call which is dialing, and this call can be held
+        Call ongoingCall = addSpyCall(SELF_MANAGED_HANDLE);
+        ongoingCall.setState(CallState.DIALING, "test");
+        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
+        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
+        doReturn(true).when(ongoingCall).isSelfManaged();
+        doReturn(ongoingCall).when(mConnectionSvrFocusMgr).getCurrentFocusCall();
+
+        // and a new incoming managed call
+        Call newCall = addSpyCall();
+        doReturn(false).when(newCall).isRespondViaSmsCapable();
+        newCall.setState(CallState.RINGING, "test");
+
+        // WHEN answering the new call
+        mCallsManager.answerCall(newCall, VideoProfile.STATE_AUDIO_ONLY);
+
+        // THEN the ongoing call is disconnected
+        verify(ongoingCall).disconnect();
+
+        // AND focus is requested for the new call
+        ArgumentCaptor<CallsManager.RequestCallback> requestCaptor =
+                ArgumentCaptor.forClass(CallsManager.RequestCallback.class);
+        verify(mConnectionSvrFocusMgr).requestFocus(eq(newCall), requestCaptor.capture());
+        // since we're mocking the focus manager, we'll just pretend it did its thing.
+        requestCaptor.getValue().onRequestFocusDone(newCall);
+
+        // and the new call is marked answered
+        assertEquals(CallState.ANSWERED, newCall.getState());
+    }
+
+    @SmallTest
+    @Test
+    public void testNoFilteringOfSelfManagedCalls() {
+        // GIVEN an incoming call which is self managed.
+        Call incomingCall = addSpyCall(SELF_MANAGED_HANDLE);
+        doReturn(false).when(incomingCall).can(Connection.CAPABILITY_HOLD);
+        doReturn(false).when(incomingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
+        doReturn(true).when(incomingCall).isSelfManaged();
+        doReturn(true).when(incomingCall).setState(anyInt(), any());
+
+        // WHEN the incoming call is successfully added.
+        mCallsManager.onSuccessfulIncomingCall(incomingCall);
+
+        // THEN the incoming call is not using call filtering
+        verify(incomingCall).setIsUsingCallFiltering(eq(false));
+    }
+
+    @SmallTest
+    @Test
+    public void testAcceptIncomingCallWhenHeadsetMediaButtonShortPress() {
+        // GIVEN an incoming call
+        Call incomingCall = addSpyCall();
+        doReturn(CallState.RINGING).when(incomingCall).getState();
+
+        // WHEN media button short press
+        mCallsManager.onMediaButton(HeadsetMediaButton.SHORT_PRESS);
+
+        // THEN the incoming call is answered
+        verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
+    }
+
+    @SmallTest
+    @Test
+    public void testRejectIncomingCallWhenHeadsetMediaButtonLongPress() {
+        // GIVEN an incoming call
+        Call incomingCall = addSpyCall();
+        doReturn(CallState.RINGING).when(incomingCall).getState();
+
+        // WHEN media button long press
+        mCallsManager.onMediaButton(HeadsetMediaButton.LONG_PRESS);
+
+        // THEN the incoming call is rejected
+        verify(incomingCall).reject(false, null);
+    }
+
+    @SmallTest
+    @Test
+    public void testHangupOngoingCallWhenHeadsetMediaButtonShortPress() {
+        // GIVEN an ongoing call
+        Call ongoingCall = addSpyCall();
+        doReturn(CallState.ACTIVE).when(ongoingCall).getState();
+
+        // WHEN media button short press
+        mCallsManager.onMediaButton(HeadsetMediaButton.SHORT_PRESS);
+
+        // THEN the active call is disconnected
+        verify(ongoingCall).disconnect();
+    }
+
+    @SmallTest
+    @Test
+    public void testToggleMuteWhenHeadsetMediaButtonLongPressDuringOngoingCall() {
+        // GIVEN an ongoing call
+        Call ongoingCall = addSpyCall();
+        doReturn(CallState.ACTIVE).when(ongoingCall).getState();
+
+        // WHEN media button long press
+        mCallsManager.onMediaButton(HeadsetMediaButton.LONG_PRESS);
+
+        // THEN the microphone toggle mute
+        verify(mCallAudioRouteStateMachine)
+                .sendMessageWithSessionInfo(CallAudioRouteStateMachine.TOGGLE_MUTE);
+    }
+
+    @SmallTest
+    @Test
+    public void testSwapCallsWhenHeadsetMediaButtonShortPressDuringTwoCalls() {
+        // GIVEN an ongoing call, and this call can be held
+        Call ongoingCall = addSpyCall();
+        doReturn(CallState.ACTIVE).when(ongoingCall).getState();
+        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
+        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
+        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
+
+        // and a held call
+        Call heldCall = addSpyCall();
+        doReturn(CallState.ON_HOLD).when(heldCall).getState();
+
+        // WHEN media button short press
+        mCallsManager.onMediaButton(HeadsetMediaButton.SHORT_PRESS);
+
+        // THEN the ongoing call is held, and the focus request for heldCall call is sent
+        verify(ongoingCall).hold(nullable(String.class));
+        verifyFocusRequestAndExecuteCallback(heldCall);
+
+        // and held call is unhold now
+        verify(heldCall).unhold(nullable(String.class));
+    }
+
+    @SmallTest
+    @Test
+    public void testHangupActiveCallWhenHeadsetMediaButtonLongPressDuringTwoCalls() {
+        // GIVEN an  ongoing call
+        Call ongoingCall = addSpyCall();
+        doReturn(CallState.ACTIVE).when(ongoingCall).getState();
+
+        // and a held call
+        Call heldCall = addSpyCall();
+        doReturn(CallState.ON_HOLD).when(heldCall).getState();
+
+        // WHEN media button long press
+        mCallsManager.onMediaButton(HeadsetMediaButton.LONG_PRESS);
+
+        // THEN the ongoing call is disconnected
+        verify(ongoingCall).disconnect();
+    }
+
+    @SmallTest
+    @Test
+    public void testNoFilteringOfCallsWhenPhoneAccountRequestsSkipped() {
+        // GIVEN an incoming call which is from a PhoneAccount that requested to skip filtering.
+        Call incomingCall = addSpyCall(SIM_1_HANDLE);
+        Bundle extras = new Bundle();
+        extras.putBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING, true);
+        PhoneAccount skipRequestedAccount = new PhoneAccount.Builder(SIM_2_HANDLE, "Skipper")
+            .setCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION
+                | PhoneAccount.CAPABILITY_CALL_PROVIDER)
+            .setExtras(extras)
+            .setIsEnabled(true)
+            .build();
+        when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(SIM_1_HANDLE))
+            .thenReturn(skipRequestedAccount);
+        doReturn(false).when(incomingCall).can(Connection.CAPABILITY_HOLD);
+        doReturn(false).when(incomingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
+        doReturn(false).when(incomingCall).isSelfManaged();
+        doReturn(true).when(incomingCall).setState(anyInt(), any());
+
+        // WHEN the incoming call is successfully added.
+        mCallsManager.onSuccessfulIncomingCall(incomingCall);
+
+        // THEN the incoming call is not using call filtering
+        verify(incomingCall).setIsUsingCallFiltering(eq(false));
+    }
+
+    @SmallTest
+    @Test
+    public void testIsInEmergencyCallNetwork() {
+        // Setup a call which the network identified as an emergency call.
+        Call ongoingCall = addSpyCall();
+        ongoingCall.setConnectionProperties(Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL);
+
+        assertFalse(ongoingCall.isEmergencyCall());
+        assertTrue(ongoingCall.isNetworkIdentifiedEmergencyCall());
+        assertTrue(mCallsManager.isInEmergencyCall());
+    }
+
+    @SmallTest
+    @Test
+    public void testIsInEmergencyCallLocal() {
+        // Setup a call which is considered emergency based on its phone number.
+        Call ongoingCall = addSpyCall();
+        when(mPhoneNumberUtilsAdapter.isLocalEmergencyNumber(any(), any())).thenReturn(true);
+        ongoingCall.setHandle(Uri.fromParts("tel", "5551212", null),
+                TelecomManager.PRESENTATION_ALLOWED);
+
+        assertTrue(ongoingCall.isEmergencyCall());
+        assertFalse(ongoingCall.isNetworkIdentifiedEmergencyCall());
+        assertTrue(mCallsManager.isInEmergencyCall());
+    }
+
+    /**
+     * Verifies that changes to a {@link PhoneAccount}'s
+     * {@link PhoneAccount#CAPABILITY_VIDEO_CALLING} capability will be reflected on a call.
+     * @throws Exception
+     */
+    @SmallTest
+    @Test
+    public void testPhoneAccountVideoAvailability() throws InterruptedException {
+        Call ongoingCall = addSpyCall(); // adds to SIM_2_ACCT
+        LinkedBlockingQueue<Integer> capabilitiesQueue = new LinkedBlockingQueue<>(1);
+        ongoingCall.addListener(new Call.ListenerBase() {
+            @Override
+            public void onConnectionCapabilitiesChanged(Call call) {
+                try {
+                    Log.i("TYLER", "Listener got " + call.getConnectionCapabilities());
+                    capabilitiesQueue.put(call.getConnectionCapabilities());
+                } catch (InterruptedException e) {
+                    fail();
+                }
+            }
+        });
+
+        // Lets make the phone account video capable.
+        PhoneAccount videoCapableAccount = new PhoneAccount.Builder(SIM_2_ACCOUNT)
+                .setCapabilities(SIM_2_ACCOUNT.getCapabilities()
+                        | PhoneAccount.CAPABILITY_VIDEO_CALLING)
+                .build();
+        mCallsManager.getPhoneAccountListener().onPhoneAccountChanged(mPhoneAccountRegistrar,
+                videoCapableAccount);
+        // Absorb first update; it'll be from when phone account changed initially (since we force
+        // a capabilities update.
+        int newCapabilities = capabilitiesQueue.poll(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+        // Lets pretend the ConnectionService made it video capable as well.
+        ongoingCall.setConnectionCapabilities(
+                Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
+        newCapabilities = capabilitiesQueue.poll(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+        assertTrue(Connection.can(newCapabilities,
+                Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL));
+        assertTrue(ongoingCall.isVideoCallingSupportedByPhoneAccount());
+
+        // Fire a changed event for the phone account making it not capable.
+        mCallsManager.getPhoneAccountListener().onPhoneAccountChanged(mPhoneAccountRegistrar,
+                SIM_2_ACCOUNT);
+        newCapabilities = capabilitiesQueue.poll(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+        assertFalse(Connection.can(newCapabilities,
+                Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL));
+        assertFalse(ongoingCall.isVideoCallingSupportedByPhoneAccount());
+
+        // Fire a change for an unrelated phone account.
+        PhoneAccount anotherVideoCapableAcct = new PhoneAccount.Builder(SIM_1_ACCOUNT)
+                .setCapabilities(SIM_2_ACCOUNT.getCapabilities()
+                        | PhoneAccount.CAPABILITY_VIDEO_CALLING)
+                .build();
+        mCallsManager.getPhoneAccountListener().onPhoneAccountChanged(mPhoneAccountRegistrar,
+                anotherVideoCapableAcct);
+        // Call still should not be video capable
+        assertFalse(Connection.can(ongoingCall.getConnectionCapabilities(),
+                Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL));
     }
 
     private Call addSpyCall() {
-        Call ongoingCall = new Call("1", /* callId */
+        return addSpyCall(SIM_2_HANDLE);
+    }
+
+    private Call addSpyCall(PhoneAccountHandle targetPhoneAccount) {
+        Call ongoingCall = new Call(String.format("TC@%d", sCallId++), /* callId */
                 mComponentContextFixture.getTestDouble(),
                 mCallsManager,
                 mLock, /* ConnectionServiceRepository */
                 null,
-                mContactsAsyncHelper,
-                mCallerInfoAsyncQueryFactory,
                 mPhoneNumberUtilsAdapter,
                 TEST_ADDRESS,
                 null /* GatewayInfo */,
                 null /* connectionManagerPhoneAccountHandle */,
-                SIM_2_HANDLE,
+                targetPhoneAccount,
                 Call.CALL_DIRECTION_INCOMING,
                 false /* shouldAttachToExistingConnection*/,
                 false /* isConference */,
diff --git a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
index 01d312b..6d776aa 100644
--- a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
@@ -26,9 +26,11 @@
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
+import android.Manifest;
 import android.app.AppOpsManager;
 import android.app.NotificationManager;
 import android.app.StatusBarManager;
+// import android.app.role.RoleManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -71,6 +73,7 @@
 import java.util.Locale;
 import java.util.Map;
 
+import static org.mockito.ArgumentMatchers.matches;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
@@ -181,6 +184,9 @@
                     return mCarrierConfigManager;
                 case Context.COUNTRY_DETECTOR:
                     return mCountryDetector;
+                // TODO: RoleManager not ready yet, uncomment when it's merged into aosp.
+                // case Context.ROLE_SERVICE:
+                //     return mRoleManager;
                 default:
                     return null;
             }
@@ -190,6 +196,8 @@
         public String getSystemServiceName(Class<?> svcClass) {
             if (svcClass == UserManager.class) {
                 return Context.USER_SERVICE;
+            } else if (svcClass == AudioManager.class) {
+                return Context.AUDIO_SERVICE;
             }
             throw new UnsupportedOperationException();
         }
@@ -430,8 +438,9 @@
     private final Map<String, IContentProvider> mIContentProviderByUri = new HashMap<>();
     private final Configuration mResourceConfiguration = new Configuration();
     private final ApplicationInfo mTestApplicationInfo = new ApplicationInfo();
+    // private final RoleManager mRoleManager = mock(RoleManager.class);
 
-    private TelecomManager mTelecomManager = null;
+    private TelecomManager mTelecomManager = mock(TelecomManager.class);
 
     public ComponentContextFixture() {
         MockitoAnnotations.initMocks(this);
@@ -461,6 +470,11 @@
             }
         }).when(mPackageManager).queryIntentServicesAsUser((Intent) any(), anyInt(), anyInt());
 
+        // By default, tests use non-ui apps instead of 3rd party companion apps.
+        when(mPackageManager.checkPermission(
+                matches(Manifest.permission.CALL_COMPANION_APP), anyString()))
+                .thenReturn(PackageManager.PERMISSION_DENIED);
+
         when(mTelephonyManager.getSubIdForPhoneAccount((PhoneAccount) any())).thenReturn(1);
 
         when(mTelephonyManager.getNetworkOperatorName()).thenReturn("label1");
@@ -523,6 +537,10 @@
         });
     }
 
+    public void putFloatResource(int id, final float value) {
+        when(mResources.getFloat(eq(id))).thenReturn(value);
+    }
+
     public void putBooleanResource(int id, boolean value) {
         when(mResources.getBoolean(eq(id))).thenReturn(value);
     }
diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
index 3154b7d..6c4e2e0 100644
--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
@@ -286,7 +286,9 @@
 
         @Override
         public void rejectWithMessage(String callId, String message,
-                Session.Info info) throws RemoteException { }
+                Session.Info info) throws RemoteException {
+            rejectedCallIds.add(callId);
+        }
 
         @Override
         public void disconnect(String callId, Session.Info info) throws RemoteException { }
diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFocusManagerTest.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFocusManagerTest.java
index 3c2cc61..77a9c0d 100644
--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFocusManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFocusManagerTest.java
@@ -16,7 +16,6 @@
 
 package com.android.server.telecom.tests;
 
-import android.os.Looper;
 import android.test.suitebuilder.annotation.SmallTest;
 import com.android.server.telecom.Call;
 import com.android.server.telecom.CallState;
@@ -63,8 +62,7 @@
     @Before
     public void setUp() throws Exception {
         super.setUp();
-        mFocusManagerUT = new ConnectionServiceFocusManager(
-                mockCallsManagerRequester, Looper.getMainLooper());
+        mFocusManagerUT = new ConnectionServiceFocusManager(mockCallsManagerRequester);
         mNewCall = createFakeCall(mNewConnectionService, CallState.NEW);
         mActiveCall = createFakeCall(mActiveConnectionService, CallState.ACTIVE);
         ArgumentCaptor<CallsManager.CallsManagerListener> captor =
diff --git a/tests/src/com/android/server/telecom/tests/ContactsAsyncHelperTest.java b/tests/src/com/android/server/telecom/tests/ContactsAsyncHelperTest.java
index 81263ae..08d9a47 100644
--- a/tests/src/com/android/server/telecom/tests/ContactsAsyncHelperTest.java
+++ b/tests/src/com/android/server/telecom/tests/ContactsAsyncHelperTest.java
@@ -16,14 +16,26 @@
 
 package com.android.server.telecom.tests;
 
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.support.test.InstrumentationRegistry;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import androidx.test.InstrumentationRegistry;
+
 import com.android.server.telecom.ContactsAsyncHelper;
 
 import org.junit.Before;
@@ -35,17 +47,6 @@
 import java.io.FileNotFoundException;
 import java.io.InputStream;
 
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isNull;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
-
 @RunWith(JUnit4.class)
 public class ContactsAsyncHelperTest extends TelecomTestCase {
     private static final Uri SAMPLE_CONTACT_PHOTO_URI = Uri.parse(
diff --git a/tests/src/com/android/server/telecom/tests/DirectToVoicemailCallFilterTest.java b/tests/src/com/android/server/telecom/tests/DirectToVoicemailCallFilterTest.java
index af4c168..a685c5e 100644
--- a/tests/src/com/android/server/telecom/tests/DirectToVoicemailCallFilterTest.java
+++ b/tests/src/com/android/server/telecom/tests/DirectToVoicemailCallFilterTest.java
@@ -17,6 +17,7 @@
 package com.android.server.telecom.tests;
 
 import android.net.Uri;
+import android.provider.CallLog;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.internal.telephony.CallerInfo;
@@ -65,7 +66,10 @@
                         false, // shouldAllowCall
                         true, // shouldReject
                         true, // shouldAddToCallLog
-                        true // shouldShowNotification
+                        true, // shouldShowNotification
+                        CallLog.Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL, //callBlockReason
+                        null, //callScreeningAppName
+                        null // callScreeningComponentName
                 ));
     }
 
diff --git a/tests/src/com/android/server/telecom/tests/EventManagerTest.java b/tests/src/com/android/server/telecom/tests/EventManagerTest.java
index 24394ec..8bf8d1d 100644
--- a/tests/src/com/android/server/telecom/tests/EventManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/EventManagerTest.java
@@ -16,6 +16,9 @@
 
 package com.android.server.telecom.tests;
 
+import android.net.Uri;
+import android.os.Build;
+import android.telecom.Log;
 import android.telecom.Logging.EventManager;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -217,4 +220,23 @@
         assertEquals(0, timings1.size());
         assertEquals(0, timings2.size());
     }
+
+    /**
+     * Ensure PII logging will log the last 2 digits of a phone number.
+     */
+    @SmallTest
+    @Test
+    public void testLogLast2DigitsPhone() {
+        if (Build.IS_USER) {
+            return;
+        }
+        assertEquals("tel:**********12",
+                Log.piiHandle(Uri.fromParts("tel", "+16505551212", null)));
+        assertEquals("tel:*****12",
+                Log.piiHandle(Uri.fromParts("tel", "5551212", null)));
+        assertEquals("tel:*11",
+                Log.piiHandle(Uri.fromParts("tel", "411", null)));
+        assertEquals("tel:1",
+                Log.piiHandle(Uri.fromParts("tel", "1", null)));
+    }
 }
\ No newline at end of file
diff --git a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
index 0671a4e..73d7a58 100644
--- a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
+++ b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
@@ -50,7 +50,8 @@
 import com.android.server.telecom.InCallController;
 import com.android.server.telecom.PhoneAccountRegistrar;
 import com.android.server.telecom.R;
-import com.android.server.telecom.SystemStateProvider;
+import com.android.server.telecom.RoleManagerAdapter;
+import com.android.server.telecom.SystemStateHelper;
 import com.android.server.telecom.TelecomSystem;
 import com.android.server.telecom.Timeouts;
 
@@ -65,11 +66,17 @@
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.matches;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
@@ -88,19 +95,24 @@
     @Mock CallsManager mMockCallsManager;
     @Mock PhoneAccountRegistrar mMockPhoneAccountRegistrar;
     @Mock BluetoothHeadsetProxy mMockBluetoothHeadset;
-    @Mock SystemStateProvider mMockSystemStateProvider;
+    @Mock SystemStateHelper mMockSystemStateHelper;
     @Mock PackageManager mMockPackageManager;
     @Mock Call mMockCall;
     @Mock Resources mMockResources;
     @Mock MockContext mMockContext;
     @Mock Timeouts.Adapter mTimeoutsAdapter;
     @Mock DefaultDialerCache mDefaultDialerCache;
+    @Mock RoleManagerAdapter mMockRoleManagerAdapter;
 
     private static final int CURRENT_USER_ID = 900973;
     private static final String DEF_PKG = "defpkg";
     private static final String DEF_CLASS = "defcls";
     private static final String SYS_PKG = "syspkg";
     private static final String SYS_CLASS = "syscls";
+    private static final String COMPANION_PKG = "cpnpkg";
+    private static final String COMPANION_CLASS = "cpncls";
+    private static final String CAR_PKG = "carpkg";
+    private static final String CAR_CLASS = "carcls";
     private static final PhoneAccountHandle PA_HANDLE =
             new PhoneAccountHandle(new ComponentName("pa_pkg", "pa_cls"), "pa_id");
 
@@ -121,9 +133,17 @@
         doReturn(true).when(mMockResources).getBoolean(R.bool.grant_location_permission_enabled);
         mEmergencyCallHelper = new EmergencyCallHelper(mMockContext, SYS_PKG,
                 mTimeoutsAdapter);
+        when(mMockCallsManager.getRoleManagerAdapter()).thenReturn(mMockRoleManagerAdapter);
         mInCallController = new InCallController(mMockContext, mLock, mMockCallsManager,
-                mMockSystemStateProvider, mDefaultDialerCache, mTimeoutsAdapter,
+                mMockSystemStateHelper, mDefaultDialerCache, mTimeoutsAdapter,
                 mEmergencyCallHelper);
+        // Companion Apps don't have CONTROL_INCALL_EXPERIENCE permission.
+        when(mMockPackageManager.checkPermission(
+                matches(Manifest.permission.CONTROL_INCALL_EXPERIENCE),
+                matches(COMPANION_PKG))).thenReturn(PackageManager.PERMISSION_DENIED);
+        when(mMockPackageManager.checkPermission(
+                matches(Manifest.permission.CONTROL_INCALL_EXPERIENCE),
+                matches(CAR_PKG))).thenReturn(PackageManager.PERMISSION_DENIED);
     }
 
     @Override
@@ -493,6 +513,154 @@
         verify(mockInCallService).addCall(any(ParcelableCall.class));
     }
 
+    /**
+     * Ensures that the {@link InCallController} will bind to an {@link InCallService} which
+     * supports third party companion calls.
+     */
+    @MediumTest
+    public void doNotTestBindToService_Companion() throws Exception {
+        setupMocks(true /* isExternalCall */);
+        setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
+
+        List<String> companionAppsList = new ArrayList<>();
+        companionAppsList.add(COMPANION_PKG);
+        companionAppsList.add(COMPANION_PKG);
+        when(mMockRoleManagerAdapter.getCallCompanionApps()).thenReturn(companionAppsList);
+        mInCallController.bindToServices(mMockCall);
+
+        // Query for the different InCallServices
+        ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mMockPackageManager, times(6)).queryIntentServicesAsUser(
+                queryIntentCaptor.capture(),
+                eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
+        // Verify call for default dialer InCallService
+        assertEquals(DEF_PKG, queryIntentCaptor.getAllValues().get(0).getPackage());
+        // Verify call for system dialer InCallService
+        assertEquals(null, queryIntentCaptor.getAllValues().get(1).getPackage());
+        // Verify call for car mode ui InCallServices
+        assertEquals(null, queryIntentCaptor.getAllValues().get(2).getPackage());
+        // Verify call for non-UI InCallServices
+        assertEquals(null, queryIntentCaptor.getAllValues().get(3).getPackage());
+        // Verify call for companion InCallServices
+        assertEquals(COMPANION_PKG, queryIntentCaptor.getAllValues().get(4).getPackage());
+        assertEquals(COMPANION_PKG, queryIntentCaptor.getAllValues().get(5).getPackage());
+
+        // Bind InCallServices
+        ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mMockContext, times(3)).bindServiceAsUser(
+                bindIntentCaptor.capture(),
+                any(ServiceConnection.class),
+                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+                eq(UserHandle.CURRENT));
+        // Verify bind dialer
+        Intent bindIntent = bindIntentCaptor.getAllValues().get(0);
+        assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
+        assertEquals(DEF_PKG, bindIntent.getComponent().getPackageName());
+        assertEquals(DEF_CLASS, bindIntent.getComponent().getClassName());
+        // Verify bind companion apps
+        bindIntent = bindIntentCaptor.getAllValues().get(1);
+        assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
+        assertEquals(COMPANION_PKG, bindIntent.getComponent().getPackageName());
+        assertEquals(COMPANION_CLASS, bindIntent.getComponent().getClassName());
+        bindIntent = bindIntentCaptor.getAllValues().get(2);
+        assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
+        assertEquals(COMPANION_PKG, bindIntent.getComponent().getPackageName());
+        assertEquals(COMPANION_CLASS, bindIntent.getComponent().getClassName());
+    }
+
+    /**
+     * Ensures that the {@link InCallController} will bind to an {@link InCallService} which
+     * supports third party car mode ui calls
+     */
+    @MediumTest
+    public void doNotTestBindToService_CarModeUI() throws Exception {
+        setupMocks(true /* isExternalCall */);
+        setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
+
+        when(mMockRoleManagerAdapter.getCarModeDialerApp()).thenReturn(CAR_PKG);
+        // Enable car mode
+        when(mMockSystemStateHelper.isCarMode()).thenReturn(true);
+        mInCallController.bindToServices(mMockCall);
+
+        // Query for the different InCallServices
+        ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
+                queryIntentCaptor.capture(),
+                eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
+        // Verify call for default dialer InCallService
+        assertEquals(DEF_PKG, queryIntentCaptor.getAllValues().get(0).getPackage());
+        // Verify call for system dialer InCallService
+        assertEquals(null, queryIntentCaptor.getAllValues().get(1).getPackage());
+        // Verify call for car mode ui InCallServices
+        assertEquals(CAR_PKG, queryIntentCaptor.getAllValues().get(2).getPackage());
+        // Verify call for non-UI InCallServices
+        assertEquals(null, queryIntentCaptor.getAllValues().get(3).getPackage());
+
+        // Bind InCallServices
+        ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mMockContext, times(1)).bindServiceAsUser(
+                bindIntentCaptor.capture(),
+                any(ServiceConnection.class),
+                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+                eq(UserHandle.CURRENT));
+        // Verify bind car mode ui
+        Intent bindIntent = bindIntentCaptor.getAllValues().get(0);
+        assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
+        assertEquals(CAR_PKG, bindIntent.getComponent().getPackageName());
+        assertEquals(CAR_CLASS, bindIntent.getComponent().getClassName());
+    }
+
+    /**
+     * Make sure the InCallController completes its binding future when the in call service
+     * finishes binding.
+     */
+    @MediumTest
+    @Test
+    public void testBindingFuture() throws Exception {
+        when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
+        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+        when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
+        when(mMockCall.isIncoming()).thenReturn(false);
+        when(mMockCall.isExternalCall()).thenReturn(false);
+        when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID)).thenReturn(DEF_PKG);
+        when(mMockContext.bindServiceAsUser(nullable(Intent.class),
+                nullable(ServiceConnection.class), anyInt(), nullable(UserHandle.class)))
+                .thenReturn(true);
+        when(mTimeoutsAdapter.getCallRemoveUnbindInCallServicesDelay(
+                nullable(ContentResolver.class))).thenReturn(500L);
+
+        when(mMockCallsManager.getCalls()).thenReturn(Collections.singletonList(mMockCall));
+        setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
+        mInCallController.bindToServices(mMockCall);
+
+        ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
+        ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
+                ArgumentCaptor.forClass(ServiceConnection.class);
+        verify(mMockContext, times(1)).bindServiceAsUser(
+                bindIntentCaptor.capture(),
+                serviceConnectionCaptor.capture(),
+                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+                eq(UserHandle.CURRENT));
+
+        CompletableFuture<Boolean> bindTimeout = mInCallController.getBindingFuture();
+
+        assertFalse(bindTimeout.isDone());
+
+        // Start the connection, make sure we don't unbind, and make sure that we don't send
+        // anything to the in-call service yet.
+        ServiceConnection serviceConnection = serviceConnectionCaptor.getValue();
+        ComponentName defDialerComponentName = new ComponentName(DEF_PKG, DEF_CLASS);
+        IBinder mockBinder = mock(IBinder.class);
+        IInCallService mockInCallService = mock(IInCallService.class);
+        when(mockBinder.queryLocalInterface(anyString())).thenReturn(mockInCallService);
+
+        serviceConnection.onServiceConnected(defDialerComponentName, mockBinder);
+        verify(mockInCallService).setInCallAdapter(nullable(IInCallAdapter.class));
+
+        // Make sure that the future completed without timing out.
+        assertTrue(bindTimeout.getNow(false));
+    }
+
     private void setupMocks(boolean isExternalCall) {
         when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
         when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
@@ -521,6 +689,22 @@
         }};
     }
 
+    private ResolveInfo getCarModeResolveinfo(final boolean includeExternalCalls) {
+        return new ResolveInfo() {{
+            serviceInfo = new ServiceInfo();
+            serviceInfo.packageName = CAR_PKG;
+            serviceInfo.name = CAR_CLASS;
+            serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
+            serviceInfo.metaData = new Bundle();
+            serviceInfo.metaData.putBoolean(
+                    TelecomManager.METADATA_IN_CALL_SERVICE_CAR_MODE_UI, true);
+            if (includeExternalCalls) {
+                serviceInfo.metaData.putBoolean(
+                        TelecomManager.METADATA_INCLUDE_EXTERNAL_CALLS, true);
+            }
+        }};
+    }
+
     private ResolveInfo getSysResolveinfo() {
         return new ResolveInfo() {{
             serviceInfo = new ServiceInfo();
@@ -530,6 +714,15 @@
         }};
     }
 
+    private ResolveInfo getCompanionResolveinfo() {
+        return new ResolveInfo() {{
+            serviceInfo = new ServiceInfo();
+            serviceInfo.packageName = COMPANION_PKG;
+            serviceInfo.name = COMPANION_CLASS;
+            serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
+        }};
+    }
+
     private void setupMockPackageManager(final boolean useDefaultDialer,
             final boolean useSystemDialer, final boolean includeExternalCalls) {
 
@@ -545,15 +738,21 @@
                 }
                 LinkedList<ResolveInfo> resolveInfo = new LinkedList<ResolveInfo>();
                 if (!TextUtils.isEmpty(packageName)) {
-                    if ((TextUtils.isEmpty(packageName) || packageName.equals(DEF_PKG)) &&
-                            useDefaultDialer) {
+                    if (packageName.equals(DEF_PKG) && useDefaultDialer) {
                         resolveInfo.add(getDefResolveInfo(includeExternalCalls));
                     }
 
-                    if ((TextUtils.isEmpty(packageName) || packageName.equals(SYS_PKG)) &&
-                           useSystemDialer) {
+                    if (packageName.equals(SYS_PKG) && useSystemDialer) {
                         resolveInfo.add(getSysResolveinfo());
                     }
+
+                    if (packageName.equals(COMPANION_PKG)) {
+                        resolveInfo.add(getCompanionResolveinfo());
+                    }
+
+                    if (packageName.equals(CAR_PKG)) {
+                        resolveInfo.add(getCarModeResolveinfo(includeExternalCalls));
+                    }
                 }
                 return resolveInfo;
             }
diff --git a/tests/src/com/android/server/telecom/tests/InCallServiceFixture.java b/tests/src/com/android/server/telecom/tests/InCallServiceFixture.java
index 69fcdd8..d114cb8 100644
--- a/tests/src/com/android/server/telecom/tests/InCallServiceFixture.java
+++ b/tests/src/com/android/server/telecom/tests/InCallServiceFixture.java
@@ -76,7 +76,11 @@
         @Override
         public void updateCall(ParcelableCall call) throws RemoteException {
             if (!mCallById.containsKey(call.getId())) {
-                throw new RuntimeException("Call " + call.getId() + " not added yet");
+                // This used to throw an exception, however the actual InCallService implementation
+                // ignores updates for calls which don't yet exist.  This is not a problem as when
+                // a call is added to an InCallService its entire state is parceled and sent to the
+                // InCallService.
+                return;
             }
             mLatestCallId = call.getId();
             mCallById.put(call.getId(), call);
diff --git a/tests/src/com/android/server/telecom/tests/InCallTonePlayerTest.java b/tests/src/com/android/server/telecom/tests/InCallTonePlayerTest.java
new file mode 100644
index 0000000..cb0497a
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/InCallTonePlayerTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2018 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 org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.media.MediaPlayer;
+import android.media.ToneGenerator;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.FlakyTest;
+
+import com.android.server.telecom.CallAudioManager;
+import com.android.server.telecom.CallAudioRoutePeripheralAdapter;
+import com.android.server.telecom.InCallTonePlayer;
+import com.android.server.telecom.TelecomSystem;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+
+@RunWith(JUnit4.class)
+public class InCallTonePlayerTest extends TelecomTestCase {
+
+    private InCallTonePlayer.Factory mFactory;
+
+    @Mock
+    private CallAudioRoutePeripheralAdapter mCallAudioRoutePeripheralAdapter;
+
+    @Mock
+    private TelecomSystem.SyncRoot mLock;
+
+    @Mock
+    private ToneGenerator mToneGenerator;
+
+    @Mock
+    private InCallTonePlayer.ToneGeneratorFactory mToneGeneratorFactory;
+
+    private InCallTonePlayer.MediaPlayerAdapter mMediaPlayerAdapter =
+            new InCallTonePlayer.MediaPlayerAdapter() {
+        private MediaPlayer.OnCompletionListener mListener;
+
+        @Override
+        public void setLooping(boolean isLooping) {
+            // Do nothing.
+        }
+
+        @Override
+        public void setOnCompletionListener(MediaPlayer.OnCompletionListener listener) {
+            mListener = listener;
+        }
+
+        @Override
+        public void start() {
+            mListener.onCompletion(null);
+        }
+
+        @Override
+        public void release() {
+            // Do nothing.
+        }
+
+        @Override
+        public int getDuration() {
+            return 0;
+        }
+    };
+
+    @Mock
+    private InCallTonePlayer.MediaPlayerFactory mMediaPlayerFactory;
+
+    @Mock
+    private InCallTonePlayer.AudioManagerAdapter mAudioManagerAdapter;
+
+    @Mock
+    private CallAudioManager mCallAudioManager;
+
+    private InCallTonePlayer mInCallTonePlayer;
+
+    @Override
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+
+        when(mToneGeneratorFactory.get(anyInt(), anyInt())).thenReturn(mToneGenerator);
+        when(mMediaPlayerFactory.get(anyInt(), any())).thenReturn(mMediaPlayerAdapter);
+
+        mFactory = new InCallTonePlayer.Factory(mCallAudioRoutePeripheralAdapter, mLock,
+                mToneGeneratorFactory, mMediaPlayerFactory, mAudioManagerAdapter);
+        mFactory.setCallAudioManager(mCallAudioManager);
+        mInCallTonePlayer = mFactory.createPlayer(InCallTonePlayer.TONE_CALL_ENDED);
+    }
+
+    @Override
+    @After
+    public void tearDown() throws Exception {
+        super.tearDown();
+        mInCallTonePlayer.cleanup();
+    }
+
+    @SmallTest
+    @Test
+    public void testNoEndCallToneInSilence() {
+        when(mAudioManagerAdapter.isVolumeOverZero()).thenReturn(false);
+        assertFalse(mInCallTonePlayer.startTone());
+
+        // Verify we didn't play a tone.
+        verify(mCallAudioManager, never()).setIsTonePlaying(eq(true));
+        verify(mMediaPlayerFactory, never()).get(anyInt(), any());
+    }
+
+    @FlakyTest
+    @SmallTest
+    @Test
+    public void testEndCallToneWhenNotSilenced() {
+        when(mAudioManagerAdapter.isVolumeOverZero()).thenReturn(true);
+        assertTrue(mInCallTonePlayer.startTone());
+
+        // Verify we did play a tone.
+        verify(mMediaPlayerFactory, timeout(5000)).get(anyInt(), any());
+        verify(mCallAudioManager).setIsTonePlaying(eq(true));
+    }
+}
diff --git a/tests/src/com/android/server/telecom/tests/IncomingCallFilterTest.java b/tests/src/com/android/server/telecom/tests/IncomingCallFilterTest.java
index d975ec2..e399088 100644
--- a/tests/src/com/android/server/telecom/tests/IncomingCallFilterTest.java
+++ b/tests/src/com/android/server/telecom/tests/IncomingCallFilterTest.java
@@ -19,6 +19,7 @@
 import android.content.ContentResolver;
 import android.content.IContentProvider;
 import android.net.Uri;
+import android.provider.CallLog;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.server.telecom.Call;
@@ -55,6 +56,7 @@
     @Mock private IncomingCallFilter.CallFilter mFilter1;
     @Mock private IncomingCallFilter.CallFilter mFilter2;
     @Mock private IncomingCallFilter.CallFilter mFilter3;
+    @Mock private IncomingCallFilter.CallFilter mFilter4;
 
     @Mock private Timeouts.Adapter mTimeoutsAdapter;
 
@@ -62,7 +64,7 @@
     private static final long LONG_TIMEOUT = 1000000;
     private static final long SHORT_TIMEOUT = 100;
 
-    private static final CallFilteringResult RESULT1 =
+    private static final CallFilteringResult PASS_CALL_RESULT =
             new CallFilteringResult(
                     true, // shouldAllowCall
                     false, // shouldReject
@@ -70,23 +72,41 @@
                     true // shouldShowNotification
             );
 
-    private static final CallFilteringResult RESULT2 =
-            new CallFilteringResult(
-                    false, // shouldAllowCall
-                    true, // shouldReject
-                    false, // shouldAddToCallLog
-                    true // shouldShowNotification
-            );
-
-    private static final CallFilteringResult RESULT3 =
+    private static final CallFilteringResult ASYNC_BLOCK_CHECK_BLOCK_RESULT =
             new CallFilteringResult(
                     false, // shouldAllowCall
                     true, // shouldReject
                     true, // shouldAddToCallLog
-                    false // shouldShowNotification
+                    false, // shouldShowNotification
+                    CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER, //callBlockReason
+                    null, //callScreeningAppName
+                    null //callScreeningComponentName
             );
 
-    private static final CallFilteringResult DEFAULT_RESULT = RESULT1;
+    private static final CallFilteringResult DIRECT_TO_VOICEMAIL_CALL_BLOCK_RESULT =
+            new CallFilteringResult(
+                    false, // shouldAllowCall
+                    true, // shouldReject
+                    true, // shouldAddToCallLog
+                    true, // shouldShowNotification
+                    CallLog.Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL, //callBlockReason
+                    null, //callScreeningAppName
+                    null //callScreeningComponentName
+            );
+
+    private static final CallFilteringResult CALL_SCREENING_SERVICE_BLOCK_RESULT =
+            new CallFilteringResult(
+                    false, // shouldAllowCall
+                    true, // shouldReject
+                    false, // shouldAddToCallLog
+                    true, // shouldShowNotification
+                    CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, //callBlockReason
+                    "com.android.thirdparty", //callScreeningAppName
+                    "com.android.thirdparty/com.android.thirdparty.callscreeningserviceimpl"
+                    //callScreeningComponentName
+            );
+
+    private static final CallFilteringResult DEFAULT_RESULT = PASS_CALL_RESULT;
 
     @Override
     @Before
@@ -99,20 +119,97 @@
 
     @SmallTest
     @Test
-    public void testSingleFilter() {
+    public void testAsyncBlockCallResultFilter() {
         IncomingCallFilter testFilter = new IncomingCallFilter(mContext, mResultCallback, mCall,
                 mLock, mTimeoutsAdapter, Collections.singletonList(mFilter1));
         testFilter.performFiltering();
         verify(mFilter1).startFilterLookup(mCall, testFilter);
 
-        testFilter.onCallFilteringComplete(mCall, RESULT1);
+        testFilter.onCallFilteringComplete(mCall, ASYNC_BLOCK_CHECK_BLOCK_RESULT);
         waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
-        verify(mResultCallback).onCallFilteringComplete(eq(mCall), eq(RESULT1));
+        verify(mResultCallback).onCallFilteringComplete(eq(mCall), eq
+                (ASYNC_BLOCK_CHECK_BLOCK_RESULT));
     }
 
     @SmallTest
     @Test
-    public void testMultipleFilters() {
+    public void testDirectToVoiceMailCallResultFilter() {
+        IncomingCallFilter testFilter = new IncomingCallFilter(mContext, mResultCallback, mCall,
+                mLock, mTimeoutsAdapter, Collections.singletonList(mFilter1));
+        testFilter.performFiltering();
+        verify(mFilter1).startFilterLookup(mCall, testFilter);
+
+        testFilter.onCallFilteringComplete(mCall, DIRECT_TO_VOICEMAIL_CALL_BLOCK_RESULT);
+        waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
+        verify(mResultCallback).onCallFilteringComplete(eq(mCall), eq
+                (DIRECT_TO_VOICEMAIL_CALL_BLOCK_RESULT));
+    }
+
+    @SmallTest
+    @Test
+    public void testCallScreeningServiceBlockCallResultFilter() {
+        IncomingCallFilter testFilter = new IncomingCallFilter(mContext, mResultCallback, mCall,
+                mLock, mTimeoutsAdapter, Collections.singletonList(mFilter1));
+        testFilter.performFiltering();
+        verify(mFilter1).startFilterLookup(mCall, testFilter);
+
+        testFilter.onCallFilteringComplete(mCall, CALL_SCREENING_SERVICE_BLOCK_RESULT);
+        waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
+        verify(mResultCallback).onCallFilteringComplete(eq(mCall), eq
+                (CALL_SCREENING_SERVICE_BLOCK_RESULT));
+    }
+
+    @SmallTest
+    @Test
+    public void testPassCallResultFilter() {
+        IncomingCallFilter testFilter = new IncomingCallFilter(mContext, mResultCallback, mCall,
+                mLock, mTimeoutsAdapter, Collections.singletonList(mFilter1));
+        testFilter.performFiltering();
+        verify(mFilter1).startFilterLookup(mCall, testFilter);
+
+        testFilter.onCallFilteringComplete(mCall, PASS_CALL_RESULT);
+        waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
+        verify(mResultCallback).onCallFilteringComplete(eq(mCall), eq(PASS_CALL_RESULT));
+    }
+
+    @SmallTest
+    @Test
+    public void testMultipleFiltersForAsyncBlockCheckFilter() {
+        List<IncomingCallFilter.CallFilter> filters =
+                new ArrayList<IncomingCallFilter.CallFilter>() {{
+                    add(mFilter1);
+                    add(mFilter2);
+                    add(mFilter3);
+                    add(mFilter4);
+                }};
+        IncomingCallFilter testFilter = new IncomingCallFilter(mContext, mResultCallback, mCall,
+                mLock, mTimeoutsAdapter, filters);
+        testFilter.performFiltering();
+        verify(mFilter1).startFilterLookup(mCall, testFilter);
+        verify(mFilter2).startFilterLookup(mCall, testFilter);
+        verify(mFilter3).startFilterLookup(mCall, testFilter);
+        verify(mFilter4).startFilterLookup(mCall, testFilter);
+
+        testFilter.onCallFilteringComplete(mCall, PASS_CALL_RESULT);
+        testFilter.onCallFilteringComplete(mCall, ASYNC_BLOCK_CHECK_BLOCK_RESULT);
+        testFilter.onCallFilteringComplete(mCall, DIRECT_TO_VOICEMAIL_CALL_BLOCK_RESULT);
+        testFilter.onCallFilteringComplete(mCall, CALL_SCREENING_SERVICE_BLOCK_RESULT);
+        waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
+        verify(mResultCallback).onCallFilteringComplete(eq(mCall), eq(
+                new CallFilteringResult(
+                        false, // shouldAllowCall
+                        true, // shouldReject
+                        false, // shouldAddToCallLog
+                        false, // shouldShowNotification
+                        CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER, //callBlockReason
+                        null, //callScreeningAppName
+                        null //callScreeningComponentName
+                )));
+    }
+
+    @SmallTest
+    @Test
+    public void testMultipleFiltersForDirectToVoicemailCallFilter() {
         List<IncomingCallFilter.CallFilter> filters =
                 new ArrayList<IncomingCallFilter.CallFilter>() {{
                     add(mFilter1);
@@ -126,16 +223,49 @@
         verify(mFilter2).startFilterLookup(mCall, testFilter);
         verify(mFilter3).startFilterLookup(mCall, testFilter);
 
-        testFilter.onCallFilteringComplete(mCall, RESULT1);
-        testFilter.onCallFilteringComplete(mCall, RESULT2);
-        testFilter.onCallFilteringComplete(mCall, RESULT3);
+        testFilter.onCallFilteringComplete(mCall, PASS_CALL_RESULT);
+        testFilter.onCallFilteringComplete(mCall, DIRECT_TO_VOICEMAIL_CALL_BLOCK_RESULT);
+        testFilter.onCallFilteringComplete(mCall, CALL_SCREENING_SERVICE_BLOCK_RESULT);
         waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
         verify(mResultCallback).onCallFilteringComplete(eq(mCall), eq(
                 new CallFilteringResult(
                         false, // shouldAllowCall
                         true, // shouldReject
                         false, // shouldAddToCallLog
-                        false // shouldShowNotification
+                        true, // shouldShowNotification
+                        CallLog.Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL, //callBlockReason
+                        null, ////callScreeningAppName
+                        null ////callScreeningComponentName
+                )));
+    }
+
+    @SmallTest
+    @Test
+    public void testMultipleFiltersForCallScreeningServiceFilter() {
+        List<IncomingCallFilter.CallFilter> filters =
+                new ArrayList<IncomingCallFilter.CallFilter>() {{
+                    add(mFilter1);
+                    add(mFilter2);
+                }};
+        IncomingCallFilter testFilter = new IncomingCallFilter(mContext, mResultCallback, mCall,
+                mLock, mTimeoutsAdapter, filters);
+        testFilter.performFiltering();
+        verify(mFilter1).startFilterLookup(mCall, testFilter);
+        verify(mFilter2).startFilterLookup(mCall, testFilter);
+
+        testFilter.onCallFilteringComplete(mCall, PASS_CALL_RESULT);
+        testFilter.onCallFilteringComplete(mCall, CALL_SCREENING_SERVICE_BLOCK_RESULT);
+        waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
+        verify(mResultCallback).onCallFilteringComplete(eq(mCall), eq(
+                new CallFilteringResult(
+                        false, // shouldAllowCall
+                        true, // shouldReject
+                        false, // shouldAddToCallLog
+                        true, // shouldShowNotification
+                        CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, //callBlockReason
+                        "com.android.thirdparty", //callScreeningAppName
+                        "com.android.thirdparty/com.android.thirdparty.callscreeningserviceimpl"
+                        //callScreeningComponentName
                 )));
     }
 
@@ -148,7 +278,7 @@
         testFilter.performFiltering();
         verify(mResultCallback, timeout((int) SHORT_TIMEOUT * 2)).onCallFilteringComplete(eq(mCall),
                 eq(DEFAULT_RESULT));
-        testFilter.onCallFilteringComplete(mCall, RESULT1);
+        testFilter.onCallFilteringComplete(mCall, PASS_CALL_RESULT);
         waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
         // verify that we don't report back again with the result
         verify(mResultCallback, atMost(1)).onCallFilteringComplete(any(Call.class),
@@ -162,7 +292,7 @@
         IncomingCallFilter testFilter = new IncomingCallFilter(mContext, mResultCallback, mCall,
                 mLock, mTimeoutsAdapter, Collections.singletonList(mFilter1));
         testFilter.performFiltering();
-        testFilter.onCallFilteringComplete(mCall, RESULT1);
+        testFilter.onCallFilteringComplete(mCall, PASS_CALL_RESULT);
         waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
         Thread.sleep(SHORT_TIMEOUT);
         verify(mResultCallback, atMost(1)).onCallFilteringComplete(any(Call.class),
@@ -172,9 +302,13 @@
     @SmallTest
     @Test
     public void testToString() {
-        assertEquals("[Allow, logged, notified]", RESULT1.toString());
-        assertEquals("[Reject, notified]", RESULT2.toString());
-        assertEquals("[Reject, logged]", RESULT3.toString());
+        assertEquals("[Allow, logged, notified]", PASS_CALL_RESULT.toString());
+        assertEquals("[Reject, notified, mCallBlockReason = 1, mCallScreeningAppName = com" +
+                ".android.thirdparty, mCallScreeningComponentName = com.android.thirdparty/com" +
+                ".android.thirdparty.callscreeningserviceimpl]",
+            CALL_SCREENING_SERVICE_BLOCK_RESULT.toString());
+        assertEquals("[Reject, logged, mCallBlockReason = 3]",
+            ASYNC_BLOCK_CHECK_BLOCK_RESULT.toString());
     }
 
     private void setTimeoutLength(long length) throws Exception {
diff --git a/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java b/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
index 4c0e76a..ae48cb5 100644
--- a/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
+++ b/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
@@ -28,6 +28,7 @@
 import android.os.Handler;
 import android.os.UserHandle;
 import android.telecom.GatewayInfo;
+import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
 import android.telephony.DisconnectCause;
@@ -36,8 +37,11 @@
 import com.android.server.telecom.Call;
 import com.android.server.telecom.CallsManager;
 import com.android.server.telecom.NewOutgoingCallIntentBroadcaster;
+import com.android.server.telecom.RoleManagerAdapter;
+import com.android.server.telecom.PhoneAccountRegistrar;
 import com.android.server.telecom.PhoneNumberUtilsAdapter;
 import com.android.server.telecom.PhoneNumberUtilsAdapterImpl;
+import com.android.server.telecom.SystemStateHelper;
 import com.android.server.telecom.TelecomSystem;
 
 import org.junit.Before;
@@ -78,6 +82,10 @@
 
     @Mock private CallsManager mCallsManager;
     @Mock private Call mCall;
+    @Mock private SystemStateHelper mSystemStateHelper;
+    @Mock private UserHandle mUserHandle;
+    @Mock private PhoneAccountRegistrar mPhoneAccountRegistrar;
+    @Mock private RoleManagerAdapter mRoleManagerAdapter;
 
     private PhoneNumberUtilsAdapter mPhoneNumberUtilsAdapterSpy;
 
@@ -89,13 +97,20 @@
         mPhoneNumberUtilsAdapterSpy = spy(new PhoneNumberUtilsAdapterImpl());
         when(mCall.getInitiatingUser()).thenReturn(UserHandle.CURRENT);
         when(mCallsManager.getLock()).thenReturn(new TelecomSystem.SyncRoot() { });
+        when(mCallsManager.getSystemStateHelper()).thenReturn(mSystemStateHelper);
+        when(mCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
+        when(mCallsManager.getPhoneAccountRegistrar()).thenReturn(mPhoneAccountRegistrar);
+        when(mCallsManager.getRoleManagerAdapter()).thenReturn(mRoleManagerAdapter);
+        when(mPhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(
+                any(PhoneAccountHandle.class))).thenReturn(-1);
+        when(mSystemStateHelper.isCarMode()).thenReturn(false);
     }
 
     @SmallTest
     @Test
     public void testNullHandle() {
         Intent intent = new Intent(Intent.ACTION_CALL, null);
-        int result = processIntent(intent, true);
+        int result = processIntent(intent, true).disconnectCause;
         assertEquals(DisconnectCause.INVALID_NUMBER, result);
         verifyNoBroadcastSent();
         verifyNoCallPlaced();
@@ -108,7 +123,7 @@
         Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(voicemailNumber));
         intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, true);
 
-        int result = processIntent(intent, true);
+        int result = processIntent(intent, true).disconnectCause;
 
         assertEquals(DisconnectCause.NOT_DISCONNECTED, result);
         verify(mCallsManager).placeOutgoingCall(eq(mCall), eq(Uri.parse(voicemailNumber)),
@@ -136,7 +151,7 @@
     private void badCallActionHelper(Uri handle, int expectedCode) {
         Intent intent = new Intent(Intent.ACTION_ALARM_CHANGED, handle);
 
-        int result = processIntent(intent, true);
+        int result = processIntent(intent, true).disconnectCause;
 
         assertEquals(expectedCode, result);
         verifyNoBroadcastSent();
@@ -164,7 +179,7 @@
         Uri handle = Uri.parse("tel:");
         Intent intent = new Intent(Intent.ACTION_CALL, handle);
 
-        int result = processIntent(intent, true);
+        int result = processIntent(intent, true).disconnectCause;
 
         assertEquals(DisconnectCause.NO_PHONE_NUMBER_SUPPLIED, result);
         verifyNoBroadcastSent();
@@ -185,7 +200,7 @@
         mComponentContextFixture.putResource(R.string.dialer_default_class,
                 dialer_default_class_string);
 
-        int result = processIntent(intent, false);
+        int result = processIntent(intent, false).disconnectCause;
 
         assertEquals(DisconnectCause.OUTGOING_CANCELED, result);
         verifyNoBroadcastSent();
@@ -245,7 +260,7 @@
         doReturn(false).when(mPhoneNumberUtilsAdapterSpy).isPotentialLocalEmergencyNumber(
                 any(Context.class), eq(handle.getSchemeSpecificPart()));
         Intent intent = new Intent(Intent.ACTION_CALL_EMERGENCY, handle);
-        int result = processIntent(intent, true);
+        int result = processIntent(intent, true).disconnectCause;
 
         assertEquals(DisconnectCause.OUTGOING_CANCELED, result);
         verifyNoCallPlaced();
@@ -260,7 +275,7 @@
                 any(Context.class), eq(handle.getSchemeSpecificPart()));
         intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, isSpeakerphoneOn);
         intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState);
-        int result = processIntent(intent, true);
+        int result = processIntent(intent, true).disconnectCause;
 
         assertEquals(DisconnectCause.NOT_DISCONNECTED, result);
         verify(mCallsManager).placeOutgoingCall(eq(mCall), eq(handle), isNull(GatewayInfo.class),
@@ -389,7 +404,7 @@
         intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, isSpeakerphoneOn);
         intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState);
 
-        int result = processIntent(intent, true);
+        int result = processIntent(intent, true).disconnectCause;
 
         assertEquals(DisconnectCause.NOT_DISCONNECTED, result);
         Bundle expectedExtras = createNumberExtras(handle.getSchemeSpecificPart());
@@ -407,12 +422,16 @@
         return i;
     }
 
-    private int processIntent(Intent intent,
+    private NewOutgoingCallIntentBroadcaster.CallDisposition processIntent(Intent intent,
             boolean isDefaultPhoneApp) {
         NewOutgoingCallIntentBroadcaster b = new NewOutgoingCallIntentBroadcaster(
                 mContext, mCallsManager, mCall, intent, mPhoneNumberUtilsAdapterSpy,
                 isDefaultPhoneApp);
-        return b.processIntent();
+        NewOutgoingCallIntentBroadcaster.CallDisposition cd = b.evaluateCall();
+        if (cd.disconnectCause == DisconnectCause.NOT_DISCONNECTED) {
+            b.processCall(cd);
+        }
+        return cd;
     }
 
     private ReceiverIntentPair verifyBroadcastSent(String number, Bundle expectedExtras) {
diff --git a/tests/src/com/android/server/telecom/tests/ParcelableCallUtilsTest.java b/tests/src/com/android/server/telecom/tests/ParcelableCallUtilsTest.java
new file mode 100644
index 0000000..753b635
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/ParcelableCallUtilsTest.java
@@ -0,0 +1,122 @@
+package com.android.server.telecom.tests;
+
+import static com.android.server.telecom.TelecomSystem.*;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.telecom.Connection;
+import android.telecom.GatewayInfo;
+import android.telecom.ParcelableCall;
+import android.telecom.PhoneAccountHandle;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.server.telecom.Call;
+import com.android.server.telecom.CallerInfoLookupHelper;
+import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.ClockProxy;
+import com.android.server.telecom.ConnectionServiceRepository;
+import com.android.server.telecom.ParcelableCallUtils;
+import com.android.server.telecom.PhoneAccountRegistrar;
+import com.android.server.telecom.PhoneNumberUtilsAdapter;
+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.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(JUnit4.class)
+public class ParcelableCallUtilsTest extends TelecomTestCase {
+
+    private SyncRoot mLock = new SyncRoot() {};
+    @Mock private ClockProxy mClockProxy;
+    @Mock private CallsManager mCallsManager;
+    @Mock private CallerInfoLookupHelper mCallerInfoLookupHelper;
+    @Mock private PhoneNumberUtilsAdapter mPhoneNumberUtilsAdapter;
+    @Mock private PhoneAccountRegistrar mPhoneAccountRegistrar;
+    private Call mCall;
+
+    @Override
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+        when(mClockProxy.currentTimeMillis()).thenReturn(System.currentTimeMillis());
+        when(mClockProxy.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime());
+        when(mCallsManager.getCallerInfoLookupHelper()).thenReturn(mCallerInfoLookupHelper);
+        when(mCallsManager.getPhoneAccountRegistrar()).thenReturn(mPhoneAccountRegistrar);
+        when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(any())).thenReturn(null);
+        when(mPhoneNumberUtilsAdapter.isLocalEmergencyNumber(any(), any())).thenReturn(false);
+        mCall = new Call("1",
+                null /* context */,
+                mCallsManager,
+                mLock,
+                null /* ConnectionServiceRepository */,
+                mPhoneNumberUtilsAdapter,
+                Uri.fromParts("tel", "6505551212", null),
+                null /* GatewayInfo */,
+                null /* connectionMgr */,
+                new PhoneAccountHandle(
+                        ComponentName.unflattenFromString("com.test/Class"), "test"),
+                Call.CALL_DIRECTION_INCOMING,
+                false /* shouldAttachToExistingConnection */,
+                false /* isConference */,
+                mClockProxy /* ClockProxy */);
+    }
+
+    @SmallTest
+    @Test
+    public void testParcelForNonSystemDialer() {
+        mCall.putExtras(Call.SOURCE_CONNECTION_SERVICE, getSomeExtras());
+        ParcelableCall call = ParcelableCallUtils.toParcelableCall(mCall,
+                false /* includevideoProvider */,
+                null /* phoneAccountRegistrar */,
+                false /* supportsExternalCalls */,
+                false /* includeRttCall */,
+                false /* isForSystemDialer */);
+
+        Bundle parceledExtras = call.getExtras();
+        assertFalse(parceledExtras.containsKey(Connection.EXTRA_SIP_INVITE));
+        assertFalse(parceledExtras.containsKey("SomeExtra"));
+        assertTrue(parceledExtras.containsKey(Connection.EXTRA_CALL_SUBJECT));
+    }
+
+    @SmallTest
+    @Test
+    public void testParcelForSystemDialer() {
+        mCall.putExtras(Call.SOURCE_CONNECTION_SERVICE, getSomeExtras());
+        ParcelableCall call = ParcelableCallUtils.toParcelableCall(mCall,
+                false /* includevideoProvider */,
+                null /* phoneAccountRegistrar */,
+                false /* supportsExternalCalls */,
+                false /* includeRttCall */,
+                true /* isForSystemDialer */);
+
+        Bundle parceledExtras = call.getExtras();
+        assertTrue(parceledExtras.containsKey(Connection.EXTRA_SIP_INVITE));
+        assertTrue(parceledExtras.containsKey("SomeExtra"));
+        assertTrue(parceledExtras.containsKey(Connection.EXTRA_CALL_SUBJECT));
+    }
+
+    private Bundle getSomeExtras() {
+        Bundle extras = new Bundle();
+        extras.putString(Connection.EXTRA_SIP_INVITE, "scary data");
+        extras.putString("SomeExtra", "Extra Extra");
+        extras.putString(Connection.EXTRA_CALL_SUBJECT, "Blah");
+        return extras;
+    }
+}
diff --git a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
index f8acb9d..a978cfd 100644
--- a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
+++ b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
@@ -16,6 +16,16 @@
 
 package com.android.server.telecom.tests;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.when;
+
 import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.BitmapFactory;
@@ -27,14 +37,16 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.support.test.InstrumentationRegistry;
 import android.telecom.Log;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.util.Xml;
 
+import androidx.test.InstrumentationRegistry;
+
 import com.android.internal.telecom.IConnectionService;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.server.telecom.DefaultDialerCache;
@@ -62,16 +74,6 @@
 import java.util.Map;
 import java.util.Set;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.when;
-
 @RunWith(JUnit4.class)
 public class PhoneAccountRegistrarTest extends TelecomTestCase {
 
@@ -909,6 +911,37 @@
         assertEquals(account1, account2);
     }
 
+    /**
+     * Tests {@link PhoneAccountHandle#areFromSamePackage(PhoneAccountHandle,
+     * PhoneAccountHandle)} comparison.
+     */
+    @SmallTest
+    @Test
+    public void testSamePhoneAccountHandlePackage() {
+        PhoneAccountHandle a = new PhoneAccountHandle(new ComponentName("packageA", "class1"),
+                "id1");
+        PhoneAccountHandle b = new PhoneAccountHandle(new ComponentName("packageA", "class2"),
+                "id2");
+        PhoneAccountHandle c = new PhoneAccountHandle(new ComponentName("packageA", "class1"),
+                "id3");
+        PhoneAccountHandle d = new PhoneAccountHandle(new ComponentName("packageB", "class1"),
+                "id1");
+
+        assertTrue(PhoneAccountHandle.areFromSamePackage(null, null));
+        assertTrue(PhoneAccountHandle.areFromSamePackage(a, b));
+        assertTrue(PhoneAccountHandle.areFromSamePackage(a, c));
+        assertTrue(PhoneAccountHandle.areFromSamePackage(b, c));
+        assertFalse(PhoneAccountHandle.areFromSamePackage(a, d));
+        assertFalse(PhoneAccountHandle.areFromSamePackage(b, d));
+        assertFalse(PhoneAccountHandle.areFromSamePackage(c, d));
+        assertFalse(PhoneAccountHandle.areFromSamePackage(a, null));
+        assertFalse(PhoneAccountHandle.areFromSamePackage(b, null));
+        assertFalse(PhoneAccountHandle.areFromSamePackage(c, null));
+        assertFalse(PhoneAccountHandle.areFromSamePackage(null, d));
+        assertFalse(PhoneAccountHandle.areFromSamePackage(null, d));
+        assertFalse(PhoneAccountHandle.areFromSamePackage(null, d));
+    }
+
     private static ComponentName makeQuickConnectionServiceComponentName() {
         return new ComponentName(
                 "com.android.server.telecom.tests",
diff --git a/tests/src/com/android/server/telecom/tests/RingerTest.java b/tests/src/com/android/server/telecom/tests/RingerTest.java
index 25460de..02ee137 100644
--- a/tests/src/com/android/server/telecom/tests/RingerTest.java
+++ b/tests/src/com/android/server/telecom/tests/RingerTest.java
@@ -18,12 +18,12 @@
 
 import android.app.NotificationManager;
 import android.content.Context;
-import android.content.res.Resources;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.Ringtone;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Parcel;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
 import android.telecom.TelecomManager;
@@ -42,20 +42,56 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import java.util.Objects;
+
 @RunWith(JUnit4.class)
 public class RingerTest extends TelecomTestCase {
     private static final Uri FAKE_RINGTONE_URI = Uri.parse("content://media/fake/audio/1729");
+    private static class UriVibrationEffect extends VibrationEffect {
+        final Uri mUri;
+
+        private UriVibrationEffect(Uri uri) {
+            mUri = uri;
+        }
+
+        @Override
+        public void validate() {
+            // not needed
+        }
+
+        @Override
+        public long getDuration() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            // not needed
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            UriVibrationEffect that = (UriVibrationEffect) o;
+            return Objects.equals(mUri, that.mUri);
+        }
+    }
 
     @Mock InCallTonePlayer.Factory mockPlayerFactory;
     @Mock SystemSettingsUtil mockSystemSettingsUtil;
@@ -63,6 +99,7 @@
     @Mock RingtoneFactory mockRingtoneFactory;
     @Mock Vibrator mockVibrator;
     @Mock InCallController mockInCallController;
+    @Spy Ringer.VibrationEffectProxy spyVibrationEffectProxy;
 
     @Mock InCallTonePlayer mockTonePlayer;
     @Mock Call mockCall1;
@@ -76,15 +113,21 @@
     public void setUp() throws Exception {
         super.setUp();
         mContext = mComponentContextFixture.getTestDouble().getApplicationContext();
-        mRingerUnderTest = new Ringer(mockPlayerFactory, mContext, mockSystemSettingsUtil,
-                mockRingtonePlayer, mockRingtoneFactory, mockVibrator, mockInCallController);
+        doAnswer(invocation -> {
+            Uri ringtoneUriForEffect = invocation.getArgument(0);
+            return new UriVibrationEffect(ringtoneUriForEffect);
+        }).when(spyVibrationEffectProxy).get(any(), any());
         when(mockPlayerFactory.createPlayer(anyInt())).thenReturn(mockTonePlayer);
         mockAudioManager =
                 (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
         when(mockAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
         NotificationManager notificationManager =
                 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+        when(mockTonePlayer.startTone()).thenReturn(true);
         when(notificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true);
+        mRingerUnderTest = new Ringer(mockPlayerFactory, mContext, mockSystemSettingsUtil,
+                mockRingtonePlayer, mockRingtoneFactory, mockVibrator, spyVibrationEffectProxy,
+                mockInCallController);
     }
 
     @SmallTest
@@ -207,9 +250,6 @@
     @SmallTest
     @Test
     public void testCustomVibrationForRingtone() {
-        Resources resources = mContext.getResources();
-        when(resources.getStringArray(com.android.internal.R.array.config_ringtoneEffectUris))
-                .thenReturn(new String[] { FAKE_RINGTONE_URI.toString() });
         mRingerUnderTest.startCallWaiting(mockCall1);
         Ringtone mockRingtone = mock(Ringtone.class);
         when(mockRingtoneFactory.getRingtone(any(Call.class))).thenReturn(mockRingtone);
@@ -218,7 +258,7 @@
         assertTrue(mRingerUnderTest.startRinging(mockCall2, false));
         verify(mockTonePlayer).stopTone();
         verify(mockRingtonePlayer).play(any(RingtoneFactory.class), any(Call.class));
-        verify(mockVibrator).vibrate(eq(VibrationEffect.get(FAKE_RINGTONE_URI, mContext)),
+        verify(mockVibrator).vibrate(eq(spyVibrationEffectProxy.get(FAKE_RINGTONE_URI, mContext)),
                 any(AudioAttributes.class));
     }
 
diff --git a/tests/src/com/android/server/telecom/tests/SystemStateHelperTest.java b/tests/src/com/android/server/telecom/tests/SystemStateHelperTest.java
new file mode 100644
index 0000000..efe8796
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/SystemStateHelperTest.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2015 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 org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.UiModeManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.server.telecom.SystemStateHelper;
+import com.android.server.telecom.SystemStateHelper.SystemStateListener;
+
+import org.junit.After;
+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.MockitoAnnotations;
+import org.mockito.internal.util.reflection.FieldSetter;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * Unit tests for SystemStateHelper
+ */
+@RunWith(JUnit4.class)
+public class SystemStateHelperTest extends TelecomTestCase {
+
+    Context mContext;
+    @Mock SystemStateListener mSystemStateListener;
+    @Mock Sensor mGravitySensor;
+    @Mock Sensor mProxSensor;
+    @Mock UiModeManager mUiModeManager;
+    @Mock SensorManager mSensorManager;
+    @Mock Intent mIntentEnter;
+    @Mock Intent mIntentExit;
+
+    @Override
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+        mContext = mComponentContextFixture.getTestDouble().getApplicationContext();
+        doReturn(mSensorManager).when(mContext).getSystemService(SensorManager.class);
+        when(mGravitySensor.getType()).thenReturn(Sensor.TYPE_GRAVITY);
+        when(mProxSensor.getType()).thenReturn(Sensor.TYPE_PROXIMITY);
+        when(mProxSensor.getMaximumRange()).thenReturn(5.0f);
+        when(mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY)).thenReturn(mGravitySensor);
+        when(mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)).thenReturn(mProxSensor);
+
+        mComponentContextFixture.putFloatResource(
+                R.dimen.device_on_ear_xy_gravity_threshold, 5.5f);
+        mComponentContextFixture.putFloatResource(
+                R.dimen.device_on_ear_y_gravity_negative_threshold, -1f);
+    }
+
+    @Override
+    @After
+    public void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    @SmallTest
+    @Test
+    public void testListeners() throws Exception {
+        SystemStateHelper systemStateHelper = new SystemStateHelper(mContext);
+
+        assertFalse(systemStateHelper.removeListener(mSystemStateListener));
+        systemStateHelper.addListener(mSystemStateListener);
+        assertTrue(systemStateHelper.removeListener(mSystemStateListener));
+        assertFalse(systemStateHelper.removeListener(mSystemStateListener));
+    }
+
+    @SmallTest
+    @Test
+    public void testQuerySystemForCarMode_True() {
+        when(mContext.getSystemService(Context.UI_MODE_SERVICE)).thenReturn(mUiModeManager);
+        when(mUiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_CAR);
+        assertTrue(new SystemStateHelper(mContext).isCarMode());
+    }
+
+    @SmallTest
+    @Test
+    public void testQuerySystemForCarMode_False() {
+        when(mContext.getSystemService(Context.UI_MODE_SERVICE)).thenReturn(mUiModeManager);
+        when(mUiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_NORMAL);
+        assertFalse(new SystemStateHelper(mContext).isCarMode());
+    }
+
+    @SmallTest
+    @Test
+    public void testReceiverAndIntentFilter() {
+        ArgumentCaptor<IntentFilter> intentFilter = ArgumentCaptor.forClass(IntentFilter.class);
+        new SystemStateHelper(mContext);
+        verify(mContext).registerReceiver(any(BroadcastReceiver.class), intentFilter.capture());
+
+        assertEquals(2, intentFilter.getValue().countActions());
+        assertEquals(UiModeManager.ACTION_ENTER_CAR_MODE, intentFilter.getValue().getAction(0));
+        assertEquals(UiModeManager.ACTION_EXIT_CAR_MODE, intentFilter.getValue().getAction(1));
+    }
+
+    @SmallTest
+    @Test
+    public void testOnEnterExitCarMode() {
+        ArgumentCaptor<BroadcastReceiver> receiver =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        new SystemStateHelper(mContext).addListener(mSystemStateListener);
+
+        verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class));
+
+        when(mIntentEnter.getAction()).thenReturn(UiModeManager.ACTION_ENTER_CAR_MODE);
+        receiver.getValue().onReceive(mContext, mIntentEnter);
+        verify(mSystemStateListener).onCarModeChanged(true);
+
+        when(mIntentExit.getAction()).thenReturn(UiModeManager.ACTION_EXIT_CAR_MODE);
+        receiver.getValue().onReceive(mContext, mIntentExit);
+        verify(mSystemStateListener).onCarModeChanged(false);
+
+        receiver.getValue().onReceive(mContext, new Intent("invalid action"));
+    }
+
+    @SmallTest
+    @Test
+    public void testDeviceOnEarCorrectlyDetected() {
+        doAnswer(invocation -> {
+            SensorEventListener listener = invocation.getArgument(0);
+            Sensor sensor = invocation.getArgument(1);
+            if (sensor.getType() == Sensor.TYPE_GRAVITY) {
+                listener.onSensorChanged(makeSensorEvent(
+                        new float[]{1.0f, 9.0f, 1.0f}, Sensor.TYPE_GRAVITY));
+            } else {
+                listener.onSensorChanged(makeSensorEvent(
+                        new float[]{0.0f}, Sensor.TYPE_PROXIMITY));
+            }
+            return true;
+        }).when(mSensorManager)
+                .registerListener(any(SensorEventListener.class), any(Sensor.class), anyInt());
+
+        assertTrue(SystemStateHelper.isDeviceAtEar(mContext));
+        verify(mSensorManager).unregisterListener(any(SensorEventListener.class));
+    }
+
+    @SmallTest
+    @Test
+    public void testDeviceIsNotOnEarWithProxNotSensed() {
+        doAnswer(invocation -> {
+            SensorEventListener listener = invocation.getArgument(0);
+            Sensor sensor = invocation.getArgument(1);
+            if (sensor.getType() == Sensor.TYPE_GRAVITY) {
+                listener.onSensorChanged(makeSensorEvent(
+                        new float[]{1.0f, 9.0f, 1.0f}, Sensor.TYPE_GRAVITY));
+            } else {
+                // do nothing to simulate proximity sensor not reporting
+            }
+            return true;
+        }).when(mSensorManager)
+                .registerListener(any(SensorEventListener.class), any(Sensor.class), anyInt());
+
+        assertFalse(SystemStateHelper.isDeviceAtEar(mContext));
+        verify(mSensorManager).unregisterListener(any(SensorEventListener.class));
+    }
+
+    @SmallTest
+    @Test
+    public void testDeviceIsNotOnEarWithWrongOrientation() {
+        doAnswer(invocation -> {
+            SensorEventListener listener = invocation.getArgument(0);
+            Sensor sensor = invocation.getArgument(1);
+            if (sensor.getType() == Sensor.TYPE_GRAVITY) {
+                listener.onSensorChanged(makeSensorEvent(
+                        new float[]{1.0f, 1.0f, 9.0f}, Sensor.TYPE_GRAVITY));
+            } else {
+                listener.onSensorChanged(makeSensorEvent(
+                        new float[]{0.0f}, Sensor.TYPE_PROXIMITY));
+            }
+            return true;
+        }).when(mSensorManager)
+                .registerListener(any(SensorEventListener.class), any(Sensor.class), anyInt());
+
+        assertFalse(SystemStateHelper.isDeviceAtEar(mContext));
+        verify(mSensorManager).unregisterListener(any(SensorEventListener.class));
+    }
+
+    @SmallTest
+    @Test
+    public void testDeviceIsNotOnEarWithMissingSensor() {
+        when(mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY)).thenReturn(null);
+        doAnswer(invocation -> {
+            SensorEventListener listener = invocation.getArgument(0);
+            Sensor sensor = invocation.getArgument(1);
+            if (sensor.getType() == Sensor.TYPE_GRAVITY) {
+                listener.onSensorChanged(makeSensorEvent(
+                        new float[]{1.0f, 9.0f, 1.0f}, Sensor.TYPE_GRAVITY));
+            } else {
+                listener.onSensorChanged(makeSensorEvent(
+                        new float[]{0.0f}, Sensor.TYPE_PROXIMITY));
+            }
+            return true;
+        }).when(mSensorManager)
+                .registerListener(any(SensorEventListener.class), any(Sensor.class), anyInt());
+
+        assertFalse(SystemStateHelper.isDeviceAtEar(mContext));
+    }
+
+    @SmallTest
+    @Test
+    public void testDeviceIsNotOnEarWithTimeout() {
+        doAnswer(invocation -> {
+            SensorEventListener listener = invocation.getArgument(0);
+            Sensor sensor = invocation.getArgument(1);
+            if (sensor.getType() == Sensor.TYPE_GRAVITY) {
+                // do nothing
+            } else {
+                listener.onSensorChanged(makeSensorEvent(
+                        new float[]{0.0f}, Sensor.TYPE_PROXIMITY));
+            }
+            return true;
+        }).when(mSensorManager)
+                .registerListener(any(SensorEventListener.class), any(Sensor.class), anyInt());
+
+        assertFalse(SystemStateHelper.isDeviceAtEar(mContext));
+    }
+
+    @SmallTest
+    @Test
+    public void testDeviceIsOnEarWithMultiSensorInputs() {
+        doAnswer(invocation -> {
+            SensorEventListener listener = invocation.getArgument(0);
+            Sensor sensor = invocation.getArgument(1);
+            if (sensor.getType() == Sensor.TYPE_GRAVITY) {
+                listener.onSensorChanged(makeSensorEvent(
+                        new float[]{1.0f, 9.0f, 1.0f}, Sensor.TYPE_GRAVITY));
+                listener.onSensorChanged(makeSensorEvent(
+                        new float[]{1.0f, -9.0f, 1.0f}, Sensor.TYPE_GRAVITY));
+                listener.onSensorChanged(makeSensorEvent(
+                        new float[]{1.0f, 0.0f, 8.0f}, Sensor.TYPE_GRAVITY));
+            } else {
+                listener.onSensorChanged(makeSensorEvent(
+                        new float[]{0.0f}, Sensor.TYPE_PROXIMITY));
+            }
+            return true;
+        }).when(mSensorManager)
+                .registerListener(any(SensorEventListener.class), any(Sensor.class), anyInt());
+
+        assertTrue(SystemStateHelper.isDeviceAtEar(mContext));
+        verify(mSensorManager).unregisterListener(any(SensorEventListener.class));
+    }
+
+    private SensorEvent makeSensorEvent(float[] values, int sensorType) throws Exception {
+        SensorEvent event = mock(SensorEvent.class);
+        Sensor mockSensor = mock(Sensor.class);
+        when(mockSensor.getType()).thenReturn(sensorType);
+        FieldSetter.setField(event, SensorEvent.class.getDeclaredField("sensor"), mockSensor);
+        FieldSetter.setField(event, SensorEvent.class.getDeclaredField("values"), values);
+        return event;
+    }
+}
diff --git a/tests/src/com/android/server/telecom/tests/SystemStateProviderTest.java b/tests/src/com/android/server/telecom/tests/SystemStateProviderTest.java
deleted file mode 100644
index 033f929..0000000
--- a/tests/src/com/android/server/telecom/tests/SystemStateProviderTest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2015 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 org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.UiModeManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Configuration;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.server.telecom.SystemStateProvider;
-import com.android.server.telecom.SystemStateProvider.SystemStateListener;
-
-import org.junit.After;
-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.MockitoAnnotations;
-
-/**
- * Unit tests for SystemStateProvider
- */
-@RunWith(JUnit4.class)
-public class SystemStateProviderTest extends TelecomTestCase {
-
-    @Mock Context mContext;
-    @Mock SystemStateListener mSystemStateListener;
-    @Mock UiModeManager mUiModeManager;
-    @Mock Intent mIntentEnter;
-    @Mock Intent mIntentExit;
-
-    @Override
-    @Before
-    public void setUp() throws Exception {
-        super.setUp();
-        MockitoAnnotations.initMocks(this);
-    }
-
-    @Override
-    @After
-    public void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-    @SmallTest
-    @Test
-    public void testListeners() throws Exception {
-        SystemStateProvider systemStateProvider = new SystemStateProvider(mContext);
-
-        assertFalse(systemStateProvider.removeListener(mSystemStateListener));
-        systemStateProvider.addListener(mSystemStateListener);
-        assertTrue(systemStateProvider.removeListener(mSystemStateListener));
-        assertFalse(systemStateProvider.removeListener(mSystemStateListener));
-    }
-
-    @SmallTest
-    @Test
-    public void testQuerySystemForCarMode_True() {
-        when(mContext.getSystemService(Context.UI_MODE_SERVICE)).thenReturn(mUiModeManager);
-        when(mUiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_CAR);
-        assertTrue(new SystemStateProvider(mContext).isCarMode());
-    }
-
-    @SmallTest
-    @Test
-    public void testQuerySystemForCarMode_False() {
-        when(mContext.getSystemService(Context.UI_MODE_SERVICE)).thenReturn(mUiModeManager);
-        when(mUiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_NORMAL);
-        assertFalse(new SystemStateProvider(mContext).isCarMode());
-    }
-
-    @SmallTest
-    @Test
-    public void testReceiverAndIntentFilter() {
-        ArgumentCaptor<IntentFilter> intentFilter = ArgumentCaptor.forClass(IntentFilter.class);
-        new SystemStateProvider(mContext);
-        verify(mContext).registerReceiver(any(BroadcastReceiver.class), intentFilter.capture());
-
-        assertEquals(2, intentFilter.getValue().countActions());
-        assertEquals(UiModeManager.ACTION_ENTER_CAR_MODE, intentFilter.getValue().getAction(0));
-        assertEquals(UiModeManager.ACTION_EXIT_CAR_MODE, intentFilter.getValue().getAction(1));
-    }
-
-    @SmallTest
-    @Test
-    public void testOnEnterExitCarMode() {
-        ArgumentCaptor<BroadcastReceiver> receiver =
-                ArgumentCaptor.forClass(BroadcastReceiver.class);
-        new SystemStateProvider(mContext).addListener(mSystemStateListener);
-
-        verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class));
-
-        when(mIntentEnter.getAction()).thenReturn(UiModeManager.ACTION_ENTER_CAR_MODE);
-        receiver.getValue().onReceive(mContext, mIntentEnter);
-        verify(mSystemStateListener).onCarModeChanged(true);
-
-        when(mIntentExit.getAction()).thenReturn(UiModeManager.ACTION_EXIT_CAR_MODE);
-        receiver.getValue().onReceive(mContext, mIntentExit);
-        verify(mSystemStateListener).onCarModeChanged(false);
-
-        receiver.getValue().onReceive(mContext, new Intent("invalid action"));
-    }
-}
diff --git a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
index cbca5e1..b779ce2 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
@@ -22,9 +22,12 @@
 import static android.Manifest.permission.READ_PHONE_STATE;
 import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
 
+import android.annotation.MainThread;
+import android.annotation.WorkerThread;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
@@ -87,6 +90,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -98,7 +102,7 @@
     public static class CallIntentProcessAdapterFake implements CallIntentProcessor.Adapter {
         @Override
         public void processOutgoingCallIntent(Context context, CallsManager callsManager,
-                Intent intent) {
+                Intent intent, String callingPackage) {
 
         }
 
@@ -121,6 +125,20 @@
         }
     }
 
+    public static class SettingsSecureAdapterFake implements
+        TelecomServiceImpl.SettingsSecureAdapter {
+        @Override
+        public void putStringForUser(ContentResolver resolver, String name, String value,
+            int userHandle) {
+
+        }
+
+        @Override
+        public String getStringForUser(ContentResolver resolver, String name, int userHandle) {
+            return THIRD_PARTY_CALL_SCREENING.flattenToString();
+        }
+    }
+
     private static class AnyStringIn implements ArgumentMatcher<String> {
         private Collection<String> mStrings;
         public AnyStringIn(Collection<String> strings) {
@@ -145,6 +163,8 @@
     @Mock private DefaultDialerCache mDefaultDialerCache;
     private TelecomServiceImpl.SubscriptionManagerAdapter mSubscriptionManagerAdapter =
             spy(new SubscriptionManagerAdapterFake());
+    private TelecomServiceImpl.SettingsSecureAdapter mSettingsSecureAdapter =
+        spy(new SettingsSecureAdapterFake());
     @Mock private UserCallIntentProcessor mUserCallIntentProcessor;
 
     private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };
@@ -160,6 +180,8 @@
             new ComponentName("test", "telComponentName"), "2", Binder.getCallingUserHandle());
     private static final PhoneAccountHandle SIP_PA_HANDLE_CURRENT = new PhoneAccountHandle(
             new ComponentName("test", "sipComponentName"), "3", Binder.getCallingUserHandle());
+    private static final ComponentName THIRD_PARTY_CALL_SCREENING = new ComponentName("com.android" +
+            ".thirdparty", "com.android.thirdparty.callscreeningserviceimpl");
 
     @Override
     @Before
@@ -185,6 +207,7 @@
                 },
                 mDefaultDialerCache,
                 mSubscriptionManagerAdapter,
+                mSettingsSecureAdapter,
                 mLock);
         mTSIBinder = telecomServiceImpl.getBinder();
         mComponentContextFixture.setTelecomManager(mTelecomManager);
@@ -250,7 +273,8 @@
                 makeMultiUserPhoneAccount(TEL_PA_HANDLE_16).build());
 
         PhoneAccountHandle returnedHandle
-                = mTSIBinder.getUserSelectedOutgoingPhoneAccount();
+                = mTSIBinder.getUserSelectedOutgoingPhoneAccount(
+                        TEL_PA_HANDLE_16.getComponentName().getPackageName());
         assertEquals(TEL_PA_HANDLE_16, returnedHandle);
     }
 
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index 4cf7644..1197396 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -69,6 +69,7 @@
 import com.android.server.telecom.AsyncRingtonePlayer;
 import com.android.server.telecom.BluetoothPhoneServiceImpl;
 import com.android.server.telecom.CallAudioManager;
+import com.android.server.telecom.CallAudioRouteStateMachine;
 import com.android.server.telecom.CallerInfoLookupHelper;
 import com.android.server.telecom.CallsManager;
 import com.android.server.telecom.CallsManagerListenerBase;
@@ -85,8 +86,12 @@
 import com.android.server.telecom.PhoneNumberUtilsAdapterImpl;
 import com.android.server.telecom.ProximitySensorManager;
 import com.android.server.telecom.ProximitySensorManagerFactory;
+import com.android.server.telecom.RoleManagerAdapter;
+import com.android.server.telecom.StatusBarNotifier;
 import com.android.server.telecom.TelecomSystem;
 import com.android.server.telecom.Timeouts;
+import com.android.server.telecom.WiredHeadsetManager;
+import com.android.server.telecom.bluetooth.BluetoothRouteManager;
 import com.android.server.telecom.components.UserCallIntentProcessor;
 import com.android.server.telecom.ui.IncomingCallNotifier;
 import com.android.server.telecom.ui.MissedCallNotifierImpl.MissedCallNotifierImplFactory;
@@ -98,7 +103,9 @@
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
+import java.io.File;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -208,6 +215,7 @@
     @Mock AsyncRingtonePlayer mAsyncRingtonePlayer;
     @Mock IncomingCallNotifier mIncomingCallNotifier;
     @Mock ClockProxy mClockProxy;
+    @Mock RoleManagerAdapter mRoleManagerAdapter;
 
     final ComponentName mInCallServiceComponentNameX =
             new ComponentName(
@@ -383,8 +391,8 @@
 
         IInCallAdapter inCallAdapter = mInCallServiceFixtureX.getInCallAdapter();
         inCallAdapter.conference(callId1.mCallId, callId2.mCallId);
-        // Wait for wacky non-deterministic behavior
-        Thread.sleep(200);
+        // Wait for the handler in ConnectionService
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
         ParcelableCall call1 = mInCallServiceFixtureX.getCall(callId1.mCallId);
         ParcelableCall call2 = mInCallServiceFixtureX.getCall(callId2.mCallId);
         // Check that the two calls end up with a parent in the end
@@ -402,6 +410,15 @@
     }
 
     private void setupTelecomSystem() throws Exception {
+        // Remove any cached PhoneAccount xml
+        File phoneAccountFile =
+                new File(mComponentContextFixture.getTestDouble()
+                        .getApplicationContext().getFilesDir(),
+                        PhoneAccountRegistrar.FILE_NAME);
+        if (phoneAccountFile.exists()) {
+            phoneAccountFile.delete();
+        }
+
         // Use actual implementations instead of mocking the interface out.
         HeadsetMediaButtonFactory headsetMediaButtonFactory =
                 spy(new HeadsetMediaButtonFactoryF());
@@ -420,48 +437,46 @@
         mClockProxy = mock(ClockProxy.class);
         when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CREATE_TIME);
         when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CREATE_ELAPSED_TIME);
+        when(mRoleManagerAdapter.getCallCompanionApps()).thenReturn(Collections.emptyList());
+        when(mRoleManagerAdapter.getDefaultCallScreeningApp()).thenReturn(null);
+        when(mRoleManagerAdapter.getCarModeDialerApp()).thenReturn(null);
         mTelecomSystem = new TelecomSystem(
                 mComponentContextFixture.getTestDouble(),
-                new MissedCallNotifierImplFactory() {
-                    @Override
-                    public MissedCallNotifier makeMissedCallNotifierImpl(Context context,
-                            PhoneAccountRegistrar phoneAccountRegistrar,
-                            DefaultDialerCache defaultDialerCache) {
-                        return mMissedCallNotifier;
-                    }
-                },
+                (context, phoneAccountRegistrar, defaultDialerCache) -> mMissedCallNotifier,
                 mCallerInfoAsyncQueryFactoryFixture.getTestDouble(),
                 headsetMediaButtonFactory,
                 proximitySensorManagerFactory,
                 inCallWakeLockControllerFactory,
-                new CallAudioManager.AudioServiceFactory() {
-                    @Override
-                    public IAudioService getAudioService() {
-                        return mAudioService;
-                    }
-                },
-                new BluetoothPhoneServiceImpl.BluetoothPhoneServiceImplFactory() {
-                    @Override
-                    public BluetoothPhoneServiceImpl makeBluetoothPhoneServiceImpl(Context context,
-                            TelecomSystem.SyncRoot lock, CallsManager callsManager,
-                            PhoneAccountRegistrar phoneAccountRegistrar) {
-                        return mBluetoothPhoneServiceImpl;
-                    }
-                },
-                new ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory() {
-                    @Override
-                    public ConnectionServiceFocusManager create(
-                            ConnectionServiceFocusManager.CallsManagerRequester requester,
-                            Looper looper) {
-                        return new ConnectionServiceFocusManager(requester, looper);
-                    }
-                },
+                () -> mAudioService,
+                (context, lock, callsManager, phoneAccountRegistrar) -> mBluetoothPhoneServiceImpl,
+                ConnectionServiceFocusManager::new,
                 mTimeoutsAdapter,
                 mAsyncRingtonePlayer,
                 mPhoneNumberUtilsAdapter,
                 mIncomingCallNotifier,
                 (streamType, volume) -> mock(ToneGenerator.class),
-                mClockProxy);
+                new CallAudioRouteStateMachine.Factory() {
+                    @Override
+                    public CallAudioRouteStateMachine create(
+                            Context context,
+                            CallsManager callsManager,
+                            BluetoothRouteManager bluetoothManager,
+                            WiredHeadsetManager wiredHeadsetManager,
+                            StatusBarNotifier statusBarNotifier,
+                            CallAudioManager.AudioServiceFactory audioServiceFactory,
+                            int earpieceControl) {
+                        return new CallAudioRouteStateMachine(context,
+                                callsManager,
+                                bluetoothManager,
+                                wiredHeadsetManager,
+                                statusBarNotifier,
+                                audioServiceFactory,
+                                // Force enable an earpiece for the end-to-end tests
+                                CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED);
+                    }
+                },
+                mClockProxy,
+                mRoleManagerAdapter);
 
         mComponentContextFixture.setTelecomManager(new TelecomManager(
                 mComponentContextFixture.getTestDouble(),
@@ -553,8 +568,11 @@
             ConnectionServiceFixture connectionServiceFixture)
             throws Exception {
 
-        return startOutgoingPhoneCallPendingCreateConnection(number, null,
-                connectionServiceFixture, Process.myUserHandle(), VideoProfile.STATE_AUDIO_ONLY);
+        startOutgoingPhoneCallWaitForBroadcaster(number, null,
+                connectionServiceFixture, Process.myUserHandle(), VideoProfile.STATE_AUDIO_ONLY,
+                false /*isEmergency*/);
+
+        return mInCallServiceFixtureX.mLatestCallId;
     }
 
     protected IdPair outgoingCallPhoneAccountSelected(PhoneAccountHandle phoneAccountHandle,
@@ -674,23 +692,22 @@
         Context localAppContext = mComponentContextFixture.getTestDouble().getApplicationContext();
         new UserCallIntentProcessor(localAppContext, userHandle).processIntent(
                 actionCallIntent, null, true /* hasCallAppOp*/, false /* isLocal */);
-        // UserCallIntentProcessor's mContext.sendBroadcastAsUser(...) will call to an empty method
-        // as to not actually try to send an intent to PrimaryCallReceiver. We verify that it was
-        // called correctly in order to continue.
-        verify(localAppContext).sendBroadcastAsUser(actionCallIntent, UserHandle.SYSTEM);
-        mTelecomSystem.getCallIntentProcessor().processIntent(actionCallIntent);
         // Wait for handler to start CallerInfo lookup.
         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
         // Send the CallerInfo lookup reply.
         mCallerInfoAsyncQueryFactoryFixture.mRequests.forEach(
                 CallerInfoAsyncQueryFactoryFixture.Request::reply);
+        if (phoneAccountHandle != null) {
+            mTelecomSystem.getCallsManager().getLatestPostSelectionProcessingFuture().join();
+        }
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
 
         boolean isSelfManaged = phoneAccountHandle == mPhoneAccountSelfManaged.getAccountHandle();
         if (!hasInCallAdapter && !isSelfManaged) {
-            verify(mInCallServiceFixtureX.getTestDouble())
+            verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
                     .setInCallAdapter(
                             any(IInCallAdapter.class));
-            verify(mInCallServiceFixtureY.getTestDouble())
+            verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT))
                     .setInCallAdapter(
                             any(IInCallAdapter.class));
         }
@@ -702,7 +719,13 @@
             int videoState) throws Exception {
         startOutgoingPhoneCallWaitForBroadcaster(number,phoneAccountHandle,
                 connectionServiceFixture, initiatingUser, videoState, false /*isEmergency*/);
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
 
+        verifyAndProcessOutgoingCallBroadcast(phoneAccountHandle);
+        return mInCallServiceFixtureX.mLatestCallId;
+    }
+
+    protected void verifyAndProcessOutgoingCallBroadcast(PhoneAccountHandle phoneAccountHandle) {
         ArgumentCaptor<Intent> newOutgoingCallIntent =
                 ArgumentCaptor.forClass(Intent.class);
         ArgumentCaptor<BroadcastReceiver> newOutgoingCallReceiver =
@@ -731,7 +754,6 @@
                     newOutgoingCallIntent.getValue());
         }
 
-        return mInCallServiceFixtureX.mLatestCallId;
     }
 
     // When Telecom is redialing due to an error, we need to make sure the number of connections
@@ -763,14 +785,16 @@
             ConnectionServiceFixture connectionServiceFixture) throws Exception {
 
         // Wait for the focus tracker.
-        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
+        waitForHandlerAction(mTelecomSystem.getCallsManager()
+                .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT);
 
         verify(connectionServiceFixture.getTestDouble())
                 .createConnection(eq(phoneAccountHandle), anyString(), any(ConnectionRequest.class),
                         eq(false)/*isIncoming*/, anyBoolean(), any());
         // Wait for handleCreateConnectionComplete
         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
-        assertEquals(startingNumConnections + 1, connectionServiceFixture.mConnectionById.size());
+        assertEquals(startingNumConnections + 1,
+                connectionServiceFixture.mConnectionById.size());
 
         // Wait for the callback in ConnectionService#onAdapterAttached to execute.
         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
@@ -847,14 +871,6 @@
         //Wait for/Verify call blocking happened asynchronously
         incomingCallAddedLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
 
-        IContentProvider blockedNumberProvider =
-                mSpyContext.getContentResolver().acquireProvider(BlockedNumberContract.AUTHORITY);
-        verify(blockedNumberProvider, timeout(TEST_TIMEOUT)).call(
-                anyString(),
-                eq(BlockedNumberContract.SystemContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER),
-                eq(number),
-                isNotNull(Bundle.class));
-
         // For the case of incoming calls, Telecom connecting the InCall services and adding the
         // Call is triggered by the async completion of the CallerInfoAsyncQuery. Once the Call
         // is added, future interactions as triggered by the ConnectionService, through the various
@@ -972,6 +988,9 @@
 
             mInCallServiceFixtureX.mInCallAdapter
                     .answerCall(ids.mCallId, videoState);
+            // Wait on the CS focus manager handler
+            waitForHandlerAction(mTelecomSystem.getCallsManager()
+                    .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT);
 
             if (!VideoProfile.isVideo(videoState)) {
                 verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
diff --git a/tests/src/com/android/server/telecom/tests/TelecomTestCase.java b/tests/src/com/android/server/telecom/tests/TelecomTestCase.java
index c356cb4..637895b 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomTestCase.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomTestCase.java
@@ -16,13 +16,14 @@
 
 package com.android.server.telecom.tests;
 
-import org.mockito.MockitoAnnotations;
-
 import android.content.Context;
 import android.os.Handler;
-import android.support.test.InstrumentationRegistry;
 import android.telecom.Log;
 
+import androidx.test.InstrumentationRegistry;
+
+import org.mockito.MockitoAnnotations;
+
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
diff --git a/tests/src/com/android/server/telecom/tests/VideoProviderProxyTest.java b/tests/src/com/android/server/telecom/tests/VideoProviderProxyTest.java
new file mode 100644
index 0000000..b09aa5b
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/VideoProviderProxyTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2018 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 org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.os.IBinder;
+import android.telecom.VideoProfile;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.internal.telecom.IVideoProvider;
+import com.android.server.telecom.Analytics;
+import com.android.server.telecom.Call;
+import com.android.server.telecom.CurrentUserProxy;
+import com.android.server.telecom.TelecomSystem;
+import com.android.server.telecom.VideoProviderProxy;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class VideoProviderProxyTest extends TelecomTestCase {
+
+    private TelecomSystem.SyncRoot mLock;
+    private VideoProviderProxy mVideoProviderProxy;
+    @Mock private IVideoProvider mVideoProvider;
+    @Mock private IBinder mIBinder;
+    @Mock private Call mCall;
+    @Mock private Analytics.CallInfo mCallInfo;
+    @Mock private CurrentUserProxy mCurrentUserProxy;
+    @Mock private VideoProviderProxy.Listener mListener;
+
+    @Override
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+        mLock = new TelecomSystem.SyncRoot() { };
+
+        when(mVideoProvider.asBinder()).thenReturn(mIBinder);
+        doNothing().when(mIBinder).linkToDeath(any(), anyInt());
+        when(mCall.getAnalytics()).thenReturn(mCallInfo);
+        doNothing().when(mCallInfo).addVideoEvent(anyInt(), anyInt());
+        doNothing().when(mCall).maybeEnableSpeakerForVideoUpgrade(anyInt());
+        mVideoProviderProxy = new VideoProviderProxy(mLock, mVideoProvider, mCall,
+                mCurrentUserProxy);
+        mVideoProviderProxy.addListener(mListener);
+    }
+
+    /**
+     * Tests the case where we receive a request to upgrade to video, except:
+     * 1. Phone account says we support video.
+     * 2. Call says we don't support video.
+     *
+     * Ensures that we send back a response immediately to indicate the call should remain as
+     * audio-only.
+     * @throws Exception
+     */
+    @SmallTest
+    @Test
+    public void testReceiveUpgradeRequestWhenLocalDoesntSupportVideo() throws Exception {
+        // Given a call which supports video at the phone account level, but is not currently
+        // marked as supporting video locally.
+        when(mCall.isLocallyVideoCapable()).thenReturn(false);
+        when(mCall.isVideoCallingSupportedByPhoneAccount()).thenReturn(true);
+
+        // Simulate receiving a request to upgrade to video.
+        mVideoProviderProxy.getVideoCallListenerBinder().receiveSessionModifyRequest(
+                new VideoProfile(VideoProfile.STATE_BIDIRECTIONAL));
+
+        // Make sure that we send back a response rejecting the request.
+        ArgumentCaptor<VideoProfile> capturedProfile = ArgumentCaptor.forClass(VideoProfile.class);
+        verify(mVideoProvider).sendSessionModifyResponse(capturedProfile.capture());
+        assertEquals(VideoProfile.STATE_AUDIO_ONLY, capturedProfile.getValue().getVideoState());
+    }
+
+    /**
+     * Tests the case where we receive a request to upgrade to video and video is supported.
+     * @throws Exception
+     */
+    @SmallTest
+    @Test
+    public void testReceiveUpgradeRequestWhenVideoIsSupported() throws Exception {
+        // Given a call which supports video at the phone account level, and is currently marked as
+        // supporting video locally.
+        when(mCall.isLocallyVideoCapable()).thenReturn(true);
+        when(mCall.isVideoCallingSupportedByPhoneAccount()).thenReturn(true);
+
+        // Simulate receiving a request to upgrade to video.
+        mVideoProviderProxy.getVideoCallListenerBinder().receiveSessionModifyRequest(
+                new VideoProfile(VideoProfile.STATE_BIDIRECTIONAL));
+
+        // Ensure it gets proxied back to the caller.
+
+        ArgumentCaptor<VideoProfile> capturedProfile = ArgumentCaptor.forClass(VideoProfile.class);
+        verify(mListener).onSessionModifyRequestReceived(any(), capturedProfile.capture());
+        assertEquals(VideoProfile.STATE_BIDIRECTIONAL, capturedProfile.getValue().getVideoState());
+    }
+
+    /**
+     * Tests the case where dialer requests an upgrade to video; we should try to change to speaker.
+     * @throws Exception
+     */
+    @SmallTest
+    @Test
+    public void testTryToEnableSpeakerOnVideoUpgrade() throws Exception {
+        mVideoProviderProxy.onSendSessionModifyRequest(
+                new VideoProfile(VideoProfile.STATE_AUDIO_ONLY),
+                new VideoProfile(VideoProfile.STATE_BIDIRECTIONAL));
+        verify(mCall).maybeEnableSpeakerForVideoUpgrade(eq(VideoProfile.STATE_BIDIRECTIONAL));
+    }
+}
diff --git a/tests/src/com/android/server/telecom/tests/VideoProviderTest.java b/tests/src/com/android/server/telecom/tests/VideoProviderTest.java
index 75dc36f..eacecf9 100644
--- a/tests/src/com/android/server/telecom/tests/VideoProviderTest.java
+++ b/tests/src/com/android/server/telecom/tests/VideoProviderTest.java
@@ -34,6 +34,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.UserHandle;
+import android.telecom.Connection;
 import android.telecom.Connection.VideoProvider;
 import android.telecom.InCallService;
 import android.telecom.InCallService.VideoCall;
@@ -96,7 +97,8 @@
         super.setUp();
         mContext = mComponentContextFixture.getTestDouble().getApplicationContext();
         mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
-
+        mConnectionServiceFixtureA.mConnectionServiceDelegate.mCapabilities
+                |= Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL;
         mCallIds = startAndMakeActiveOutgoingCall(
                 "650-555-1212",
                 mPhoneAccountA0.getAccountHandle(),