DO NOT MERGE - Restrict ability to add call based on device provision status am: 0044d82fde
am: b4b8bf90dc  -s ours

* commit 'b4b8bf90dc7cf5a1ea3330dae71463379e7bdce5':
  DO NOT MERGE - Restrict ability to add call based on device provision status
diff --git a/Android.mk b/Android.mk
index 395aacc..0917793 100644
--- a/Android.mk
+++ b/Android.mk
@@ -4,8 +4,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_JAVA_LIBRARIES := telephony-common
-LOCAL_STATIC_JAVA_LIBRARIES := \
-        guava \
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 427b248..a2c0b91 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -18,7 +18,7 @@
         xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
         package="com.android.server.telecom"
         coreApp="true"
-        android:sharedUserId="android.uid.phone">
+        android:sharedUserId="android.uid.system">
 
     <!-- Prevents the activity manager from delaying any activity-start
          requests by this package, including requests immediately after
@@ -27,6 +27,7 @@
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
     <uses-permission android:name="android.permission.CALL_PRIVILEGED" />
     <uses-permission android:name="android.permission.MANAGE_USERS" />
+    <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.MODIFY_AUDIO_SETTINGS" />
     <uses-permission android:name="android.permission.READ_CALL_LOG" />
@@ -38,18 +39,6 @@
     <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
     <uses-permission android:name="android.permission.BROADCAST_CALLLOG_INFO" />
 
-    <!-- Protects the ability to register any PhoneAccount with a capability flags of either
-         PhoneAccount#CAPABILITY_CALL_PROVIDER or PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION. -->
-    <permission
-            android:name="com.android.server.telecom.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION"
-            android:label="Register CALL_PROVIDER or SIM_SUBSCRIPTION PhoneAccount"
-            android:protectionLevel="signature"/>
-
-    <permission
-            android:name="com.android.server.telecom.permission.REGISTER_CONNECTION_MANAGER"
-            android:label="Register CONNECTION_MANAGER PhoneAccount"
-            android:protectionLevel="signature"/>
-
     <permission
             android:name="android.permission.BROADCAST_CALLLOG_INFO"
             android:label="Broadcast the call type/duration information"
@@ -64,12 +53,11 @@
          can check for incompatible APIs. -->
     <uses-sdk android:minSdkVersion="19" />
 
-    <application android:name="TelecomApp"
-            android:persistent="true"
-            android:label="@string/telecommAppLabel"
+    <application android:label="@string/telecommAppLabel"
             android:icon="@mipmap/ic_launcher_phone"
             android:allowBackup="false"
-            android:supportsRtl="true">
+            android:supportsRtl="true"
+            android:process="system">
 
         <!-- CALL vs CALL_PRIVILEGED vs CALL_EMERGENCY
              We have three different intents through which a call can be initiated each with its
@@ -90,7 +78,8 @@
         <activity android:name="CallActivity"
                 android:theme="@style/Theme.Telecomm.Transparent"
                 android:permission="android.permission.CALL_PHONE"
-                android:excludeFromRecents="true">
+                android:excludeFromRecents="true"
+                android:process=":ui">
             <!-- CALL action intent filters for the various ways of initiating an outgoing call. -->
             <intent-filter>
                 <action android:name="android.intent.action.CALL" />
@@ -126,7 +115,8 @@
              the system from processing this intent (b/8871505). -->
         <activity-alias android:name="PrivilegedCallActivity"
                 android:targetActivity="CallActivity"
-                android:permission="android.permission.CALL_PRIVILEGED">
+                android:permission="android.permission.CALL_PRIVILEGED"
+                android:process=":ui">
             <intent-filter android:priority="1000">
                 <action android:name="android.intent.action.CALL_PRIVILEGED" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -160,7 +150,8 @@
              that scheme be removed from this activity? -->
         <activity-alias android:name="EmergencyCallActivity"
                 android:targetActivity="CallActivity"
-                android:permission="android.permission.CALL_PRIVILEGED">
+                android:permission="android.permission.CALL_PRIVILEGED"
+                android:process=":ui">
             <intent-filter android:priority="1000">
                 <action android:name="android.intent.action.CALL_EMERGENCY" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -185,16 +176,8 @@
             </intent-filter>
         </activity-alias>
 
-        <activity-alias android:name="IncomingCallActivity"
-                android:targetActivity="CallActivity"
-                android:exported="true">
-            <intent-filter>
-                <action android:name="android.telecom.action.INCOMING_CALL" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity-alias>
-
-        <receiver android:name="TelecomBroadcastReceiver" android:exported="false">
+        <receiver android:name="TelecomBroadcastReceiver" android:exported="false"
+                android:process="system">
             <intent-filter>
                 <action android:name="com.android.server.telecom.ACTION_CALL_BACK_FROM_NOTIFICATION" />
                 <action android:name="com.android.server.telecom.ACTION_CALL_BACK_FROM_NOTIFICATION" />
@@ -202,7 +185,8 @@
             </intent-filter>
         </receiver>
 
-        <receiver android:name="PhoneAccountBroadcastReceiver">
+        <receiver android:name="PhoneAccountBroadcastReceiver"
+                android:process="system">
             <intent-filter>
                 <action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
                 <data android:scheme="package" />
@@ -211,7 +195,9 @@
 
         <activity android:name=".RespondViaSmsSettings$Settings"
                   android:label="@string/respond_via_sms_setting_title"
-                  android:configChanges="orientation|screenSize|keyboardHidden">
+                  android:configChanges="orientation|screenSize|keyboardHidden"
+                  android:theme="@style/Theme.Telecom.DialerSettings"
+                  android:process=":ui">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
             </intent-filter>
@@ -221,19 +207,31 @@
                 android:configChanges="orientation|screenSize|keyboardHidden"
                 android:excludeFromRecents="true"
                 android:launchMode="singleInstance"
-                android:theme="@style/Theme.Telecomm.Transparent">
+                android:theme="@style/Theme.Telecomm.Transparent"
+                android:process=":ui">
         </activity>
 
         <receiver android:name=".CallReceiver"
-            android:exported="false">
+                android:exported="true"
+                android:permission="android.permission.MODIFY_PHONE_STATE"
+                android:process="system">
         </receiver>
 
         <service android:name="BluetoothPhoneService"
-                android:singleUser="true">
+                android:singleUser="true"
+                android:process="system">
             <intent-filter>
                 <action android:name="android.bluetooth.IBluetoothHeadsetPhone" />
             </intent-filter>
         </service>
 
+        <service android:name=".TelecomService"
+                android:singleUser="true"
+                android:process="system">
+            <intent-filter>
+                <android android:name="android.telecom.ITelecomService" />
+            </intent-filter>
+        </service>
+
     </application>
 </manifest>
diff --git a/res/drawable-hdpi/ic_arrow_back_white_24dp.png b/res/drawable-hdpi/ic_arrow_back_white_24dp.png
new file mode 100644
index 0000000..5fa4948
--- /dev/null
+++ b/res/drawable-hdpi/ic_arrow_back_white_24dp.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_more_vert_white_24dp.png b/res/drawable-hdpi/ic_more_vert_white_24dp.png
new file mode 100644
index 0000000..675f3ee
--- /dev/null
+++ b/res/drawable-hdpi/ic_more_vert_white_24dp.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_arrow_back_white_24dp.png b/res/drawable-mdpi/ic_arrow_back_white_24dp.png
new file mode 100644
index 0000000..9e662f6
--- /dev/null
+++ b/res/drawable-mdpi/ic_arrow_back_white_24dp.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_more_vert_white_24dp.png b/res/drawable-mdpi/ic_more_vert_white_24dp.png
new file mode 100644
index 0000000..1d8ad18
--- /dev/null
+++ b/res/drawable-mdpi/ic_more_vert_white_24dp.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_arrow_back_white_24dp.png b/res/drawable-xhdpi/ic_arrow_back_white_24dp.png
new file mode 100644
index 0000000..addbfc8
--- /dev/null
+++ b/res/drawable-xhdpi/ic_arrow_back_white_24dp.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_more_vert_white_24dp.png b/res/drawable-xhdpi/ic_more_vert_white_24dp.png
new file mode 100644
index 0000000..1b04eda
--- /dev/null
+++ b/res/drawable-xhdpi/ic_more_vert_white_24dp.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_arrow_back_white_24dp.png b/res/drawable-xxhdpi/ic_arrow_back_white_24dp.png
new file mode 100644
index 0000000..4057cc5
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_arrow_back_white_24dp.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_more_vert_white_24dp.png b/res/drawable-xxhdpi/ic_more_vert_white_24dp.png
new file mode 100644
index 0000000..2955c02
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_more_vert_white_24dp.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_arrow_back_white_24dp.png b/res/drawable-xxxhdpi/ic_arrow_back_white_24dp.png
new file mode 100644
index 0000000..02f2f6f
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_arrow_back_white_24dp.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_more_vert_white_24dp.png b/res/drawable-xxxhdpi/ic_more_vert_white_24dp.png
new file mode 100644
index 0000000..25b6f9f
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_more_vert_white_24dp.png
Binary files differ
diff --git a/res/drawable/ic_back_arrow.xml b/res/drawable/ic_back_arrow.xml
new file mode 100644
index 0000000..cbb4c11
--- /dev/null
+++ b/res/drawable/ic_back_arrow.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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
+  -->
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+        android:src="@drawable/ic_arrow_back_white_24dp"
+        android:autoMirrored="true" />
diff --git a/res/menu/respond_via_message_settings_menu.xml b/res/menu/respond_via_message_settings_menu.xml
deleted file mode 100644
index 6f5e246..0000000
--- a/res/menu/respond_via_message_settings_menu.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 Google Inc.
-
-     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.
--->
-
-<!-- Menu for Respond-via-Message settings screen. -->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/respond_via_message_reset"
-          android:title="@string/respond_via_sms_menu_reset_default_activity" />
-</menu>
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 7decddd..aa793a1 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Redigeer vinnige antwoorde"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Vinnige antwoord"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Stel verstek program terug"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Boodskap gestuur na <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Hierdie gebruiker word nie toegelaat om nienood-foonoproepe te maak nie"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Oproep nie gestuur nie; geen geldige nommer is ingevoer nie."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Net noodoproepe word deur die toesteleienaar toegelaat"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Voer \'n geldige nommer in om \'n oproep te maak."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Oproep kan nie op die oomblik bygevoeg word nie."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Vermiste stemboodskapnommer"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Geen stemboodskapnommer is op die SIM-kaart gestoor nie."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Voeg nommer by"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index d44f01b..fec8369 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"ነባሪውን መተግበሪያ ዳግም አስጀምር"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"ለ <xliff:g id="PHONE_NUMBER">%s</xliff:g> የተላከ መልዕክት"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"ይህ ተጠቃሚ የአስቸኳይ አደጋ ያልሆኑ ስልክ ጥሪዎችን እንዲያደርጉ አልተፈቀደላቸውም"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"ጥሪ አልተላከም፣ ትክክለኛ ቁጥር አልገባም።"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"የአስቸኳይ አደጋ ጥሪዎች ብቻ ናቸው በባለቤቱ የተፈቀዱት"</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>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index a30f1e6..14fc640 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"إعادة تعيين التطبيق الافتراضي"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"تم إرسال الرسالة إلى <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"هذا المستخدم غير مسموح له بإجراء مكالمات هاتفية بخلاف مكالمات الطوارئ"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"لم يتم إرسال الاتصال، لم يتم إدخال رقم صالح."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"مسموح لمالك الجهاز بمكالمات الطوارئ فقط"</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>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index d3c0d96..d706029 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"Възст. на станд. настройки"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"До <xliff:g id="PHONE_NUMBER">%s</xliff:g> бе изпратено съобщение."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"На този потребител е разрешено да провежда само спешни обаждания"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Обаждането не е изпратено, не е въведен валиден номер."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Собственикът на устройството разрешава само спешни обаждания"</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>
diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml
index 9fc3317..4379a37 100644
--- a/res/values-bn-rBD/strings.xml
+++ b/res/values-bn-rBD/strings.xml
@@ -34,12 +34,11 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"ডিফল্ট অ্যাপ্লিকেশন পুনরায় সেট করুন"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> এ বার্তা পাঠানো হয়েছে৷"</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"ফোন অ্যাকাউন্ট সেটিংস"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"আউটগোয়িং ডিফল্ট অ্যাকাউন্ট"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"Wi-Fi এর মাধ্যমে কল করার অ্যাকাউন্ট"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"প্রতিবার জিজ্ঞাসা করুন"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"Wi-Fi কলিং ব্যবহার করবেন না"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"জরুরী নয় এমন ফোন কল করার জন্য ব্যবহারকারী অনুমতি পাননি"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"ডিভাইসের মালিক শুধুমাত্র জরুরি কলগুলিতে অনুমতি দিয়েছেন"</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>
 </resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index e7011f5..c2a01f5 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -34,10 +34,10 @@
     <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>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Resposta ràpida"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Restableix aplic. predetermin."</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Missatge enviat a <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Aquest usuari no pot fer trucades que no siguin d\'emergència."</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"No s\'ha enviat la trucada perquè no s\'ha introduït cap número vàlid."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"El propietari del dispositiu només permet les trucades d\'emergència."</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Per realitzar una trucada, introdueix un número vàlid."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"En aquest moment no es pot afegir la trucada."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Falta el número de correu de veu"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"No hi ha cap número de correu de veu emmagatzemat a la targeta SIM."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Afegeix número"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index db612a4..ff24203 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Upravit rychlé odpovědi"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Rychlá odpověď"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Resetovat výchozí aplikaci"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Zpráva byla odeslána na číslo <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Uživatel smí uskutečňovat pouze tísňová volání."</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Hovor nelze spojit, nebylo zadáno platné číslo."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Vlastník zařízení povolil pouze tísňová volání."</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Chcete-li uskutečnit hovor, zadejte platné telefonní číslo."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Hovor aktuálně nelze přidat."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Chybí číslo hlasové schránky"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Na SIM kartě není uloženo žádné číslo hlasové schránky."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Přidat číslo"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index e7ba06f..93e4b83 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"Nulstil standardapp"</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="outgoing_call_not_allowed" msgid="1434784869685645427">"Denne bruger har kun tilladelse til at foretage nødopkald"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Opkaldet kunne ikke sendes. Der blev ikke indtastet et gyldigt nummer."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Enhedens ejer tillader kun nødopkald."</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>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Tilføj nummer"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 9a5ee71..7e99980 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Kurzantworten bearbeiten"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Kurzantwort"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Standard-App zurücksetzen"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Nachricht an <xliff:g id="PHONE_NUMBER">%s</xliff:g> gesendet"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Dieser Nutzer darf abgesehen von Notrufen keine Anrufe tätigen."</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Anruf nicht verbunden; keine gültige Nummer eingegeben."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Der Geräteinhaber hat nur Notrufe zugelassen."</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Geben Sie eine gültige Nummer ein."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Der Anruf kann momentan nicht hinzugefügt werden."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Fehlende Mailbox-Nummer"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Auf der SIM-Karte ist keine Mailbox-Nummer gespeichert."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Nummer hinzufügen"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 7bea2ac..1805be5 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"Επαναφορά προεπιλ. εφαρμογής"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Το μήνυμα εστάλη στο <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Δεν επιτρέπεται σε αυτόν το χρήστη να πραγματοποιεί τηλεφωνικές κλήσεις οι οποίες δεν είναι εκτάκτου ανάγκης"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Η κλήση δεν πραγματοποιήθηκε, δεν έγινε εισαγωγή έγκυρου αριθμού."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Από τον κάτοχο της συσκευής επιτρέπονται μόνο κλήσεις έκτακτης ανάγκης"</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>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 97cc163..ae6fbb4 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"Reset default app"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Message sent to <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"This user is not allowed to make non-emergency phone calls"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Call not sent. No valid number entered."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Only emergency calls are allowed by the device owner"</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>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 97cc163..ae6fbb4 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"Reset default app"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Message sent to <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"This user is not allowed to make non-emergency phone calls"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Call not sent. No valid number entered."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Only emergency calls are allowed by the device owner"</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>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 85ee3fd..4ca4e93 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Editar respuestas rápidas"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Respuesta rápida"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Restablecer aplic. predeterm."</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mensaje enviado a <xliff:g id="PHONE_NUMBER">%s</xliff:g>"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Este usuario solo tiene permisos para hacer llamadas de emergencia."</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Llamada no enviada. No se ingresó un número válido."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"El propietario del dispositivo solo permite las llamadas de emergencia."</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Para realizar una llamada, ingresa un número válido."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"No se puede agregar la llamada en este momento."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Falta el número de correo de voz"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"No hay un número de correo de voz almacenado en la tarjeta SIM."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Agregar número"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 83743fb..7fc0f9c 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Editar respuestas rápidas"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Respuestas rápidas"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Restablecer aplicación"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mensaje enviado a <xliff:g id="PHONE_NUMBER">%s</xliff:g>"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Este usuario solo puede realizar llamadas de emergencia"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"No se ha enviado la llamada; el número introducido no es válido."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"El propietario del dispositivo solo permite llamadas de emergencia"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Para realizar una llamada, introduce un número válido."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"No se puede añadir la llamada en este momento."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Falta el número del buzón de voz."</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"No se ha almacenado ningún número de buzón de voz en la tarjeta SIM."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Añadir número"</string>
diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml
index 3ce3075..b101f26 100644
--- a/res/values-et-rEE/strings.xml
+++ b/res/values-et-rEE/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Kiirvastuste muutmine"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Kiirvastus"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Lähtesta vaikerakendus"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Sõnum on saadetud numbrile <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"See kasutaja võib teha ainult hädaabikõnesid"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Kõnet ei tehtud, sisestati kehtetu number."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Seadme omanik lubab ainult hädaabikõnesid"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Helistamiseks sisestage kehtiv number."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Kõnet ei saa praegu lisada."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Puudub kõnepostinumber"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"SIM-kaardile pole salvestatud ühtegi kõnepostinumbrit."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Lisa number"</string>
diff --git a/res/values-eu-rES/strings.xml b/res/values-eu-rES/strings.xml
index b194e6e..8450649 100644
--- a/res/values-eu-rES/strings.xml
+++ b/res/values-eu-rES/strings.xml
@@ -34,12 +34,11 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Editatu erantzun bizkorrak"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Erantzun bizkorra"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Berrezarri aplik. lehenetsia"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mezua bidali da <xliff:g id="PHONE_NUMBER">%s</xliff:g> zenbakira."</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"Telefonoaren kontuaren ezarpenak"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"Irteerako kontu lehenetsia"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"Wi-Fi bidezko deiak egiteko kontua"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"Galdetu beti"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"Ez erabili Wi-Fi bidezko deiak"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Erabiltzaile honek ez du larrialdietakoak ez diren telefono-deiak egiteko baimenik"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Gailuaren jabeak larrialdi-deiak bakarrik egitea onartzen du"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Deitzeko, idatzi balio duen zenbaki bat."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Une honetan ezin da deirik gehitu."</string>
+    <string name="no_vm_number" msgid="4164780423805688336">"Erantzungailuaren zenbakia falta da"</string>
+    <string name="no_vm_number_msg" msgid="1300729501030053828">"Ez da erantzungailuaren zenbakirik gorde SIM txartelean."</string>
+    <string name="add_vm_number_str" msgid="4676479471644687453">"Gehitu zenbakia"</string>
 </resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index a54b374..a0ba00b 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"بازنشانی برنامه‌ پیش‌فرض"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"پیام به <xliff:g id="PHONE_NUMBER">%s</xliff:g> ارسال شد."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"این کاربر اجازه برقراری تماس‌های تلفنی غیر اضطراری ندارد."</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"تماس ارسال نشد، هیچ شماره معتبری وارد نشده است."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"مالک دستگاه فقط تماس‌های اضطراری را مجاز کرده است"</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>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index eab9a8b..93f268e 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Muokkaa pikavastausta"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Pikavastaukset"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Palauta oletussovellus"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Viesti lähetetty numeroon <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Tämä käyttäjä saa soittaa vain hätäpuheluita"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Puhelua ei soitettu, et antanut kelvollista numeroa."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Laitteen omistaja on sallinut vain hätäpuhelut"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Soita antamalla kelvollinen numero."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Puhelua ei voi lisätä juuri nyt."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Puhelinvastaajan numero puuttuu"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"SIM-kortille ei ole tallennettu puhelinvastaajan numeroa."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Lisää numero"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 63bd398..0d0ab25 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Modif. rép. rapides"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Réponse rapide"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Rétablir application par défaut"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Message envoyé à <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Cet utilisateur n\'est pas autorisé à faire des appels téléphoniques non urgents"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"L\'appel n\'a pas été effectué, car le numéro entré n\'est pas valide."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Seuls les appels d\'urgence sont autorisés par le propriétaire de l\'appareil"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Pour faire un appel, entrez un numéro valide."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Impossible d\'ajouter l\'appel pour le moment."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Numéro de messagerie vocale manquant"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Aucun numéro de messagerie vocale n\'est enregistré sur la carte SIM."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Ajouter un numéro"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 2fb06f6..7983939 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -34,10 +34,10 @@
     <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>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Réponse rapide"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Rétablir application par défaut"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Message envoyé à <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Cet utilisateur n\'est autorisé à effectuer que des appels d\'urgence."</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"L\'appel n\'a pas été effectué. Aucun numéro valide n\'a été saisi."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Le propriétaire de l\'appareil n\'autorise que les appels d\'urgence."</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Pour émettre un appel, veuillez saisir un numéro valide."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Impossible d\'ajouter un appel pour le moment."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Numéro de messagerie vocale manquant"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Aucun numéro de messagerie vocale n\'est enregistré sur la carte SIM."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Ajouter un numéro"</string>
diff --git a/res/values-gl-rES/strings.xml b/res/values-gl-rES/strings.xml
index f75da28..0dba5fc 100644
--- a/res/values-gl-rES/strings.xml
+++ b/res/values-gl-rES/strings.xml
@@ -34,12 +34,11 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Editar respostas rápidas"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Resposta rápida"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Restablecer aplicación predet."</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mensaxe enviada ao <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"Configuración da conta do teléfono"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"Conta saínte predeterminada"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"Conta de chamadas wifi"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"Preguntar sempre"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"Non utilizar as chamadas wifi"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Este usuario non ten permiso para facer chamadas telefónicas que non sexan de emerxencia"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"O propietario do dispositivo só permite as chamadas de emerxencia"</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>
+    <string name="no_vm_number" msgid="4164780423805688336">"Falta o número de correo de voz"</string>
+    <string name="no_vm_number_msg" msgid="1300729501030053828">"Non hai ningún número de correo de voz almacenado na tarxeta SIM."</string>
+    <string name="add_vm_number_str" msgid="4676479471644687453">"Engadir número"</string>
 </resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index debd49b..802c206 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -30,15 +30,15 @@
     <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_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_menu_reset_default_activity" msgid="1461742052902053466">"डिफ़ॉल्ट ऐप्स  रीसेट करें"</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="outgoing_call_not_allowed" msgid="1434784869685645427">"इस उपयोगकर्ता को गैर-आपातकालीन फ़ोन कॉल करने की अनुमति नहीं है"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"कॉल नहीं भेजा गया, कोई मान्य नंबर नहीं डाला गया था."</string>
-    <string name="no_vm_number" msgid="4164780423805688336">"गुम ध्वनिमेल नंबर"</string>
-    <string name="no_vm_number_msg" msgid="1300729501030053828">"सिम कार्ड पर कोई ध्वनिमेल नंबर संग्रहीत नहीं है."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"डिवाइस स्‍वामी द्वारा केवल आपातकालीन कॉल करने की अनुमति है"</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>
 </resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index f86f4a9..af4b0c0 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Uređivanje brzih odgovora"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Brzi odgovor"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Poništavanje zadane aplikacije"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Poruka poslana na broj <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Ovaj korisnik smije uspostavljati samo hitne pozive"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Poziv nije uspostavljen, nije unesen važeći broj."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Vlasnik uređaja dopušta samo hitne pozive"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Unesite važeći broj da biste uspostavili poziv."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Poziv trenutačno nije moguć."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Nedostaje broj govorne pošte"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Na SIM kartici nije spremljen broj govorne pošte."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Dodaj broj"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index cc7c77a..eb6e388 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Gyors válaszok szerkesztése"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Gyors válasz"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Alapalkalmazás visszaállítása"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Üzenet elküldve ide: <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Ez a felhasználó csak vészhelyzeti telefonhívásokat kezdeményezhet"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"A hívás indítása érvénytelen szám beírása miatt nem történt meg."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Az eszköz tulajdonosa csak a segélyhívásokat engedélyezte"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Hívásindításhoz adjon meg egy érvényes számot."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Jelenleg nem lehet videohívást hozzáadni."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Hiányzik a hangposta száma"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Nincs hangpostaszám a SIM kártyán."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Szám hozzáadása"</string>
diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml
index 8f47792..3879e04 100644
--- a/res/values-hy-rAM/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"Վերականգնել լռելյայն հավելվածը"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Հաղորդագրությունն ուղարկվել է <xliff:g id="PHONE_NUMBER">%s</xliff:g>-ին:"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Այս օգտվողին չի թույլատրվում կատարել ոչ արտակարգ զանգեր"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Զանգը չի կատարվել, անվավեր համար է մուտքագրված:"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Սարքի սեփականատերը թույլատրում է միայն արտակարգ իրավիճակի զանգերը"</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>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 755eb9d..fac45f3 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Edit tanggapan cepat"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Tanggapan cepat"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Setel ulang aplikasi default"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Pesan dikirim ke <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Pengguna ini tidak diizinkan untuk membuat panggilan telepon non-darurat"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Panggilan tidak terkirim, tidak ada nomor valid yang dimasukkan."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Hanya panggilan darurat yang diizinkan oleh pemilik perangkat"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Untuk melakukan panggilan telepon, masukkan nomor yang valid."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Panggilan tidak dapat ditambahkan untuk saat ini."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Nomor kotak pesan hilang"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Tidak ada nomor kotak pesan tersimpan pada kartu SIM."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Tambahkan nomor"</string>
diff --git a/res/values-is-rIS/strings.xml b/res/values-is-rIS/strings.xml
index 8c37bd3..1862dac 100644
--- a/res/values-is-rIS/strings.xml
+++ b/res/values-is-rIS/strings.xml
@@ -34,12 +34,11 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Breyta snarsvörum"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Snarsvar"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Endurstilla sjálfgefið forrit"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Skilaboð send til <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"Reikningsstillingar síma"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"Sjálfgefinn sendingarreikningur"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"Reikningur Wi-Fi símtala"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"Spyrja í hvert skipti"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"Ekki nota Wi-Fi símtöl"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Þessi notandi hefur ekki leyfi til að hringja símtöl önnur en neyðarsímtöl"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Eigandi tækisins leyfir aðeins neyðarsímtöl"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Sláðu inn gilt númer til að hringja símtal."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Ekki er hægt að bæta símtali við sem stendur."</string>
+    <string name="no_vm_number" msgid="4164780423805688336">"Talhólfsnúmer vantar"</string>
+    <string name="no_vm_number_msg" msgid="1300729501030053828">"Ekkert talhólfsnúmer er vistað á SIM-kortinu."</string>
+    <string name="add_vm_number_str" msgid="4676479471644687453">"Bæta númeri við"</string>
 </resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index ead17ae..584bbad 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Modifica risposte rapide"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Risposta rapida"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Reimposta app predefinita"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Messaggio inviato a <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Questo utente non è autorizzato a fare telefonate diverse da quelle di emergenza"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Chiamata non inviata. Nessun numero valido inserito."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Il proprietario del dispositivo consente soltanto chiamate di emergenza"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Per effettuare una chiamata, inserisci un numero valido."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Al momento non è possibile aggiungere la chiamata."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Numero segreteria mancante"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Nessun numero di segreteria presente nella SIM."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Aggiungi numero"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 3e3c509..64e44bf 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"אפס את האפליקציה המוגדר כברירת מחדל"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"הודעה נשלחה אל <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"משתמש זה אינו רשאי לבצע שיחות טלפון שאינן שיחות חירום"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"השיחה לא נשלחה. לא הוזן מספר חוקי."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"בעלי המכשיר מתיר לבצע שיחות חירום בלבד"</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>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 1caaccd..10b9087 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"デフォルトのアプリをリセット"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g>にメッセージを送信しました。"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"このユーザーは緊急通報以外の通話は発信できません"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"発信できません。有効な番号が入力されていません。"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"端末の所有者に許可されているのは緊急通報のみです。"</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>
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml
index 6e7eedf..4cb2256 100644
--- a/res/values-ka-rGE/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"ნაგულისხმევი აპის ისევ დაყენება"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"შეტყობინება გაიგზავნა <xliff:g id="PHONE_NUMBER">%s</xliff:g>-თან."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"ამ მომხმარებელს არ აქვს უფლება, განახორციელოს არასაგანგებო სატელეფონო ზარები."</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"ვერ გაიგზავნა, ტელეფონის ნომერი სწორად არ იქნა შეყვანილი."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"მოწყობილობის მფლობელის მიერ ნებადართულია მხოლოდ საგანგებო ზარების განხორციელება"</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>
diff --git a/res/values-kk-rKZ/strings.xml b/res/values-kk-rKZ/strings.xml
index 921c40c..064d563 100644
--- a/res/values-kk-rKZ/strings.xml
+++ b/res/values-kk-rKZ/strings.xml
@@ -34,12 +34,11 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"Бастапқы қолдб-ға қайта реттеу"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Хабар <xliff:g id="PHONE_NUMBER">%s</xliff:g> нөміріне жіберілді."</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"Телефон есептік жазбасының параметрлері"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"Әдепкі шығыс есептік жазба"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"Wi-Fi қоңыраулар есептік жазбасы"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"Әр қоңырау үшін сұрау"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"Wi-Fi қоңырауларын пайдаланбау"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Бұл пайдаланушыға жедел емес қоңырауларды шалуға рұқсат етілмеген"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Құрылғы иесі тек жедел қоңырауларға рұқсат еткен"</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>
 </resources>
diff --git a/res/values-km-rKH/strings.xml b/res/values-km-rKH/strings.xml
index e392e2d..b5fb8eb 100644
--- a/res/values-km-rKH/strings.xml
+++ b/res/values-km-rKH/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"កំណត់​កម្មវិធី​លំនាំដើម​ឡើងវិញ"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"បាន​ផ្ញើ​សារ​ទៅ <xliff:g id="PHONE_NUMBER">%s</xliff:g> ។"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"អ្នក​ប្រើ​ម្នាក់​នេះ​មិន​ត្រូវ​បាន​អនុញ្ញាត​ឲ្យ​បង្កើត​កា​រ​ហៅ​ទូរស័ព្ទ​ពេល​មិន​អាសន្ន"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"មិន​បាន​ផ្ញើ​ការ​ហៅ បាន​បញ្ចូល​លេខ​​​មិន​ត្រឹមត្រូវ។"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"ការហៅពេលមានអាសន្នដែលត្រូវបានអនុញ្ញាតដោយម្ចាស់ឧបករណ៍តែប៉ុណ្ណោះ។"</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>
diff --git a/res/values-kn-rIN/strings.xml b/res/values-kn-rIN/strings.xml
index 5109406..6887fce 100644
--- a/res/values-kn-rIN/strings.xml
+++ b/res/values-kn-rIN/strings.xml
@@ -18,10 +18,10 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="telecommAppLabel" product="default" msgid="3477737022166975496">"ಫೋನ್"</string>
     <string name="unknown" msgid="6878797917991465859">"ಅಜ್ಞಾತ"</string>
-    <string name="notification_missedCallTitle" msgid="7554385905572364535">"ತಪ್ಪಿ ಹೋದ ಕರೆ"</string>
+    <string name="notification_missedCallTitle" msgid="7554385905572364535">"ಮಿಸ್ಡ್‌ ಕಾಲ್‌"</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_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>
@@ -34,12 +34,11 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"ಡೀಫಾಲ್ಟ್ ಅಪ್ಲಿಕೇಶನ್ ಮರುಹೊಂದಿಸಿ"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> ಗೆ ಸಂದೇಶ ಕಳುಹಿಸಲಾಗಿದೆ."</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"ಫೋನ್ ಖಾತೆ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"ಡೀಫಾಲ್ಟ್ ಹೊರಹೋಗುವ ಖಾತೆ"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"Wi-Fi ಕರೆ ಮಾಡುವ ಖಾತೆ"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"ಪ್ರತಿ ಬಾರಿ ಕೇಳಿ"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"Wi-Fi ಕರೆ ಮಾಡುವಿಕೆಯನ್ನು ಬಳಸಬೇಡಿ"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"ತುರ್ತುಸ್ಥಿತಿಯಲ್ಲದ ಫೋನ್‌ ಕರೆಗಳನ್ನು ಮಾಡಲು ಈ ಬಳಕೆದಾರರನ್ನು ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"ಸಾಧನದ ಮಾಲೀಕರಿಂದ ತುರ್ತು ಕರೆಗಳನ್ನು ಮಾಡಲು ಮಾತ್ರ ಅವಕಾಶವಿದೆ"</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>
 </resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 3d67c7f..66c0131 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"기본 앱 재설정"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g>(으)로 메시지를 보냈습니다."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"일반 전화를 걸 수 없는 사용자입니다."</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"잘못된 번호를 입력했으므로 전화를 걸지 못했습니다."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"기기 소유자만 긴급 전화를 사용할 수 있습니다."</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>
diff --git a/res/values-ky-rKG/strings.xml b/res/values-ky-rKG/strings.xml
index 064a0d1..253d7ab 100644
--- a/res/values-ky-rKG/strings.xml
+++ b/res/values-ky-rKG/strings.xml
@@ -43,12 +43,14 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"Абалкы колдонмону өзгөртүү"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> номуруна билдирүү жөнөтүлдү."</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"Телефондун каттоо эсебинин жөндөөлөрү"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"Демейки чыгуучу каттоо эсеби"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"Wi-Fi чалуу үчүн каттоо эсеби"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"Чалган сайын сурасын"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"Wi-Fi чалуу колдонулбасын"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Бул колдонуучу шашылыш эмес чалууларды аткара албайт"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Түзмөк ээси шашылыш чалууларга гана уруксат берген"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Чалуу үчүн, жарактуу номер киргизиңиз."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Бул жолу чалууну кошуу мүмкүн эмес."</string>
+    <!-- no translation found for no_vm_number (4164780423805688336) -->
+    <skip />
+    <!-- no translation found for no_vm_number_msg (1300729501030053828) -->
+    <skip />
+    <!-- no translation found for add_vm_number_str (4676479471644687453) -->
+    <skip />
 </resources>
diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml
index cac6273..a6e3ffb 100644
--- a/res/values-lo-rLA/strings.xml
+++ b/res/values-lo-rLA/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"ຄືນຄ່າແອັບຯເລີ່ມຕົ້ນ"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"ສົ່ງຂໍ້ຄວາມຫາ <xliff:g id="PHONE_NUMBER">%s</xliff:g> ແລ້ວ."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"ຜູ່​ໃຊ້​ນີ້ບໍ່​ໄດ້​ຮັບ​ອະ​ນຸ​ຍາດ​ໃຫ້​ໂທ​ສຸກ​ເສີນ​ໄດ້"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"ບໍ່ໄດ້ໂທເທື່ອ, ເບີໂທທີ່ລະບຸບໍ່ຖືກຕ້ອງ."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"ພຽງ​ແຕ່​ການ​ໂທ​ສຸກ​ເສີນ​ທີ່​ໄດ້​ຮັບ​ອະ​ນຸ​ຍາດ​ຈາກ​ເຈົ້າ​ຂອງ​ອຸ​ປະ​ກອນ​ເທົ່າ​ນັ້ນ"</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 card."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"ເພີ່ມໝາຍເລກ"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 74213ca..6a52bb8 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Redaguoti greitus atsakus"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Greitas atsakas"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Nustat. iš naujo numat. prog."</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Pranešimas išsiųstas numeriu <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Šiam naudotojui leidžiama vykdyti tik skambučius pagalbos numeriais"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Skambutis neatliktas; įvestas netinkamas numeris."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Įrenginio savininkas leidžia skambinti tik pagalbos numeriais"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Kad galėtumėte paskambinti, įveskite tinkamą numerį."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Šiuo metu dar vieno skambučio atlikti negalima."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Trūksta balso pašto numerio"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"SIM kortelėje nėra išsaugoto balso pašto numerio."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Pridėti numerį"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 5c3fb24..0c4e2e0 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Ātro atbilžu rediģēšana"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Ātrā atbilde"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Atiestatīt noklus. lietotni"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Ziņojums nosūt. uz šādu tālr. nr.: <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Šim lietotājam nav atļauts veikt ārkārtas tālruņa zvanus."</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Zvans nav nosūtīts; nav ievadīts derīgs numurs."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Ierīces īpašnieks ļauj veikt tikai ārkārtas zvanus."</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Lai veiktu zvanu, ievadiet derīgu numuru."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Šobrīd nevar pievienot zvanu."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Trūkst balss pasta numura"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"SIM kartē neviens balss pasta numurs nav saglabāts."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Pievienot numuru"</string>
diff --git a/res/values-mk-rMK/strings.xml b/res/values-mk-rMK/strings.xml
index 52df23f..008a70f 100644
--- a/res/values-mk-rMK/strings.xml
+++ b/res/values-mk-rMK/strings.xml
@@ -34,12 +34,11 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"Ресетирај стандардна апликација"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Порака е испратена на <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"Поставки на телефонска сметка"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"Стандардна излезна сметка"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"Сметка за повикување преку Wi-Fi"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"Секогаш прашај"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"Не користи повикување преку Wi-Fi"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Корисникот нема дозвола да прави телефонски повици ако не е итно"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Дозволени се само итни повици од страна на сопственикот на уредот"</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>
 </resources>
diff --git a/res/values-ml-rIN/strings.xml b/res/values-ml-rIN/strings.xml
index 3e8d420..d3b3b1c 100644
--- a/res/values-ml-rIN/strings.xml
+++ b/res/values-ml-rIN/strings.xml
@@ -34,12 +34,11 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"സ്ഥിര അപ്ലിക്കേഷൻ പുനഃസജ്ജമാക്കുക"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> എന്നതിലേക്ക് സന്ദേശമയച്ചു."</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"ഫോൺ അക്കൗണ്ട് ക്രമീകരണങ്ങൾ"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"സ്ഥിര ഔട്ട്ഗോയിംഗ് അക്കൗണ്ട്"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"Wi-Fi കോൾ ചെയ്യൽ അക്കൗണ്ട്"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"ഓരോ തവണയും ചോദിക്കുക"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"Wi-Fi കോൾ ചെയ്യൽ ഉപയോഗിക്കരുത്"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"അത്യാവശ്യമല്ലാത്ത ഫോൺ കോളുകൾ ചെയ്യാൻ ഈ ഉപയോക്താവിനെ അനുവദിക്കുന്നില്ല"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"ഉപകരണ ഉടമ അടിയന്തിര കോളുകൾ മാത്രമേ അനുവദിച്ചിട്ടുള്ളൂ"</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>
 </resources>
diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn-rMN/strings.xml
index b38d1d1..7b3c734 100644
--- a/res/values-mn-rMN/strings.xml
+++ b/res/values-mn-rMN/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"Үндсэн апп-г сэргээх"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Зурвасыг <xliff:g id="PHONE_NUMBER">%s</xliff:g> руу илгээв."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Энэ хэрэглэгч нь яаралтай бус утасны дуудлага хийх эрхгүй"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Дуудлага илгээгдсэнгүй, зөв дугаар оруулаагүй байна."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Энэхүү төхөөрөмжийн эзэмшигч нь зөвхөн түргэн тусламжийн дуудлага хийх эрхтэй байна."</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>
diff --git a/res/values-mr-rIN/strings.xml b/res/values-mr-rIN/strings.xml
index c04c823..5b802d0 100644
--- a/res/values-mr-rIN/strings.xml
+++ b/res/values-mr-rIN/strings.xml
@@ -34,12 +34,11 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"डीफॉल्ट अ‍ॅप रीसेट करा"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"संदेश <xliff:g id="PHONE_NUMBER">%s</xliff:g> वर पाठविला."</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"फोन खाते सेटिंग्ज"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"डीफॉल्ट केले जाणारे खाते"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"Wi-Fi कॉल करण्याचे खाते"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"प्रत्येक वेळी विचारा"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"Wi-Fi कॉल करणे वापरू नका"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"या वापरकर्त्यास आणीबाणी-नसलेले फोन कॉल करण्‍याची अनुमती नाही"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"डिव्हाइस मालकाद्वारे केवळ आणीबाणी कॉलना अनुमती आहे"</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>
 </resources>
diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml
index d0d7846..82f34a4 100644
--- a/res/values-ms-rMY/strings.xml
+++ b/res/values-ms-rMY/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Edit respons pantas"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Respons pantas"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Tetapkan semula apl lalai"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mesej dihantar ke <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Pengguna ini tidak dibenarkan membuat panggilan telefon bukan kecemasan"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Panggilan tidak dihantar, tiada nombor yang sah dimasukkan."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Hanya panggilan kecemasan dibenarkan oleh pemilik peranti"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Untuk membuat panggilan, masukkan nombor yang sah."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Panggilan tidak boleh ditambahkan pada masa ini."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Nombor mel suara tiada"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Tidak ada nombor mel suara disimpan pada kad SIM."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Tambah nombor"</string>
diff --git a/res/values-my-rMM/strings.xml b/res/values-my-rMM/strings.xml
index 3742912..b028ed5 100644
--- a/res/values-my-rMM/strings.xml
+++ b/res/values-my-rMM/strings.xml
@@ -34,12 +34,11 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"ပုံသေ အပ်ပလီကေးရှင်းအား ပြန်ပြောင်းရန်"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> ထံ စာတိုပို့လိုက်ပါပြီ"</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"ဖုန်း အကောင့် ဆက်တင်များ"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"ပုံသေ အထွက် အကောင့်"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"ကြိုးမဲ့ ခေါ်ဆိုမှု အကောင့်"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"အကြိမ်တိုင်းမှာ မေးရန်"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"ကြိုးမဲ့ ခေါ်ဆိုမှုကို မသုံးပါနှင့်"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"ဒီအသုံးပြုသူအား အရေးပေါ် မဟုတ်သည့် ဖုန်း ခေါ်ဆိုမှုများ လုပ်ခွင့် မပြုပါ"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"အရေးပေါ်ဖုန်းများကိုသာ ခေါ်ဆိုနိုင်ရန် စက်ကိရိယာပိုင်ရှင်က ခွင့်ပြုထား၏"</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>
 </resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 36b1297..92d9061 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Rediger hurtigsvar"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Hurtigsvar"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Tilbakestill standardappen"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Melding er sendt til <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Denne brukeren har bare tillatelse til å ringe nødnumre"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Kunne ikke ringe. Du har ikke angitt et gyldig nummer."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Eieren av enheten tillater bare nødanrop"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Skriv inn et gyldig nummer for å plassere en samtale."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Anrop kan ikke legges til akkurat nå."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Mangler nummer til telefonsvarer"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Det er ikke lagret noe telefonsvarernummer på SIM-kortet."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Legg til nummer"</string>
diff --git a/res/values-ne-rNP/strings.xml b/res/values-ne-rNP/strings.xml
index 0fe8775..cc91f33 100644
--- a/res/values-ne-rNP/strings.xml
+++ b/res/values-ne-rNP/strings.xml
@@ -34,12 +34,11 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"पूर्वनिर्धारित अनुप्रयोग पुनःसेट गर्नुहोस्"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> लाई सन्देश पठाइयो।"</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"फोन खाता सेटिङहरू"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"बहिर्गमन पूर्वनिर्धारित खाता"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"वाइफाइ कल गर्ने खाता"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"प्रत्येक चोटि सोध्नुहोस्"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"वाइफाइ कल प्रयोग नगर्नुहोस्"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"यो प्रयोगकर्तालाई गैर-आकस्मिक फोन कल गर्न अनुमति छैन"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"केवल आपतकालीन कलहरू मात्र यन्त्र मालिकद्वारा अनुमति दिइएको छ"</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>
 </resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 9d5a1ee..e726f49 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Snelle reacties bewerken"</string>
     <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_menu_reset_default_activity" msgid="1461742052902053466">"Standaardapp opnieuw instellen"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Bericht verzonden naar <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Het is deze gebruiker niet toegestaan niet-noodoproepen te plaatsen"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Oproep niet verzonden, geen geldig nummer ingevoerd."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Alleen noodoproepen zijn toegestaan door de apparaateigenaar"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Als u wilt bellen, moet u een geldig nummer invoeren."</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 SIM-kaart opgeslagen."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Nummer toevoegen"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 7d392ac..9d48689 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Edytuj szybkie odpowiedzi"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Szybka odpowiedź"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Resetuj domyślną aplikację"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Wiadomość wysłano na numer <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Ten użytkownik nie ma uprawnień do połączeń innych niż alarmowe"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Połączenie niezrealizowane. Nie podano poprawnego numeru."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Właściciel urządzenia zezwala tylko na połączenia alarmowe"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Aby zadzwonić, wybierz prawidłowy numer."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Nie można w tej chwili dodać połączenia."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Brakuje numeru poczty głosowej"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Na karcie SIM nie ma zapisanego numeru poczty głosowej."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Dodaj numer"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index ed953a7..2d2d4b9 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Editar respostas rápidas"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Resposta rápida"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Repor aplicação predefinida"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mensagem enviada para <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Este utilizador não está autorizado a fazer chamadas telefónicas que não sejam de emergência"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"A chamada não foi efetuada. Não foi introduzido um número válido."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Só são permitidas chamadas de emergência pelo proprietário do dispositivo"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Para telefonar, introduza um número válido."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Não é possível adicionar a chamada neste momento."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Número do correio de voz em falta"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Não existe um número de correio de voz armazenado no cartão SIM."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Adicionar número"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index f36b090..8a8b7f7 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -16,7 +16,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="telecommAppLabel" product="default" msgid="3477737022166975496">"Smartphone"</string>
+    <string name="telecommAppLabel" product="default" msgid="3477737022166975496">"Telefone"</string>
     <string name="unknown" msgid="6878797917991465859">"Desconhecido"</string>
     <string name="notification_missedCallTitle" msgid="7554385905572364535">"Chamada perdida"</string>
     <string name="notification_missedCallsTitle" msgid="1361677948941502522">"Chamadas perdidas"</string>
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Editar respostas rápidas"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Resposta rápida"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Redefinir app padrão"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mensagem enviada para <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Este usuário não tem permissão para fazer chamadas não emergenciais pelo smartphone"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Chamada não enviada: nenhum número válido foi inserido."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Apenas chamadas de emergência são permitidas pelo proprietário do dispositivo"</string>
+    <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 cartão SIM."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Adicionar número"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 8010c9b..170d4f2 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Editaţi răspunsurile rapide"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Răspuns rapid"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Resetați aplic. prestabilită"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mesajul a fost trimis la <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Acest utilizator nu are permisiunea de a efectua apeluri telefonice către alte numere în afară de cele de urgență"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Apelul nu s-a trimis; niciun număr valid introdus."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Proprietarul dispozitivului permite numai apelurile de urgență"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Pentru a apela, introduceți un număr valid."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Apelul nu poate fi adăugat în acest moment."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Lipseşte numărul mesageriei vocale"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Niciun număr de mesagerie vocală nu este stocat pe cardul SIM."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Adăugaţi numărul"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index d95b887..26437e7 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"Сбросить стандартные настройки"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Сообщение отправлено на номер <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Этот пользователь может звонить только в службы экстренной помощи"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Для вызова укажите действительный номер телефона."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Владелец устройства разрешил только экстренные вызовы"</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>
diff --git a/res/values-si-rLK/strings.xml b/res/values-si-rLK/strings.xml
index 91f9f29..159cc40 100644
--- a/res/values-si-rLK/strings.xml
+++ b/res/values-si-rLK/strings.xml
@@ -34,12 +34,11 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"සුපුරුදු යෙදුම යළි සකසන්න"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> හට පණිවිඩය යවන්න."</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"දුරකථන ගිණුම සැකසීම"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"සුපුරුදු එළියට යෑමේ ගිණුම"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"Wi-Fi ඇමතුම් ගැනීමේ ගිණුම"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"සෑම වේලාවේම අසන්න"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"Wi-Fi ඇමතුම භාවිතා කරන්න එපා"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"හදිසි-නැති දුරකථන ඇමතුම් සිදුකිරීමට මෙම පරිශීලකයාට අවසර නොමැත"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"උපාංගයේ හිමිකරු විසින් හදිස්සි ඇමතුම් වලට පමණක් අවසර දෙයි"</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>
 </resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index f0fb553..7fb63b1 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -34,10 +34,10 @@
     <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>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Rýchla odpoveď"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Obnoviť predvolenú aplikáciu"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Správa bola odoslaná na číslo <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Tento používateľ smie uskutočňovať iba tiesňové hovory."</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Hovor sa nepodarilo spojiť, nebolo zadané platné číslo."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Vlastník zariadenia povolil iba tiesňové volania."</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Ak chcete volať, zadajte platné číslo"</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Hovor momentálne nie je možné pridať."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Chýba číslo hlasovej schránky"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Na karte SIM nie je uložené žiadne číslo hlasovej schránky."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Pridať číslo"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index a0eb220..ec6df19 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Urejanje hitrih odgovorov"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Hiter odgovor"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Ponastavi privzeto aplikacijo"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"SMS poslan na številko <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Temu uporabniku ni dovoljeno telefoniranje, razen klicev v sili"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Klic ni bil poslan, veljavna številka ni vnesena."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Lastnik naprave dovoljuje samo opravljanje klicev v sili"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Če želite opraviti klic, vnesite veljavno številko."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Klica trenutno ni mogoče dodati."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Manjkajoča številka glasovne pošte"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Na kartici SIM ni shranjena številka glasovne pošte."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Dodaj številko"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 2e49851..a93b09d 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"Ресетуј подразумев. апликацију"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Порука је послата на број <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Овом кориснику није дозвољено да упућује телефонске позиве који нису хитни"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Позив није послат, није унет важећи број."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Власник уређаја је дозволио само хитне позиве"</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>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 8abbe72..c25b40b 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Redigera snabbsvar"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Snabbsvar"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Återställ standardappen"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Meddelandet har skickats till <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Denna användare har inte tillåtelse att ringa icke-akuta samtal"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Samtalet har inte skickats. Du måste ange ett giltigt nummer."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Endast nödsamtal är tillåtna av enhetens ägare"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Ange ett giltigt nummer om du vill ringa ett samtal."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Det går inte att lägga till samtalet just nu."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Nummer till röstbrevlåda saknas"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Det finns inget nummer till röstbrevlådan sparat på SIM-kortet."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Lägg till nummer"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 6395aba..1c01fb7 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Hariri majibu ya haraka"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Majibu ya haraka"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Weka upya programu chaguo-msingi"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Ujumbe uliotumwa kwa <xliff:g id="PHONE_NUMBER">%s</xliff:g> ."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Mtumiaji huyu haruhusiwi kupiga simu zisizo za dharura"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Simu haijatumwa, hakuna nambari sahihi iliyowekwa."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Ni simu za dharura pekee zinazoruhusiwa na mmiliki wa kifaa"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Ili upige simu, weka nambari sahihi."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Hangout ya video haiwezi kuongezwa kwa wakati huu."</string>
     <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>
diff --git a/res/values-ta-rIN/strings.xml b/res/values-ta-rIN/strings.xml
index 5c50ffb..98157c6 100644
--- a/res/values-ta-rIN/strings.xml
+++ b/res/values-ta-rIN/strings.xml
@@ -34,12 +34,11 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"இயல்பு பயன்பாட்டை மீட்டமை"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> க்குச் செய்தி அனுப்பப்பட்டது."</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"ஃபோன் கணக்கு அமைப்புகள்"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"அழைப்பிற்கான இயல்புநிலை கணக்கு"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"வைஃபை அழைப்பிற்கான கணக்கு"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"ஒவ்வொரு முறையும் கேள்"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"வைஃபை அழைப்பைப் பயன்படுத்தாதே"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"அவசரமற்ற ஃபோன் அழைப்புகளைச் செய்ய இவருக்கு அனுமதியில்லை"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"சாதன உரிமையாளர் அவசர அழைப்புகளை மட்டுமே அனுமதித்துள்ளார்"</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>
 </resources>
diff --git a/res/values-te-rIN/strings.xml b/res/values-te-rIN/strings.xml
index 627ed4a..31b5273 100644
--- a/res/values-te-rIN/strings.xml
+++ b/res/values-te-rIN/strings.xml
@@ -34,12 +34,11 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"డిఫాల్ట్ అనువర్తనాన్ని రీసెట్ చేయి"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g>కు సందేశం పంపబడింది."</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"ఫోన్ ఖాతా సెట్టింగ్‌లు"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"డిఫాల్ట్ అవుట్‌గోయింగ్ ఖాతా"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"Wi-Fi కాలింగ్ ఖాతా"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"ప్రతిసారి అడుగు"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"Wi-Fi కాలింగ్‌ను ఉపయోగించవద్దు"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"ఈ వినియోగదారుకి అత్యవసరం కాని ఫోన్ కాల్‌లు చేయడానికి అనుమతి లేదు"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"పరికరం యజమాని అత్యవసర కాల్‌లను మాత్రమే అనుమతించారు"</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>
 </resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 78f2ee4..b936083 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"รีเซ็ตแอปพลิเคชันเริ่มต้น"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"ส่งข้อความไปยัง <xliff:g id="PHONE_NUMBER">%s</xliff:g> แล้ว"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"ไม่อนุญาตให้ผู้ใช้รายนี้ดำเนินการโทรที่ไม่ฉุกเฉิน"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"ไม่ได้โทรออก ไม่ได้ป้อนหมายเลขที่ถูกต้อง"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"เจ้าของอุปกรณ์อนุญาตเฉพาะหมายเลขฉุกเฉิน"</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>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 0b7f481..81d05b7 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"I-edit ang mga mabilisang tugon"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Mabilisang tugon"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"I-reset ang default na app"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Naipadala ang mensahe sa <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Hindi pinapahintulutan ang user na ito na gumawa ng mga hindi pang-emergency na tawag sa telepono"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Hindi naipadala ang tawag, walang inilagay na wastong numero."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Ang mga emergency na tawag lang ang pinapayagan ng may-ari ng device"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Upang tumawag, maglagay ng wastong numero."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Hindi maidadagdag ang tawag sa oras na ito."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Nawawala ang numero ng voicemail"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Walang nakaimbak na numero ng voicemail sa SIM card."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Magdagdag ng numero"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 662bee5..00169e4 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Hızlı yanıtları düzenle"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Hızlı yanıt"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Varsayılan uygulamayı sıfırla"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mesaj, <xliff:g id="PHONE_NUMBER">%s</xliff:g> numaralı telefona gönderildi."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Bu kullanıcının acil olmayan telefon çağrıları yapmasına izin verilmiyor"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Çağrı gönderilmedi, geçerli bir numara girilmedi."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Cihaz sahibi sadece acil durum çağrılarına izin veriyor"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Telefon etmek için geçerli bir numara girin."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Çağrı şu anda eklenemiyor."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Eksik sesli mesaj numarası"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"SIM kartta depolanan sesli mesaj numarası yok."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Numara ekle"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index cb89808..e2494d2 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"Скинути програму за умовчанням"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Повідомлення надіслано на номер <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Цьому користувачу не дозволено здійснювати звичайні телефонні дзвінки"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Дзвінок не відбувся, введіть дійсний номер."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Власник пристрою дозволив лише екстрені виклики"</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>
diff --git a/res/values-ur-rPK/strings.xml b/res/values-ur-rPK/strings.xml
index 16b8bac..c2503e3 100644
--- a/res/values-ur-rPK/strings.xml
+++ b/res/values-ur-rPK/strings.xml
@@ -34,12 +34,11 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"ڈیفالٹ ایپ دوبارہ ترتیب دیں"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"پیغام <xliff:g id="PHONE_NUMBER">%s</xliff:g> کو بھیج دیا گیا۔"</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"فون اکاؤنٹ کی ترتیبات"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"ڈیفالٹ آؤٹ گوئنگ اکاؤنٹ"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"‏Wi-Fi کالنگ اکاؤنٹ"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"ہر بار پوچھیں"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"‏Wi-Fi کالنگ کا استعمال نہ کریں"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"اس صارف کو غیر ہنگامی فون کالیں کرنے کی اجازت نہیں ہے"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"آلہ کے مالک نے صرف ہنگامی کالز کی اجازت دی ہے۔"</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>
 </resources>
diff --git a/res/values-uz-rUZ/strings.xml b/res/values-uz-rUZ/strings.xml
index 6d259b3..e2f370d 100644
--- a/res/values-uz-rUZ/strings.xml
+++ b/res/values-uz-rUZ/strings.xml
@@ -34,12 +34,11 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Tezkor javoblarni tahrirlash"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Tezkor javob"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Standart ilovani tiklash"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Xabar <xliff:g id="PHONE_NUMBER">%s</xliff:g>ga jo‘natildi."</string>
-    <string name="phone_account_preferences_title" msgid="5042332049625236956">"Telefon hisobi sozlamalari"</string>
-    <string name="default_outgoing_account_title" msgid="8261079649574578970">"Chiquvchi qo‘ng‘iroqlar uchun birlamchi hisob"</string>
-    <string name="sim_call_manager_account" msgid="2559930293628077755">"Wi-Fi qo‘ng‘iroqlar uchun hisob"</string>
-    <string name="account_ask_every_time" msgid="944077828070287407">"Har safar so‘ralsin"</string>
-    <string name="do_not_use_sim_call_manager" msgid="5519252524007323694">"Wi-Fi qo‘ng‘iroqlardan foydalanilmasin"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Ushbu foydalanuvchiga favqulodda qo‘ng‘iroqlardan boshqa telefon qo‘ng‘iroqlarini amalga oshirish uchun ruxsat berilmagan"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Qurilma egasi faqat favqulodda qo‘ng‘iroqlarga ruxsat bergan"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Qo‘ng‘iroq qilish uchun raqamni to‘g‘ri kiriting."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Hozirgi vaqtda qo‘ng‘iroq qo‘shib bo‘lmaydi."</string>
+    <string name="no_vm_number" msgid="4164780423805688336">"Javobsiz ovozli xabar raqami"</string>
+    <string name="no_vm_number_msg" msgid="1300729501030053828">"SIM kartada birorta ham ovozli xabar saqlanmagan."</string>
+    <string name="add_vm_number_str" msgid="4676479471644687453">"Raqam qo‘shish"</string>
 </resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 83d75ba..68c794e 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Chỉnh sửa trả lời nhanh"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Trả lời nhanh"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Đặt lại ứng dụng mặc định"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Đã gửi tin nhắn tới <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Người dùng này không được phép thực hiện cuộc gọi điện thoại không khẩn cấp"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Không gọi được, bạn đã nhập số không hợp lệ."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Chỉ chủ sở hữu thiết bị mới được phép thực hiện cuộc gọi khẩn cấp"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Để thực hiện cuộc gọi, hãy nhập một số hợp lệ."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Không thể thêm cuộc gọi tại thời điểm này."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Thiếu số thư thoại"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Không có số thư thoại nào được lưu trữ trên thẻ SIM."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Thêm số điện thoại"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index e085d1e..8a62ae2 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"重置默认应用"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"讯息已发送至 <xliff:g id="PHONE_NUMBER">%s</xliff:g>。"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"此用户无权拨打非紧急呼救电话"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"拨号失败,因为输入的号码无效。"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"设备机主仅允许拨打紧急呼救电话"</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>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index a775f59..c05d3c9 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"重設預設應用程式"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"訊息已傳送至 <xliff:g id="PHONE_NUMBER">%s</xliff:g>。"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"這位使用者只可撥打緊急電話"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"無法傳送,輸入的號碼無效。"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"只有裝置擁有者才可撥打緊急電話"</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>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 3922f91..bb0d95e 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -34,10 +34,10 @@
     <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_menu_reset_default_activity" msgid="1461742052902053466">"重設預設應用程式"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"訊息已傳送至 <xliff:g id="PHONE_NUMBER">%s</xliff:g>。"</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"這位使用者只能撥打緊急電話"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"輸入的號碼無效,無法撥出。"</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"裝置擁有者限定只能撥打緊急電話"</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>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index f498490..222378d 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -34,10 +34,10 @@
     <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Hlela izimpendulo ezisheshayo"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Izimpendulo ezisheshayo"</string>
-    <string name="respond_via_sms_menu_reset_default_activity" msgid="1461742052902053466">"Setha kabusha uhlelo lokusebenza lokuzenzakalelayo"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Umlayezo othunyelwe ku <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
-    <string name="outgoing_call_not_allowed" msgid="1434784869685645427">"Lo msebenzisi akavunyelwe ukwenza amakholi wefoni okungewona wesimo esiphuthumayo"</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="4987143284589568716">"Ikholi ayithunyelwe, ayikho inombolo evumelekile efakiwe."</string>
+    <string name="outgoing_call_not_allowed" msgid="1435394568102165287">"Amakholi wesimo esiphuthumayo kuphela avunyelwe ngumnikazi wedivayisi"</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Ukuze wenze ikholi, faka inombolo evumelekile."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Ikholi ayikwazi ukungezwa ngalesi sikhathi."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Inombolo engekho yomyalezo wezwi"</string>
     <string name="no_vm_number_msg" msgid="1300729501030053828">"Ayikho inombolo yomlayezo wezwi egcinwe ekhadini le-SIM."</string>
     <string name="add_vm_number_str" msgid="4676479471644687453">"Engeza inombolo"</string>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index e93e855..64db085 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -16,4 +16,8 @@
 
 <resources>
     <color name="theme_color">#0288d1</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">#0277bd</color>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 86d803d..f7ad003 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -18,4 +18,6 @@
     <!-- Dimension used to possibly down-scale high-res photo into what is suitable
          for notification's large icon. -->
     <dimen name="notification_icon_size">64dp</dimen>
+
+    <dimen name="dialer_settings_actionbar_elevation">2dp</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9ecc6bb..37e59c0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -68,9 +68,6 @@
     <string name="respond_via_sms_setting_summary"></string>
     <!-- Dialog title when changing a string for the "Respond via SMS" feature. [CHAR LIMIT=30] -->
     <string name="respond_via_sms_edittext_dialog_title">Quick response</string>
-    <!-- Menu option in  "Respond via SMS" that allows user to reset the default
-         activity used to handle "Respond via SMS" [CHAR LIMIT=30] -->
-    <string name="respond_via_sms_menu_reset_default_activity">Reset default app</string>
 
     <!-- "Respond via SMS": Confirmation message shown after sending
         a text response. [CHAR LIMIT=40] -->
@@ -78,10 +75,13 @@
 
     <!-- Message indicating that the user is not allowed to make non-emergency outgoing phone calls
          due to a user restriction -->
-    <string name="outgoing_call_not_allowed">This user is not allowed to make non-emergency phone calls</string>
+    <string name="outgoing_call_not_allowed">Only emergency calls are allowed by the device owner</string>
 
     <!-- Call failure message displayed in an error dialog used to indicate that a phone number was not provided -->
-    <string name="outgoing_call_error_no_phone_number_supplied">Call not sent, no valid number entered.</string>
+    <string name="outgoing_call_error_no_phone_number_supplied">To place a call, enter a valid number.</string>
+
+    <!-- Message shown when the user tries to make a video call when already in a video call. -->
+    <string name ="duplicate_video_call_not_allowed">Call cannot be added at this time.</string>
 
     <!-- missing voicemail number -->
     <!-- Title of the "Missing voicemail number" dialog -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 6b6c1bb..f073906 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -24,4 +24,30 @@
         <item name="android:backgroundDimEnabled">true</item>
         <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
     </style>
+
+    <style name="Theme.Telecom.DialerSettings" parent="@android:style/Theme.Material.Light">
+        <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:windowContentOverlay">@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: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_white_24dp</item>
+    </style>
 </resources>
diff --git a/src/com/android/server/telecom/AsyncRingtonePlayer.java b/src/com/android/server/telecom/AsyncRingtonePlayer.java
index 4434424..3030fea 100644
--- a/src/com/android/server/telecom/AsyncRingtonePlayer.java
+++ b/src/com/android/server/telecom/AsyncRingtonePlayer.java
@@ -196,7 +196,9 @@
         }
 
         Ringtone ringtone = RingtoneManager.getRingtone(mContext, ringtoneUri);
-        ringtone.setStreamType(AudioManager.STREAM_RING);
+        if (ringtone != null) {
+            ringtone.setStreamType(AudioManager.STREAM_RING);
+        }
         return ringtone;
     }
 }
diff --git a/src/com/android/server/telecom/BluetoothManager.java b/src/com/android/server/telecom/BluetoothManager.java
index 9b5fd26..f74349f 100644
--- a/src/com/android/server/telecom/BluetoothManager.java
+++ b/src/com/android/server/telecom/BluetoothManager.java
@@ -26,6 +26,8 @@
 import android.content.IntentFilter;
 import android.os.SystemClock;
 
+import com.android.internal.util.IndentingPrintWriter;
+
 import java.util.List;
 
 /**
@@ -244,30 +246,33 @@
         mBluetoothConnectionPending = false;
     }
 
-    private void dumpBluetoothState() {
-        Log.d(this, "============== dumpBluetoothState() =============");
-        Log.d(this, "= isBluetoothAvailable: " + isBluetoothAvailable());
-        Log.d(this, "= isBluetoothAudioConnected: " + isBluetoothAudioConnected());
-        Log.d(this, "= isBluetoothAudioConnectedOrPending: " +
-                isBluetoothAudioConnectedOrPending());
-        Log.d(this, "=");
+    /**
+     * Dumps the state of the {@link BluetoothManager}.
+     *
+     * @param pw The {@code IndentingPrintWriter} to write the state to.
+     */
+    public void dump(IndentingPrintWriter pw) {
+        pw.println("isBluetoothAvailable: " + isBluetoothAvailable());
+        pw.println("isBluetoothAudioConnected: " + isBluetoothAudioConnected());
+        pw.println("isBluetoothAudioConnectedOrPending: " + isBluetoothAudioConnectedOrPending());
+
         if (mBluetoothAdapter != null) {
             if (mBluetoothHeadset != null) {
                 List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();
 
                 if (deviceList.size() > 0) {
                     BluetoothDevice device = deviceList.get(0);
-                    Log.d(this, "= BluetoothHeadset.getCurrentDevice: " + device);
-                    Log.d(this, "= BluetoothHeadset.State: "
-                        + mBluetoothHeadset.getConnectionState(device));
-                    Log.d(this, "= BluetoothHeadset audio connected: " +
-                        mBluetoothHeadset.isAudioConnected(device));
+                    pw.println("BluetoothHeadset.getCurrentDevice: " + device);
+                    pw.println("BluetoothHeadset.State: "
+                            + mBluetoothHeadset.getConnectionState(device));
+                    pw.println("BluetoothHeadset audio connected: " +
+                            mBluetoothHeadset.isAudioConnected(device));
                 }
             } else {
-                Log.d(this, "= mBluetoothHeadset is null");
+                pw.println("mBluetoothHeadset is null");
             }
         } else {
-            Log.d(this, "= mBluetoothAdapter is null; device is not BT capable");
+            pw.println("mBluetoothAdapter is null; device is not BT capable");
         }
     }
 }
diff --git a/src/com/android/server/telecom/BluetoothPhoneService.java b/src/com/android/server/telecom/BluetoothPhoneService.java
index 8bf50ae..9a0cae1 100644
--- a/src/com/android/server/telecom/BluetoothPhoneService.java
+++ b/src/com/android/server/telecom/BluetoothPhoneService.java
@@ -28,11 +28,12 @@
 import android.net.Uri;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.telecom.CallState;
+import android.telecom.Connection;
 import android.telecom.PhoneAccount;
-import android.telecom.PhoneCapabilities;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -53,7 +54,8 @@
      * Request object for performing synchronous requests to the main thread.
      */
     private static class MainThreadRequest {
-        Object result;
+        private static final Object RESULT_NOT_SET = new Object();
+        Object result = RESULT_NOT_SET;
         int param;
 
         MainThreadRequest(int param) {
@@ -498,7 +500,7 @@
                 return true;
             }
         } else if (chld == CHLD_TYPE_HOLDACTIVE_ACCEPTHELD) {
-            if (activeCall != null && activeCall.can(PhoneCapabilities.SWAP_CONFERENCE)) {
+            if (activeCall != null && activeCall.can(Connection.CAPABILITY_SWAP_CONFERENCE)) {
                 activeCall.swapConference();
                 return true;
             } else if (ringingCall != null) {
@@ -509,13 +511,13 @@
                 // currently-held call.
                 callsManager.unholdCall(heldCall);
                 return true;
-            } else if (activeCall != null && activeCall.can(PhoneCapabilities.HOLD)) {
+            } else if (activeCall != null && activeCall.can(Connection.CAPABILITY_HOLD)) {
                 callsManager.holdCall(activeCall);
                 return true;
             }
         } else if (chld == CHLD_TYPE_ADDHELDTOCONF) {
             if (activeCall != null) {
-                if (activeCall.can(PhoneCapabilities.MERGE_CONFERENCE)) {
+                if (activeCall.can(Connection.CAPABILITY_MERGE_CONFERENCE)) {
                     activeCall.mergeConference();
                     return true;
                 } else {
@@ -539,14 +541,19 @@
     }
 
     private <T> T sendSynchronousRequest(int message, int param) {
+        if (Looper.myLooper() == mHandler.getLooper()) {
+            Log.w(TAG, "This method will deadlock if called from the main thread.");
+        }
+
         MainThreadRequest request = new MainThreadRequest(param);
         mHandler.obtainMessage(message, request).sendToTarget();
         synchronized (request) {
-            while (request.result == null) {
+            while (request.result == MainThreadRequest.RESULT_NOT_SET) {
                 try {
                     request.wait();
                 } catch (InterruptedException e) {
                     // Do nothing, go back and wait until the request is complete.
+                    Log.e(TAG, e, "InterruptedException");
                 }
             }
         }
@@ -587,8 +594,8 @@
 
             // Run some alternative states for Conference-level merge/swap support.
             // Basically, if call supports swapping or merging at the conference-level, then we need
-            // to expose the calls as having distinct states (ACTIVE vs HOLD) or the functionality
-            // won't show up on the bluetooth device.
+            // to expose the calls as having distinct states (ACTIVE vs CAPABILITY_HOLD) or the
+            // functionality won't show up on the bluetooth device.
 
             // Before doing any special logic, ensure that we are dealing with an ACTIVE call and
             // that the conference itself has a notion of the current "active" child call.
@@ -597,8 +604,8 @@
                 // Reevaluate state if we can MERGE or if we can SWAP without previously having
                 // MERGED.
                 boolean shouldReevaluateState =
-                        conferenceCall.can(PhoneCapabilities.MERGE_CONFERENCE) ||
-                        (conferenceCall.can(PhoneCapabilities.SWAP_CONFERENCE) &&
+                        conferenceCall.can(Connection.CAPABILITY_MERGE_CONFERENCE) ||
+                        (conferenceCall.can(Connection.CAPABILITY_SWAP_CONFERENCE) &&
                          !conferenceCall.wasConferencePreviouslyMerged());
 
                 if (shouldReevaluateState) {
@@ -680,7 +687,7 @@
 
         String ringingAddress = null;
         int ringingAddressType = 128;
-        if (ringingCall != null) {
+        if (ringingCall != null && ringingCall.getHandle() != null) {
             ringingAddress = ringingCall.getHandle().getSchemeSpecificPart();
             if (ringingAddress != null) {
                 ringingAddressType = PhoneNumberUtils.toaFromString(ringingAddress);
@@ -698,11 +705,11 @@
         // to show "swap" and "merge" functionality.
         boolean ignoreHeldCallChange = false;
         if (activeCall != null && activeCall.isConference()) {
-            if (activeCall.can(PhoneCapabilities.SWAP_CONFERENCE)) {
+            if (activeCall.can(Connection.CAPABILITY_SWAP_CONFERENCE)) {
                 // Indicate that BT device should show SWAP command by indicating that there is a
                 // call on hold, but only if the conference wasn't previously merged.
                 numHeldCalls = activeCall.wasConferencePreviouslyMerged() ? 0 : 1;
-            } else if (activeCall.can(PhoneCapabilities.MERGE_CONFERENCE)) {
+            } else if (activeCall.can(Connection.CAPABILITY_MERGE_CONFERENCE)) {
                 numHeldCalls = 1;  // Merge is available, so expose via numHeldCalls.
             }
 
@@ -851,8 +858,11 @@
      * phone account for PhoneAccount.SCHEME_TEL.
      */
     private PhoneAccount getBestPhoneAccount() {
-        TelecomApp app = (TelecomApp) getApplication();
-        PhoneAccountRegistrar registry = app.getPhoneAccountRegistrar();
+        PhoneAccountRegistrar registry = TelecomGlobals.getInstance().getPhoneAccountRegistrar();
+        if (registry == null) {
+            return null;
+        }
+
         Call call = getCallsManager().getForegroundCall();
 
         PhoneAccount account = null;
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index a0a8a62..8a85f2c 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -22,6 +22,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Trace;
 import android.provider.ContactsContract.Contacts;
 import android.telecom.CallState;
 import android.telecom.DisconnectCause;
@@ -30,7 +31,6 @@
 import android.telecom.ParcelableConnection;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
-import android.telecom.PhoneCapabilities;
 import android.telecom.Response;
 import android.telecom.StatusHints;
 import android.telecom.TelecomManager;
@@ -44,7 +44,6 @@
 import com.android.internal.telephony.CallerInfoAsyncQuery.OnQueryCompleteListener;
 import com.android.internal.telephony.SmsApplication;
 import com.android.server.telecom.ContactsAsyncHelper.OnImageLoadCompleteListener;
-
 import com.android.internal.util.Preconditions;
 
 import java.util.ArrayList;
@@ -74,7 +73,8 @@
         void onFailedUnknownCall(Call call);
         void onRingbackRequested(Call call, boolean ringbackRequested);
         void onPostDialWait(Call call, String remaining);
-        void onCallCapabilitiesChanged(Call call);
+        void onPostDialChar(Call call, char nextChar);
+        void onConnectionCapabilitiesChanged(Call call);
         void onParentChanged(Call call);
         void onChildrenChanged(Call call);
         void onCannedSmsResponsesLoaded(Call call);
@@ -89,6 +89,7 @@
         void onConnectionManagerPhoneAccountChanged(Call call);
         void onPhoneAccountChanged(Call call);
         void onConferenceableCallsChanged(Call call);
+        boolean onCanceledViaNewOutgoingCallBroadcast(Call call);
     }
 
     abstract static class ListenerBase implements Listener {
@@ -109,7 +110,9 @@
         @Override
         public void onPostDialWait(Call call, String remaining) {}
         @Override
-        public void onCallCapabilitiesChanged(Call call) {}
+        public void onPostDialChar(Call call, char nextChar) {}
+        @Override
+        public void onConnectionCapabilitiesChanged(Call call) {}
         @Override
         public void onParentChanged(Call call) {}
         @Override
@@ -138,6 +141,10 @@
         public void onPhoneAccountChanged(Call call) {}
         @Override
         public void onConferenceableCallsChanged(Call call) {}
+        @Override
+        public boolean onCanceledViaNewOutgoingCallBroadcast(Call call) {
+            return false;
+        }
     }
 
     private static final OnQueryCompleteListener sCallerInfoQueryListener =
@@ -182,7 +189,13 @@
      * The time this call was created. Beyond logging and such, may also be used for bookkeeping
      * and specifically for marking certain call attempts as failed attempts.
      */
-    private final long mCreationTimeMillis = System.currentTimeMillis();
+    private long mCreationTimeMillis = System.currentTimeMillis();
+
+    /** The time this call was made active. */
+    private long mConnectTimeMillis = 0;
+
+    /** The time this call was disconnected. */
+    private long mDisconnectTimeMillis = 0;
 
     /** The gateway information associated with this call. This stores the original call handle
      * that the user is attempting to connect to via the gateway, the actual handle to dial in
@@ -198,8 +211,6 @@
 
     private final List<Call> mConferenceableCalls = new ArrayList<>();
 
-    private long mConnectTimeMillis = 0;
-
     /** The state of the call. */
     private int mState;
 
@@ -268,7 +279,7 @@
     /** Whether direct-to-voicemail query is pending. */
     private boolean mDirectToVoicemailQueryPending;
 
-    private int mCallCapabilities;
+    private int mConnectionCapabilities;
 
     private boolean mIsConference = false;
 
@@ -335,6 +346,37 @@
         maybeLoadCannedSmsResponses();
     }
 
+    /**
+     * Persists the specified parameters and initializes the new instance.
+     *
+     * @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.
+     * @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.
+     * @param isIncoming True if this is an incoming call.
+     * @param connectTimeMillis The connection time of the call.
+     */
+    Call(
+            Context context,
+            ConnectionServiceRepository repository,
+            Uri handle,
+            GatewayInfo gatewayInfo,
+            PhoneAccountHandle connectionManagerPhoneAccountHandle,
+            PhoneAccountHandle targetPhoneAccountHandle,
+            boolean isIncoming,
+            boolean isConference,
+            long connectTimeMillis) {
+        this(context, repository, handle, gatewayInfo, connectionManagerPhoneAccountHandle,
+                targetPhoneAccountHandle, isIncoming, isConference);
+
+        mConnectTimeMillis = connectTimeMillis;
+    }
+
     void addListener(Listener listener) {
         mListeners.add(listener);
     }
@@ -361,13 +403,35 @@
                 getVideoState(),
                 getChildCalls().size(),
                 getParentCall() != null,
-                PhoneCapabilities.toString(getCallCapabilities()));
+                Connection.capabilitiesToString(getConnectionCapabilities()));
     }
 
     int getState() {
         return mState;
     }
 
+    private boolean shouldContinueProcessingAfterDisconnect() {
+        // Stop processing once the call is active.
+        if (!CreateConnectionTimeout.isCallBeingPlaced(this)) {
+            return false;
+        }
+
+        // Make sure that there are additional connection services to process.
+        if (mCreateConnectionProcessor == null
+            || !mCreateConnectionProcessor.isProcessingComplete()
+            || !mCreateConnectionProcessor.hasMorePhoneAccounts()) {
+            return false;
+        }
+
+        if (mDisconnectCause == null) {
+            return false;
+        }
+
+        // Continue processing if the current attempt failed or timed out.
+        return mDisconnectCause.getCode() == DisconnectCause.ERROR ||
+            mCreateConnectionProcessor.isCallTimedOut();
+    }
+
     /**
      * Sets the call state. Although there exists the notion of appropriate state transitions
      * (see {@link CallState}), in practice those expectations break down when cellular systems
@@ -377,10 +441,28 @@
     void setState(int newState) {
         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;
+            }
+
             mState = newState;
             maybeLoadCannedSmsResponses();
 
-            if (mState == CallState.DISCONNECTED) {
+            if (mState == CallState.ACTIVE || mState == CallState.ON_HOLD) {
+                if (mConnectTimeMillis == 0) {
+                    // We check to see if mConnectTime is already set to prevent the
+                    // call from resetting active time when it goes in and out of
+                    // ACTIVE/ON_HOLD
+                    mConnectTimeMillis = System.currentTimeMillis();
+                }
+
+                // We're clearly not disconnected, so reset the disconnected time.
+                mDisconnectTimeMillis = 0;
+            } else if (mState == CallState.DISCONNECTED) {
+                mDisconnectTimeMillis = System.currentTimeMillis();
                 setLocallyDisconnecting(false);
                 fixParentAfterDisconnect();
             }
@@ -417,8 +499,20 @@
 
     void setHandle(Uri handle, int presentation) {
         if (!Objects.equals(handle, mHandle) || presentation != mHandlePresentation) {
-            mHandle = handle;
             mHandlePresentation = presentation;
+            if (mHandlePresentation == TelecomManager.PRESENTATION_RESTRICTED ||
+                    mHandlePresentation == TelecomManager.PRESENTATION_UNKNOWN) {
+                mHandle = null;
+            } else {
+                mHandle = handle;
+                if (mHandle != null && !PhoneAccount.SCHEME_VOICEMAIL.equals(mHandle.getScheme())
+                        && TextUtils.isEmpty(mHandle.getSchemeSpecificPart())) {
+                    // If the number is actually empty, set it to null, unless this is a
+                    // SCHEME_VOICEMAIL uri which always has an empty number.
+                    mHandle = null;
+                }
+            }
+
             mIsEmergencyCall = mHandle != null && PhoneNumberUtils.isLocalEmergencyNumber(mContext,
                     mHandle.getSchemeSpecificPart());
             startCallerInfoLookup();
@@ -533,7 +627,21 @@
      *     mCreationTimeMillis.
      */
     long getAgeMillis() {
-        return System.currentTimeMillis() - mCreationTimeMillis;
+        if (mState == CallState.DISCONNECTED &&
+                (mDisconnectCause.getCode() == DisconnectCause.REJECTED ||
+                 mDisconnectCause.getCode() == DisconnectCause.MISSED)) {
+            // Rejected and missed calls have no age. They're immortal!!
+            return 0;
+        } else if (mConnectTimeMillis == 0) {
+            // Age is measured in the amount of time the call was active. A zero connect time
+            // indicates that we never went active, so return 0 for the age.
+            return 0;
+        } else if (mDisconnectTimeMillis == 0) {
+            // We connected, but have not yet disconnected
+            return System.currentTimeMillis() - mConnectTimeMillis;
+        }
+
+        return mDisconnectTimeMillis - mConnectTimeMillis;
     }
 
     /**
@@ -544,28 +652,29 @@
         return mCreationTimeMillis;
     }
 
+    void setCreationTimeMillis(long time) {
+        mCreationTimeMillis = time;
+    }
+
     long getConnectTimeMillis() {
         return mConnectTimeMillis;
     }
 
-    void setConnectTimeMillis(long connectTimeMillis) {
-        mConnectTimeMillis = connectTimeMillis;
+    int getConnectionCapabilities() {
+        return mConnectionCapabilities;
     }
 
-    int getCallCapabilities() {
-        return mCallCapabilities;
+    void setConnectionCapabilities(int connectionCapabilities) {
+        setConnectionCapabilities(connectionCapabilities, false /* forceUpdate */);
     }
 
-    void setCallCapabilities(int callCapabilities) {
-        setCallCapabilities(callCapabilities, false /* forceUpdate */);
-    }
-
-    void setCallCapabilities(int callCapabilities, boolean forceUpdate) {
-        Log.v(this, "setCallCapabilities: %s", PhoneCapabilities.toString(callCapabilities));
-        if (forceUpdate || mCallCapabilities != callCapabilities) {
-           mCallCapabilities = callCapabilities;
+    void setConnectionCapabilities(int connectionCapabilities, boolean forceUpdate) {
+        Log.v(this, "setConnectionCapabilities: %s", Connection.capabilitiesToString(
+                connectionCapabilities));
+        if (forceUpdate || mConnectionCapabilities != connectionCapabilities) {
+           mConnectionCapabilities = connectionCapabilities;
             for (Listener l : mListeners) {
-                l.onCallCapabilitiesChanged(this);
+                l.onConnectionCapabilitiesChanged(this);
             }
         }
     }
@@ -668,12 +777,11 @@
             CallIdMapper idMapper,
             ParcelableConnection connection) {
         Log.v(this, "handleCreateConnectionSuccessful %s", connection);
-        mCreateConnectionProcessor = null;
         setTargetPhoneAccount(connection.getPhoneAccount());
         setHandle(connection.getHandle(), connection.getHandlePresentation());
         setCallerDisplayName(
                 connection.getCallerDisplayName(), connection.getCallerDisplayNamePresentation());
-        setCallCapabilities(connection.getCapabilities());
+        setConnectionCapabilities(connection.getConnectionCapabilities());
         setVideoProvider(connection.getVideoProvider());
         setVideoState(connection.getVideoState());
         setRingbackRequested(connection.isRingbackRequested());
@@ -710,7 +818,6 @@
 
     @Override
     public void handleCreateConnectionFailure(DisconnectCause disconnectCause) {
-        mCreateConnectionProcessor = null;
         clearConnectionService();
         setDisconnectCause(disconnectCause);
         CallsManager.getInstance().markCallAsDisconnected(this, disconnectCause);
@@ -754,17 +861,21 @@
         }
     }
 
+    void disconnect() {
+        disconnect(false);
+    }
+
     /**
      * Attempts to disconnect the call through the connection service.
      */
-    void disconnect() {
+    void disconnect(boolean wasViaNewOutgoingCallBroadcaster) {
         // Track that the call is now locally disconnecting.
         setLocallyDisconnecting(true);
 
         if (mState == CallState.NEW || mState == CallState.PRE_DIAL_WAIT ||
                 mState == CallState.CONNECTING) {
             Log.v(this, "Aborting call %s", this);
-            abort();
+            abort(wasViaNewOutgoingCallBroadcaster);
         } else if (mState != CallState.ABORTED && mState != CallState.DISCONNECTED) {
             if (mConnectionService == null) {
                 Log.e(this, new Exception(), "disconnect() request on a call without a"
@@ -780,11 +891,31 @@
         }
     }
 
-    void abort() {
-        if (mCreateConnectionProcessor != null) {
+    void abort(boolean wasViaNewOutgoingCallBroadcaster) {
+        if (mCreateConnectionProcessor != null &&
+                !mCreateConnectionProcessor.isProcessingComplete()) {
             mCreateConnectionProcessor.abort();
         } else if (mState == CallState.NEW || mState == CallState.PRE_DIAL_WAIT
                 || mState == CallState.CONNECTING) {
+            if (wasViaNewOutgoingCallBroadcaster) {
+                // If the cancelation was from NEW_OUTGOING_CALL, then we do not automatically
+                // destroy the call.  Instead, we announce the cancelation and CallsManager handles
+                // it through a timer. Since apps often cancel calls through NEW_OUTGOING_CALL and
+                // then re-dial them quickly using a gateway, allowing the first call to end
+                // causes jank. This timeout allows CallsManager to transition the first call into
+                // the second call so that in-call only ever sees a single call...eliminating the
+                // jank altogether.
+                for (Listener listener : mListeners) {
+                    if (listener.onCanceledViaNewOutgoingCallBroadcast(this)) {
+                        // The first listener to handle this wins. A return value of true means that
+                        // the listener will handle the disconnection process later and so we
+                        // should not continue it here.
+                        setLocallyDisconnecting(false);
+                        return;
+                    }
+                }
+            }
+
             handleCreateConnectionFailure(new DisconnectCause(DisconnectCause.CANCELED));
         } else {
             Log.v(this, "Cannot abort a call which isn't either PRE_DIAL_WAIT or CONNECTING");
@@ -893,6 +1024,12 @@
         }
     }
 
+    void onPostDialChar(char nextChar) {
+        for (Listener l : mListeners) {
+            l.onPostDialChar(this, nextChar);
+        }
+    }
+
     void postDialContinue(boolean proceed) {
         mConnectionService.onPostDialContinue(this, proceed);
     }
@@ -916,7 +1053,7 @@
     void mergeConference() {
         if (mConnectionService == null) {
             Log.w(this, "merging conference calls without a connection service.");
-        } else if (can(PhoneCapabilities.MERGE_CONFERENCE)) {
+        } else if (can(Connection.CAPABILITY_MERGE_CONFERENCE)) {
             mConnectionService.mergeConference(this);
             mWasConferencePreviouslyMerged = true;
         }
@@ -925,7 +1062,7 @@
     void swapConference() {
         if (mConnectionService == null) {
             Log.w(this, "swapping conference calls without a connection service.");
-        } else if (can(PhoneCapabilities.SWAP_CONFERENCE)) {
+        } else if (can(Connection.CAPABILITY_SWAP_CONFERENCE)) {
             mConnectionService.swapConference(this);
             switch (mChildCalls.size()) {
                 case 1:
@@ -983,7 +1120,7 @@
     }
 
     boolean can(int capability) {
-        return (mCallCapabilities & capability) == capability;
+        return (mConnectionCapabilities & capability) == capability;
     }
 
     private void addChildCall(Call call) {
@@ -1123,6 +1260,7 @@
      * @param token The token used with this query.
      */
     private void setCallerInfo(CallerInfo callerInfo, int token) {
+        Trace.beginSection("setCallerInfo");
         Preconditions.checkNotNull(callerInfo);
 
         if (mQueryToken == token) {
@@ -1147,6 +1285,7 @@
 
             processDirectToVoicemail();
         }
+        Trace.endSection();
     }
 
     CallerInfo getCallerInfo() {
diff --git a/src/com/android/server/telecom/CallActivity.java b/src/com/android/server/telecom/CallActivity.java
index 7022327..37e24f6 100644
--- a/src/com/android/server/telecom/CallActivity.java
+++ b/src/com/android/server/telecom/CallActivity.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.telecom.PhoneAccount;
@@ -85,8 +86,6 @@
                 Intent.ACTION_CALL_PRIVILEGED.equals(action) ||
                 Intent.ACTION_CALL_EMERGENCY.equals(action)) {
             processOutgoingCallIntent(intent);
-        } else if (TelecomManager.ACTION_INCOMING_CALL.equals(action)) {
-            processIncomingCallIntent(intent);
         }
     }
 
@@ -124,20 +123,7 @@
         }
 
         intent.putExtra(CallReceiver.KEY_IS_DEFAULT_DIALER, isDefaultDialer());
-
-        if (UserHandle.myUserId() == UserHandle.USER_OWNER) {
-            CallReceiver.processOutgoingCallIntent(getApplicationContext(), intent);
-        } else {
-            sendBroadcastToReceiver(intent, false /* isIncoming */);
-        }
-    }
-
-    private void processIncomingCallIntent(Intent intent) {
-        if (UserHandle.myUserId() == UserHandle.USER_OWNER) {
-            CallReceiver.processIncomingCallIntent(intent);
-        } else {
-            sendBroadcastToReceiver(intent, true /* isIncoming */);
-        }
+        sendBroadcastToReceiver(intent);
     }
 
     private boolean isDefaultDialer() {
@@ -166,11 +152,11 @@
     /**
      * Trampolines the intent to the broadcast receiver that runs only as the primary user.
      */
-    private boolean sendBroadcastToReceiver(Intent intent, boolean incoming) {
-        intent.putExtra(CallReceiver.KEY_IS_INCOMING_CALL, incoming);
+    private boolean sendBroadcastToReceiver(Intent intent) {
+        intent.putExtra(CallReceiver.KEY_IS_INCOMING_CALL, false);
         intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
         intent.setClass(this, CallReceiver.class);
-        Log.d(this, "Sending broadcast as user to CallReceiver- isIncoming: %s", incoming);
+        Log.d(this, "Sending broadcast as user to CallReceiver");
         sendBroadcastAsUser(intent, UserHandle.OWNER);
         return true;
     }
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index a89dcea..b555f85 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -21,6 +21,7 @@
 import android.telecom.AudioState;
 import android.telecom.CallState;
 
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 
 import java.util.Objects;
@@ -43,6 +44,7 @@
     private boolean mIsTonePlaying;
     private boolean mWasSpeakerOn;
     private int mMostRecentlyUsedMode = AudioManager.MODE_IN_CALL;
+    private Call mCallToSpeedUpMTAudio = null;
 
     CallAudioManager(Context context, StatusBarNotifier statusBarNotifier,
             WiredHeadsetManager wiredHeadsetManager) {
@@ -67,7 +69,8 @@
         if (hasFocus() && getForegroundCall() == call) {
             if (!call.isIncoming()) {
                 // Unmute new outgoing call.
-                setSystemAudioState(false, mAudioState.route, mAudioState.supportedRouteMask);
+                setSystemAudioState(false, mAudioState.getRoute(),
+                        mAudioState.getSupportedRouteMask());
             }
         }
     }
@@ -92,7 +95,7 @@
 
     @Override
     public void onIncomingCallAnswered(Call call) {
-        int route = mAudioState.route;
+        int route = mAudioState.getRoute();
 
         // We do two things:
         // (1) If this is the first call, then we can to turn on bluetooth if available.
@@ -103,7 +106,13 @@
             route = AudioState.ROUTE_BLUETOOTH;
         }
 
-        setSystemAudioState(false /* isMute */, route, mAudioState.supportedRouteMask);
+        setSystemAudioState(false /* isMute */, route, mAudioState.getSupportedRouteMask());
+
+        if (call.can(android.telecom.Call.Details.CAPABILITY_SPEED_UP_MT_AUDIO)) {
+            Log.v(this, "Speed up audio setup for IMS MT call.");
+            mCallToSpeedUpMTAudio = call;
+            updateAudioStreamAndMode();
+        }
     }
 
     @Override
@@ -129,21 +138,40 @@
             return;
         }
 
-        int newRoute = AudioState.ROUTE_EARPIECE;
+        boolean isCurrentlyWiredHeadset = mAudioState.getRoute() == AudioState.ROUTE_WIRED_HEADSET;
+
+        int newRoute = mAudioState.getRoute();  // start out with existing route
         if (newIsPluggedIn) {
             newRoute = AudioState.ROUTE_WIRED_HEADSET;
-        } else if (mWasSpeakerOn) {
+        } else if (isCurrentlyWiredHeadset) {
             Call call = getForegroundCall();
-            if (call != null && call.isAlive()) {
-                // Restore the speaker state.
-                newRoute = AudioState.ROUTE_SPEAKER;
+            boolean hasLiveCall = call != null && call.isAlive();
+
+            if (hasLiveCall) {
+                // In order of preference when a wireless headset is unplugged.
+                if (mWasSpeakerOn) {
+                    newRoute = AudioState.ROUTE_SPEAKER;
+                } else {
+                    newRoute = AudioState.ROUTE_EARPIECE;
+                }
+
+                // We don't automatically connect to bluetooth when user unplugs their wired headset
+                // and they were previously using the wired. Wired and earpiece are effectively the
+                // same choice in that they replace each other as an option when wired headsets
+                // are plugged in and out. This means that keeping it earpiece is a bit more
+                // consistent with the status quo.  Bluetooth also has more danger associated with
+                // choosing it in the wrong curcumstance because bluetooth devices can be
+                // semi-public (like in a very-occupied car) where earpiece doesn't carry that risk.
             }
         }
-        setSystemAudioState(mAudioState.isMuted, newRoute, calculateSupportedRoutes());
+
+        // We need to call this every time even if we do not change the route because the supported
+        // routes changed either to include or not include WIRED_HEADSET.
+        setSystemAudioState(mAudioState.isMuted(), newRoute, calculateSupportedRoutes());
     }
 
     void toggleMute() {
-        mute(!mAudioState.isMuted);
+        mute(!mAudioState.isMuted());
     }
 
     void mute(boolean shouldMute) {
@@ -159,8 +187,9 @@
             Log.v(this, "ignoring mute for emergency call");
         }
 
-        if (mAudioState.isMuted != shouldMute) {
-            setSystemAudioState(shouldMute, mAudioState.route, mAudioState.supportedRouteMask);
+        if (mAudioState.isMuted() != shouldMute) {
+            setSystemAudioState(shouldMute, mAudioState.getRoute(),
+                    mAudioState.getSupportedRouteMask());
         }
     }
 
@@ -178,19 +207,20 @@
         Log.v(this, "setAudioRoute, route: %s", AudioState.audioRouteToString(route));
 
         // Change ROUTE_WIRED_OR_EARPIECE to a single entry.
-        int newRoute = selectWiredOrEarpiece(route, mAudioState.supportedRouteMask);
+        int newRoute = selectWiredOrEarpiece(route, mAudioState.getSupportedRouteMask());
 
         // If route is unsupported, do nothing.
-        if ((mAudioState.supportedRouteMask | newRoute) == 0) {
+        if ((mAudioState.getSupportedRouteMask() | newRoute) == 0) {
             Log.wtf(this, "Asking to set to a route that is unsupported: %d", newRoute);
             return;
         }
 
-        if (mAudioState.route != newRoute) {
+        if (mAudioState.getRoute() != newRoute) {
             // Remember the new speaker state so it can be restored when the user plugs and unplugs
             // a headset.
             mWasSpeakerOn = newRoute == AudioState.ROUTE_SPEAKER;
-            setSystemAudioState(mAudioState.isMuted, newRoute, mAudioState.supportedRouteMask);
+            setSystemAudioState(mAudioState.isMuted(), newRoute,
+                    mAudioState.getSupportedRouteMask());
         }
     }
 
@@ -229,16 +259,16 @@
         }
 
         int supportedRoutes = calculateSupportedRoutes();
-        int newRoute = mAudioState.route;
+        int newRoute = mAudioState.getRoute();
         if (bluetoothManager.isBluetoothAudioConnectedOrPending()) {
             newRoute = AudioState.ROUTE_BLUETOOTH;
-        } else if (mAudioState.route == AudioState.ROUTE_BLUETOOTH) {
+        } else if (mAudioState.getRoute() == AudioState.ROUTE_BLUETOOTH) {
             newRoute = selectWiredOrEarpiece(AudioState.ROUTE_WIRED_OR_EARPIECE, supportedRoutes);
             // Do not switch to speaker when bluetooth disconnects.
             mWasSpeakerOn = false;
         }
 
-        setSystemAudioState(mAudioState.isMuted, newRoute, supportedRoutes);
+        setSystemAudioState(mAudioState.isMuted(), newRoute, supportedRoutes);
     }
 
     boolean isBluetoothAudioOn() {
@@ -251,14 +281,18 @@
 
     private void saveAudioState(AudioState audioState) {
         mAudioState = audioState;
-        mStatusBarNotifier.notifyMute(mAudioState.isMuted);
-        mStatusBarNotifier.notifySpeakerphone(mAudioState.route == AudioState.ROUTE_SPEAKER);
+        mStatusBarNotifier.notifyMute(mAudioState.isMuted());
+        mStatusBarNotifier.notifySpeakerphone(mAudioState.getRoute() == AudioState.ROUTE_SPEAKER);
     }
 
     private void onCallUpdated(Call call) {
         boolean wasNotVoiceCall = mAudioFocusStreamType != AudioManager.STREAM_VOICE_CALL;
         updateAudioStreamAndMode();
 
+        if (call != null && call.getState() == CallState.ACTIVE &&
+                            call == mCallToSpeedUpMTAudio) {
+            mCallToSpeedUpMTAudio = null;
+        }
         // If we transition from not voice call to voice call, we need to set an initial state.
         if (wasNotVoiceCall && mAudioFocusStreamType == AudioManager.STREAM_VOICE_CALL) {
             setInitialAudioState(call, true /* force */);
@@ -283,20 +317,20 @@
         Log.i(this, "changing audio state from %s to %s", oldAudioState, mAudioState);
 
         // Mute.
-        if (mAudioState.isMuted != mAudioManager.isMicrophoneMute()) {
-            Log.i(this, "changing microphone mute state to: %b", mAudioState.isMuted);
-            mAudioManager.setMicrophoneMute(mAudioState.isMuted);
+        if (mAudioState.isMuted() != mAudioManager.isMicrophoneMute()) {
+            Log.i(this, "changing microphone mute state to: %b", mAudioState.isMuted());
+            mAudioManager.setMicrophoneMute(mAudioState.isMuted());
         }
 
         // Audio route.
-        if (mAudioState.route == AudioState.ROUTE_BLUETOOTH) {
+        if (mAudioState.getRoute() == AudioState.ROUTE_BLUETOOTH) {
             turnOnSpeaker(false);
             turnOnBluetooth(true);
-        } else if (mAudioState.route == AudioState.ROUTE_SPEAKER) {
+        } else if (mAudioState.getRoute() == AudioState.ROUTE_SPEAKER) {
             turnOnBluetooth(false);
             turnOnSpeaker(true);
-        } else if (mAudioState.route == AudioState.ROUTE_EARPIECE ||
-                mAudioState.route == AudioState.ROUTE_WIRED_HEADSET) {
+        } else if (mAudioState.getRoute() == AudioState.ROUTE_EARPIECE ||
+                mAudioState.getRoute() == AudioState.ROUTE_WIRED_HEADSET) {
             turnOnBluetooth(false);
             turnOnSpeaker(false);
         }
@@ -335,9 +369,21 @@
         if (mIsRinging) {
             requestAudioFocusAndSetMode(AudioManager.STREAM_RING, AudioManager.MODE_RINGTONE);
         } else {
-            Call call = getForegroundCall();
-            if (call != null) {
-                int mode = call.getIsVoipAudioMode() ?
+            Call foregroundCall = getForegroundCall();
+            Call waitingForAccountSelectionCall =
+                    CallsManager.getInstance().getFirstCallWithState(CallState.PRE_DIAL_WAIT);
+            Call call = CallsManager.getInstance().getForegroundCall();
+            if (foregroundCall == null && call != null && call == mCallToSpeedUpMTAudio) {
+                requestAudioFocusAndSetMode(AudioManager.STREAM_VOICE_CALL,
+                                                         AudioManager.MODE_IN_CALL);
+            } else if (foregroundCall != null && waitingForAccountSelectionCall == null) {
+                // In the case where there is a call that is waiting for account selection,
+                // this will fall back to abandonAudioFocus() below, which temporarily exits
+                // the in-call audio mode. This is to allow TalkBack to speak the "Call with"
+                // dialog information at media volume as opposed to through the earpiece.
+                // Once exiting the "Call with" dialog, the audio focus will return to an in-call
+                // audio mode when this method (updateAudioStreamAndMode) is called again.
+                int mode = foregroundCall.getIsVoipAudioMode() ?
                         AudioManager.MODE_IN_COMMUNICATION : AudioManager.MODE_IN_CALL;
                 requestAudioFocusAndSetMode(AudioManager.STREAM_VOICE_CALL, mode);
             } else if (mIsTonePlaying) {
@@ -359,7 +405,8 @@
     }
 
     private void requestAudioFocusAndSetMode(int stream, int mode) {
-        Log.i(this, "requestAudioFocusAndSetMode, stream: %d -> %d", mAudioFocusStreamType, stream);
+        Log.i(this, "requestAudioFocusAndSetMode, stream: %d -> %d, mode: %d",
+                mAudioFocusStreamType, stream, mode);
         Preconditions.checkState(stream != STREAM_NONE);
 
         // Even if we already have focus, if the stream is different we update audio manager to give
@@ -380,6 +427,7 @@
             Log.v(this, "abandoning audio focus");
             mAudioManager.abandonAudioFocusForCall();
             mAudioFocusStreamType = STREAM_NONE;
+            mCallToSpeedUpMTAudio = null;
         }
     }
 
@@ -466,7 +514,8 @@
         AudioState audioState = getInitialAudioState(call);
         Log.v(this, "setInitialAudioState %s, %s", audioState, call);
         setSystemAudioState(
-                force, audioState.isMuted, audioState.route, audioState.supportedRouteMask);
+                force, audioState.isMuted(), audioState.getRoute(),
+                audioState.getSupportedRouteMask());
     }
 
     private void updateAudioForForegroundCall() {
@@ -485,8 +534,9 @@
         // We ignore any foreground call that is in the ringing state because we deal with ringing
         // calls exclusively through the mIsRinging variable set by {@link Ringer}.
         if (call != null && call.getState() == CallState.RINGING) {
-            call = null;
+            return null;
         }
+
         return call;
     }
 
@@ -498,4 +548,30 @@
     private boolean hasFocus() {
         return mAudioFocusStreamType != STREAM_NONE;
     }
+
+    /**
+     * Dumps the state of the {@link CallAudioManager}.
+     *
+     * @param pw The {@code IndentingPrintWriter} to write the state to.
+     */
+    public void dump(IndentingPrintWriter pw) {
+        pw.println("mAudioState: " + mAudioState);
+        pw.println("mBluetoothManager:");
+        pw.increaseIndent();
+        mBluetoothManager.dump(pw);
+        pw.decreaseIndent();
+        if (mWiredHeadsetManager != null) {
+            pw.println("mWiredHeadsetManager:");
+            pw.increaseIndent();
+            mWiredHeadsetManager.dump(pw);
+            pw.decreaseIndent();
+        } else {
+            pw.println("mWiredHeadsetManager: null");
+        }
+        pw.println("mAudioFocusStreamType: " + mAudioFocusStreamType);
+        pw.println("mIsRinging: " + mIsRinging);
+        pw.println("mIsTonePlaying: " + mIsTonePlaying);
+        pw.println("mWasSpeakerOn: " + mWasSpeakerOn);
+        pw.println("mMostRecentlyUsedMode: " + mMostRecentlyUsedMode);
+    }
 }
diff --git a/src/com/android/server/telecom/CallIdMapper.java b/src/com/android/server/telecom/CallIdMapper.java
index 40a50a5..729db0a 100644
--- a/src/com/android/server/telecom/CallIdMapper.java
+++ b/src/com/android/server/telecom/CallIdMapper.java
@@ -16,11 +16,65 @@
 
 package com.android.server.telecom;
 
-import com.google.common.collect.HashBiMap;
+import android.util.ArrayMap;
+
+import java.util.Map;
 
 /** Utility to map {@link Call} objects to unique IDs. IDs are generated when a call is added. */
 class CallIdMapper {
-    private final HashBiMap<String, Call> mCalls = HashBiMap.create();
+    /**
+     * A very basic bidirectional map.
+     */
+    static class BiMap<K, V> {
+        private Map<K, V> mPrimaryMap = new ArrayMap<>();
+        private Map<V, K> mSecondaryMap = new ArrayMap<>();
+
+        public boolean put(K key, V value) {
+            if (key == null || value == null || mPrimaryMap.containsKey(key) ||
+                    mSecondaryMap.containsKey(value)) {
+                return false;
+            }
+
+            mPrimaryMap.put(key, value);
+            mSecondaryMap.put(value, key);
+            return true;
+        }
+
+        public boolean remove(K key) {
+            if (key == null) {
+                return false;
+            }
+            if (mPrimaryMap.containsKey(key)) {
+                V value = getValue(key);
+                mPrimaryMap.remove(key);
+                mSecondaryMap.remove(value);
+                return true;
+            }
+            return false;
+        }
+
+        public boolean removeValue(V value) {
+            if (value == null) {
+                return false;
+            }
+            return remove(getKey(value));
+        }
+
+        public V getValue(K key) {
+            return mPrimaryMap.get(key);
+        }
+
+        public K getKey(V value) {
+            return mSecondaryMap.get(value);
+        }
+
+        public void clear() {
+            mPrimaryMap.clear();
+            mSecondaryMap.clear();
+        }
+    }
+
+    private final BiMap<String, Call> mCalls = new BiMap<>();
     private final String mCallIdPrefix;
     private static int sIdCount;
 
@@ -55,7 +109,7 @@
             return;
         }
         ThreadUtil.checkOnMainThread();
-        mCalls.inverse().remove(call);
+        mCalls.removeValue(call);
     }
 
     void removeCall(String callId) {
@@ -68,7 +122,7 @@
             return null;
         }
         ThreadUtil.checkOnMainThread();
-        return mCalls.inverse().get(call);
+        return mCalls.getKey(call);
     }
 
     Call getCall(Object objId) {
@@ -82,7 +136,7 @@
             return null;
         }
 
-        return mCalls.get(callId);
+        return mCalls.getValue(callId);
     }
 
     void clear() {
diff --git a/src/com/android/server/telecom/CallLogManager.java b/src/com/android/server/telecom/CallLogManager.java
index 658af10..781f2b1 100755
--- a/src/com/android/server/telecom/CallLogManager.java
+++ b/src/com/android/server/telecom/CallLogManager.java
@@ -98,10 +98,10 @@
 
     @Override
     public void onCallStateChanged(Call call, int oldState, int newState) {
+        int disconnectCause = call.getDisconnectCause().getCode();
         boolean isNewlyDisconnected =
                 newState == CallState.DISCONNECTED || newState == CallState.ABORTED;
-        boolean isCallCanceled = isNewlyDisconnected &&
-                call.getDisconnectCause().getCode() == DisconnectCause.CANCELED;
+        boolean isCallCanceled = isNewlyDisconnected && disconnectCause == DisconnectCause.CANCELED;
 
         // Log newly disconnected calls only if:
         // 1) It was not in the "choose account" phase when disconnected
@@ -114,7 +114,7 @@
             int type;
             if (!call.isIncoming()) {
                 type = Calls.OUTGOING_TYPE;
-            } else if (oldState == CallState.RINGING) {
+            } else if (disconnectCause == DisconnectCause.MISSED) {
                 type = Calls.MISSED_TYPE;
             } else {
                 type = Calls.INCOMING_TYPE;
@@ -140,13 +140,12 @@
 
         Log.d(TAG, "logNumber set to: %s", Log.pii(logNumber));
 
-        final int presentation = getPresentation(call);
         final PhoneAccountHandle accountHandle = call.getTargetPhoneAccount();
 
         // TODO(vt): Once data usage is available, wire it up here.
         int callFeatures = getCallFeatures(call.getVideoStateHistory());
-        logCall(call.getCallerInfo(), logNumber, presentation, callLogType, callFeatures,
-                accountHandle, creationTime, age, null);
+        logCall(call.getCallerInfo(), logNumber, call.getHandlePresentation(),
+                callLogType, callFeatures, accountHandle, creationTime, age, null);
     }
 
     /**
@@ -232,21 +231,6 @@
     }
 
     /**
-     * Gets the presentation from the {@link Call}.
-     *
-     * TODO: There needs to be a way to pass information from
-     * Connection.getNumberPresentation() into a {@link Call} object. Until then, always return
-     * PhoneConstants.PRESENTATION_ALLOWED. On top of that, we might need to introduce
-     * getNumberPresentation to the ContactInfo object as well.
-     *
-     * @param call The call object to retrieve caller details from.
-     * @return The number presentation constant to insert into the call logs.
-     */
-    private int getPresentation(Call call) {
-        return PhoneConstants.PRESENTATION_ALLOWED;
-    }
-
-    /**
      * Adds the call defined by the parameters in the provided AddCallArgs to the CallLogProvider
      * using an AsyncTask to avoid blocking the main thread.
      *
diff --git a/src/com/android/server/telecom/CallReceiver.java b/src/com/android/server/telecom/CallReceiver.java
index 17ca3e5..bdae582 100644
--- a/src/com/android/server/telecom/CallReceiver.java
+++ b/src/com/android/server/telecom/CallReceiver.java
@@ -5,12 +5,15 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
+import android.telecom.VideoProfile;
 import android.telephony.DisconnectCause;
 import android.telephony.PhoneNumberUtils;
+import android.widget.Toast;
 
 /**
  * Single point of entry for all outgoing and incoming calls. {@link CallActivity} serves as a
@@ -29,17 +32,15 @@
     @Override
     public void onReceive(Context context, Intent intent) {
         final boolean isUnknownCall = intent.getBooleanExtra(KEY_IS_UNKNOWN_CALL, false);
-        final boolean isIncomingCall = intent.getBooleanExtra(KEY_IS_INCOMING_CALL, false);
-        Log.i(this, "onReceive - isIncomingCall: %s isUnknownCall: %s", isIncomingCall,
-                isUnknownCall);
+        Log.i(this, "onReceive - isUnknownCall: %s", isUnknownCall);
 
+        Trace.beginSection("processNewCallCallIntent");
         if (isUnknownCall) {
             processUnknownCallIntent(intent);
-        } else if (isIncomingCall) {
-            processIncomingCallIntent(intent);
         } else {
             processOutgoingCallIntent(context, intent);
         }
+        Trace.endSection();
     }
 
     /**
@@ -48,6 +49,10 @@
      * @param intent Call intent containing data about the handle to call.
      */
     static void processOutgoingCallIntent(Context context, Intent intent) {
+        if (shouldPreventDuplicateVideoCall(context, intent)) {
+            return;
+        }
+
         Uri handle = intent.getData();
         String scheme = handle.getScheme();
         String uriString = handle.getSchemeSpecificPart();
@@ -65,7 +70,7 @@
             clientExtras = intent.getBundleExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS);
         }
         if (clientExtras == null) {
-            clientExtras = Bundle.EMPTY;
+            clientExtras = new Bundle();
         }
 
         final boolean isDefaultDialer = intent.getBooleanExtra(KEY_IS_DEFAULT_DIALER, false);
@@ -108,7 +113,7 @@
             clientExtras = intent.getBundleExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS);
         }
         if (clientExtras == null) {
-            clientExtras = Bundle.EMPTY;
+            clientExtras = new Bundle();
         }
 
         Log.d(TAG, "Processing incoming call from connection service [%s]",
@@ -153,4 +158,28 @@
         errorIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         context.startActivityAsUser(errorIntent, UserHandle.CURRENT);
     }
+
+    /**
+     * Whether an outgoing video call should be prevented from going out. Namely, don't allow an
+     * outgoing video call if there is already an ongoing video call. Notify the user if their call
+     * is not sent.
+     *
+     * @return {@code true} if the outgoing call is a video call and should be prevented from going
+     *     out, {@code false} otherwise.
+     */
+    private static boolean shouldPreventDuplicateVideoCall(Context context, Intent intent) {
+        int intentVideoState = intent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
+                VideoProfile.VideoState.AUDIO_ONLY);
+        if (intentVideoState == VideoProfile.VideoState.AUDIO_ONLY
+                || !getCallsManager().hasVideoCall()) {
+            return false;
+        } else {
+            // Display an error toast to the user.
+            Toast.makeText(
+                    context,
+                    context.getResources().getString(R.string.duplicate_video_call_not_allowed),
+                    Toast.LENGTH_LONG).show();
+            return true;
+        }
+    }
 }
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 4fdb8a1..3b7269d 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -17,29 +17,30 @@
 package com.android.server.telecom;
 
 import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Trace;
 import android.provider.CallLog.Calls;
 import android.provider.Settings;
 import android.telecom.AudioState;
 import android.telecom.CallState;
+import android.telecom.Conference;
+import android.telecom.Connection;
 import android.telecom.DisconnectCause;
 import android.telecom.GatewayInfo;
 import android.telecom.ParcelableConference;
+import android.telecom.ParcelableConnection;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
-import android.telecom.PhoneCapabilities;
 import android.telecom.TelecomManager;
+import android.telecom.VideoProfile;
+import android.telephony.PhoneNumberUtils;
 import android.telephony.TelephonyManager;
 
 import com.android.internal.util.IndentingPrintWriter;
 
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableList;
-
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -73,12 +74,13 @@
         void onIsConferencedChanged(Call call);
         void onIsVoipAudioModeChanged(Call call);
         void onVideoStateChanged(Call call);
+        void onCanAddCallChanged(boolean canAddCall);
     }
 
     /**
      * Singleton instance of the {@link CallsManager}, initialized from {@link TelecomService}.
      */
-    private static CallsManager INSTANCE = null;
+    private static CallsManager sInstance = null;
 
     private static final String TAG = "CallsManager";
 
@@ -86,17 +88,18 @@
     private static final int MAXIMUM_HOLD_CALLS = 1;
     private static final int MAXIMUM_RINGING_CALLS = 1;
     private static final int MAXIMUM_OUTGOING_CALLS = 1;
-
-    private static final int[] LIVE_CALL_STATES =
-            {CallState.CONNECTING, CallState.PRE_DIAL_WAIT, CallState.DIALING, CallState.ACTIVE};
+    private static final int MAXIMUM_TOP_LEVEL_CALLS = 2;
 
     private static final int[] OUTGOING_CALL_STATES =
             {CallState.CONNECTING, CallState.PRE_DIAL_WAIT, CallState.DIALING};
 
+    private static final int[] LIVE_CALL_STATES =
+            {CallState.CONNECTING, CallState.PRE_DIAL_WAIT, CallState.DIALING, CallState.ACTIVE};
+
     /**
      * The main call repository. Keeps an instance of all live calls. New incoming and outgoing
      * calls are added to the map and removed when the calls move to the disconnected state.
-    *
+     *
      * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
      * load factor before resizing, 1 means we only expect a single thread to
      * access the map so make only a single shard
@@ -109,6 +112,7 @@
     private final InCallController mInCallController;
     private final CallAudioManager mCallAudioManager;
     private final Ringer mRinger;
+    private final InCallWakeLockController mInCallWakeLockController;
     // For this set initial table size to 16 because we add 13 listeners in
     // the CallsManager constructor.
     private final Set<CallsManagerListener> mListeners = Collections.newSetFromMap(
@@ -123,6 +127,11 @@
     private final PhoneAccountRegistrar mPhoneAccountRegistrar;
     private final MissedCallNotifier mMissedCallNotifier;
     private final Set<Call> mLocallyDisconnectingCalls = new HashSet<>();
+    private final Set<Call> mPendingCallsToDisconnect = new HashSet<>();
+    /* Handler tied to thread in which CallManager was initialized. */
+    private final Handler mHandler = new Handler();
+
+    private boolean mCanAddCall = true;
 
     /**
      * The call the user is currently interacting with. This is the call that should have audio
@@ -130,9 +139,11 @@
      */
     private Call mForegroundCall;
 
+    private Runnable mStopTone;
+
     /** Singleton accessor. */
     static CallsManager getInstance() {
-        return INSTANCE;
+        return sInstance;
     }
 
     /**
@@ -141,7 +152,7 @@
      * @param instance The instance to set.
      */
     static void initialize(CallsManager instance) {
-        INSTANCE = instance;
+        sInstance = instance;
     }
 
     /**
@@ -166,6 +177,7 @@
         mDtmfLocalTonePlayer = new DtmfLocalTonePlayer(context);
         mConnectionServiceRepository = new ConnectionServiceRepository(mPhoneAccountRegistrar,
                 context);
+        mInCallWakeLockController = new InCallWakeLockController(context, this);
 
         mListeners.add(statusBarNotifier);
         mListeners.add(mCallLogManager);
@@ -257,9 +269,43 @@
     }
 
     @Override
+    public void onPostDialChar(final Call call, char nextChar) {
+        if (PhoneNumberUtils.is12Key(nextChar)) {
+            // Play tone if it is one of the dialpad digits, canceling out the previously queued
+            // up stopTone runnable since playing a new tone automatically stops the previous tone.
+            if (mStopTone != null) {
+                mHandler.removeCallbacks(mStopTone);
+            }
+
+            mDtmfLocalTonePlayer.playTone(call, nextChar);
+
+            mStopTone = new Runnable() {
+                @Override
+                public void run() {
+                    // Set a timeout to stop the tone in case there isn't another tone to follow.
+                    mDtmfLocalTonePlayer.stopTone(call);
+                }
+            };
+            mHandler.postDelayed(
+                    mStopTone,
+                    Timeouts.getDelayBetweenDtmfTonesMillis(mContext.getContentResolver()));
+        } else if (nextChar == 0 || nextChar == TelecomManager.DTMF_CHARACTER_WAIT ||
+                nextChar == TelecomManager.DTMF_CHARACTER_PAUSE) {
+            // Stop the tone if a tone is playing, removing any other stopTone callbacks since
+            // the previous tone is being stopped anyway.
+            if (mStopTone != null) {
+                mHandler.removeCallbacks(mStopTone);
+            }
+            mDtmfLocalTonePlayer.stopTone(call);
+        } else {
+            Log.w(this, "onPostDialChar: invalid value %d", nextChar);
+        }
+    }
+
+    @Override
     public void onParentChanged(Call call) {
         // parent-child relationship affects which call should be foreground, so do an update.
-        updateForegroundCall();
+        updateCallsManagerState();
         for (CallsManagerListener listener : mListeners) {
             listener.onIsConferencedChanged(call);
         }
@@ -268,7 +314,7 @@
     @Override
     public void onChildrenChanged(Call call) {
         // parent-child relationship affects which call should be foreground, so do an update.
-        updateForegroundCall();
+        updateCallsManagerState();
         for (CallsManagerListener listener : mListeners) {
             listener.onIsConferencedChanged(call);
         }
@@ -288,8 +334,24 @@
         }
     }
 
-    ImmutableCollection<Call> getCalls() {
-        return ImmutableList.copyOf(mCalls);
+    @Override
+    public boolean onCanceledViaNewOutgoingCallBroadcast(final Call call) {
+        mPendingCallsToDisconnect.add(call);
+        mHandler.postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                if (mPendingCallsToDisconnect.remove(call)) {
+                    Log.i(this, "Delayed disconnection of call: %s", call);
+                    call.disconnect();
+                }
+            }
+        }, Timeouts.getNewOutgoingCallCancelMillis(mContext.getContentResolver()));
+
+        return true;
+    }
+
+    Collection<Call> getCalls() {
+        return Collections.unmodifiableCollection(mCalls);
     }
 
     Call getForegroundCall() {
@@ -313,6 +375,15 @@
         return false;
     }
 
+    boolean hasVideoCall() {
+        for (Call call : mCalls) {
+            if (call.getVideoState() != VideoProfile.VideoState.AUDIO_ONLY) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     AudioState getAudioState() {
         return mCallAudioManager.getAudioState();
     }
@@ -373,13 +444,42 @@
                 // to the existing connection instead of trying to create a new one.
                 true /* isIncoming */,
                 false /* isConference */);
-        call.setConnectTimeMillis(System.currentTimeMillis());
         call.setIsUnknown(true);
         call.setExtras(extras);
         call.addListener(this);
         call.startCreateConnection(mPhoneAccountRegistrar);
     }
 
+    private Call getNewOutgoingCall(Uri handle) {
+        // First check to see if we can reuse any of the calls that are waiting to disconnect.
+        // See {@link Call#abort} and {@link #onCanceledViaNewOutgoingCall} for more information.
+        Call reusedCall = null;
+        for (Call pendingCall : mPendingCallsToDisconnect) {
+            if (reusedCall == null && Objects.equals(pendingCall.getHandle(), handle)) {
+                mPendingCallsToDisconnect.remove(pendingCall);
+                Log.i(this, "Reusing disconnected call %s", pendingCall);
+                reusedCall = pendingCall;
+            } else {
+                pendingCall.disconnect();
+            }
+        }
+        if (reusedCall != null) {
+            return reusedCall;
+        }
+
+        // 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.
+        return new Call(
+                mContext,
+                mConnectionServiceRepository,
+                handle,
+                null /* gatewayInfo */,
+                null /* connectionManagerPhoneAccount */,
+                null /* phoneAccountHandle */,
+                false /* isIncoming */,
+                false /* isConference */);
+    }
+
     /**
      * Kicks off the first steps to creating an outgoing call so that InCallUI can launch.
      *
@@ -389,21 +489,18 @@
      * @param extras The optional extras Bundle passed with the intent used for the incoming call.
      */
     Call startOutgoingCall(Uri handle, PhoneAccountHandle phoneAccountHandle, Bundle extras) {
-        // 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.
-        Call call = new Call(
-                mContext,
-                mConnectionServiceRepository,
-                handle,
-                null /* gatewayInfo */,
-                null /* connectionManagerPhoneAccount */,
-                null /* phoneAccountHandle */,
-                false /* isIncoming */,
-                false /* isConference */);
+        Call call = getNewOutgoingCall(handle);
 
         List<PhoneAccountHandle> accounts =
                 mPhoneAccountRegistrar.getCallCapablePhoneAccounts(handle.getScheme());
 
+        Log.v(this, "startOutgoingCall found accounts = " + accounts);
+
+        if (mForegroundCall != null && mForegroundCall.getTargetPhoneAccount() != null) {
+            // If there is an ongoing call, use the same phone account to place this new call.
+            phoneAccountHandle = mForegroundCall.getTargetPhoneAccount();
+        }
+
         // 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.
@@ -434,6 +531,12 @@
         // a call, or cancel this call altogether.
         if (!isPotentialInCallMMICode && !makeRoomForOutgoingCall(call, isEmergencyCall)) {
             // just cancel at this point.
+            Log.i(this, "No remaining room for outgoing call: %s", call);
+            if (mCalls.contains(call)) {
+                // This call can already exist if it is a reused call,
+                // See {@link #getNewOutgoingCall}.
+                call.disconnect();
+            }
             return null;
         }
 
@@ -453,7 +556,9 @@
         // Do not add the call if it is a potential MMI code.
         if ((isPotentialMMICode(handle) || isPotentialInCallMMICode) && !needsAccountSelection) {
             call.addListener(this);
-        } else {
+        } 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 #getNewOutgoingCall}).
             addCall(call);
         }
 
@@ -532,7 +637,8 @@
             if (mForegroundCall != null && mForegroundCall != call &&
                     (mForegroundCall.isActive() ||
                      mForegroundCall.getState() == CallState.DIALING)) {
-                if (0 == (mForegroundCall.getCallCapabilities() & PhoneCapabilities.HOLD)) {
+                if (0 == (mForegroundCall.getConnectionCapabilities()
+                        & Connection.CAPABILITY_HOLD)) {
                     // 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.
@@ -540,6 +646,13 @@
                         mForegroundCall.disconnect();
                     }
                 } else {
+                    Call heldCall = getHeldCall();
+                    if (heldCall != null) {
+                        Log.v(this, "Disconnecting held call %s before holding active call.",
+                                heldCall);
+                        heldCall.disconnect();
+                    }
+
                     Log.v(this, "Holding active/dialing call %s before answering incoming call %s.",
                             mForegroundCall, call);
                     mForegroundCall.hold();
@@ -665,7 +778,8 @@
         } else {
             Log.d(this, "unholding call: (%s)", call);
             for (Call c : mCalls) {
-                if (c != null && c.isAlive() && c != call) {
+                // Only attempt to hold parent calls and not the individual children.
+                if (c != null && c.isAlive() && c != call && c.getParentCall() == null) {
                     c.hold();
                 }
             }
@@ -743,9 +857,6 @@
     }
 
     void markCallAsActive(Call call) {
-        if (call.getConnectTimeMillis() == 0) {
-            call.setConnectTimeMillis(System.currentTimeMillis());
-        }
         setCallState(call, CallState.ACTIVE);
 
         if (call.getStartWithSpeakerphoneOn()) {
@@ -791,7 +902,10 @@
         if (service != null) {
             for (Call call : mCalls) {
                 if (call.getConnectionService() == service) {
-                    markCallAsDisconnected(call, new DisconnectCause(DisconnectCause.ERROR));
+                    if (call.getState() != CallState.DISCONNECTED) {
+                        markCallAsDisconnected(call, new DisconnectCause(DisconnectCause.ERROR));
+                    }
+                    markCallAsRemoved(call);
                 }
             }
         }
@@ -834,13 +948,9 @@
     }
 
     /**
-     * Checks to see if the specified call is the only high-level call and if so, enable the
-     * "Add-call" button. We allow you to add a second call but not a third or beyond.
-     *
-     * @param call The call to test for add-call.
-     * @return Whether the add-call feature should be enabled for the call.
+     * Returns true if telecom supports adding another top-level call.
      */
-    protected boolean isAddCallCapable(Call call) {
+    boolean canAddCall() {
         boolean isDeviceProvisioned = Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
         if (!isDeviceProvisioned) {
@@ -848,23 +958,25 @@
             return false;
         }
 
-        if (call.getParentCall() != null) {
-            // Never true for child calls.
+        if (getFirstCallWithState(OUTGOING_CALL_STATES) != null) {
             return false;
         }
 
-        // Use canManageConference as a mechanism to check if the call is CDMA.
-        // Disable "Add Call" for CDMA calls which are conference calls.
-        boolean canManageConference = PhoneCapabilities.MANAGE_CONFERENCE
-                == (call.getCallCapabilities() & PhoneCapabilities.MANAGE_CONFERENCE);
-        if (call.isConference() && !canManageConference) {
-            return false;
-        }
+        int count = 0;
+        for (Call call : mCalls) {
+            if (call.isEmergencyCall()) {
+                // We never support add call if one of the calls is an emergency call.
+                return false;
+            } else if (call.getParentCall() == null) {
+                count++;
+            }
 
-        // Loop through all the other calls and there exists a top level (has no parent) call
-        // that is not the specified call, return false.
-        for (Call otherCall : mCalls) {
-            if (call != otherCall && otherCall.getParentCall() == null) {
+            // We do not check states for canAddCall. We treat disconnected calls the same
+            // and wait until they are removed instead. If we didn't count disconnected calls,
+            // we could put InCallServices into a state where they are showing two calls but
+            // also support add-call. Technically it's right, but overall looks better (UI-wise)
+            // and acts better if we wait until the call is removed.
+            if (count >= MAXIMUM_TOP_LEVEL_CALLS) {
                 return false;
             }
         }
@@ -936,6 +1048,14 @@
     Call createConferenceCall(
             PhoneAccountHandle phoneAccount,
             ParcelableConference parcelableConference) {
+
+        // If the parceled conference specifies a connect time, use it; otherwise default to 0,
+        // which is the default value for new Calls.
+        long connectTime =
+                parcelableConference.getConnectTimeMillis() ==
+                        Conference.CONNECT_TIME_NOT_SPECIFIED ? 0 :
+                        parcelableConference.getConnectTimeMillis();
+
         Call call = new Call(
                 mContext,
                 mConnectionServiceRepository,
@@ -944,13 +1064,11 @@
                 null /* connectionManagerPhoneAccount */,
                 phoneAccount,
                 false /* isIncoming */,
-                true /* isConference */);
+                true /* isConference */,
+                connectTime);
 
         setCallState(call, Call.getStateFromConnectionState(parcelableConference.getState()));
-        if (call.getState() == CallState.ACTIVE) {
-            call.setConnectTimeMillis(System.currentTimeMillis());
-        }
-        call.setCallCapabilities(parcelableConference.getCapabilities());
+        call.setConnectionCapabilities(parcelableConference.getConnectionCapabilities());
 
         // TODO: Move this to be a part of addCall()
         call.addListener(this);
@@ -988,20 +1106,28 @@
      * @param call The call to add.
      */
     private void addCall(Call call) {
+        Trace.beginSection("addCall");
         Log.v(this, "addCall(%s)", call);
-
         call.addListener(this);
         mCalls.add(call);
 
         // TODO: Update mForegroundCall prior to invoking
         // onCallAdded for calls which immediately take the foreground (like the first call).
         for (CallsManagerListener listener : mListeners) {
+            if (Log.SYSTRACE_DEBUG) {
+                Trace.beginSection(listener.getClass().toString() + " addCall");
+            }
             listener.onCallAdded(call);
+            if (Log.SYSTRACE_DEBUG) {
+                Trace.endSection();
+            }
         }
-        updateForegroundCall();
+        updateCallsManagerState();
+        Trace.endSection();
     }
 
     private void removeCall(Call call) {
+        Trace.beginSection("removeCall");
         Log.v(this, "removeCall(%s)", call);
 
         call.setParentCall(null);  // need to clean up parent relationship before destroying.
@@ -1017,18 +1143,17 @@
         // Only broadcast changes for calls that are being tracked.
         if (shouldNotify) {
             for (CallsManagerListener listener : mListeners) {
+                if (Log.SYSTRACE_DEBUG) {
+                    Trace.beginSection(listener.getClass().toString() + " onCallRemoved");
+                }
                 listener.onCallRemoved(call);
+                if (Log.SYSTRACE_DEBUG) {
+                    Trace.endSection();
+                }
             }
-            updateForegroundCall();
+            updateCallsManagerState();
         }
-
-        // Now that a call has been removed, other calls may gain new call capabilities (for
-        // example, if only one call is left, it is now add-call capable again). Trigger the
-        // recalculation of the call's current capabilities by forcing an update. (See
-        // InCallController.toParcelableCall()).
-        for (Call otherCall : mCalls) {
-            otherCall.setCallCapabilities(otherCall.getCallCapabilities(), true /* forceUpdate */);
-        }
+        Trace.endSection();
     }
 
     /**
@@ -1054,13 +1179,21 @@
             // unexpected transition occurs.
             call.setState(newState);
 
+            Trace.beginSection("onCallStateChanged");
             // Only broadcast state change for calls that are being tracked.
             if (mCalls.contains(call)) {
                 for (CallsManagerListener listener : mListeners) {
+                    if (Log.SYSTRACE_DEBUG) {
+                        Trace.beginSection(listener.getClass().toString() + " onCallStateChanged");
+                    }
                     listener.onCallStateChanged(call, oldState, newState);
+                    if (Log.SYSTRACE_DEBUG) {
+                        Trace.endSection();
+                    }
                 }
-                updateForegroundCall();
+                updateCallsManagerState();
             }
+            Trace.endSection();
         }
     }
 
@@ -1068,6 +1201,7 @@
      * Checks which call should be visible to the user and have audio focus.
      */
     private void updateForegroundCall() {
+        Trace.beginSection("updateForegroundCall");
         Call newForegroundCall = null;
         for (Call call : mCalls) {
             // TODO: Foreground-ness needs to be explicitly set. No call, regardless
@@ -1098,9 +1232,37 @@
             mForegroundCall = newForegroundCall;
 
             for (CallsManagerListener listener : mListeners) {
+                if (Log.SYSTRACE_DEBUG) {
+                    Trace.beginSection(listener.getClass().toString() + " updateForegroundCall");
+                }
                 listener.onForegroundCallChanged(oldForegroundCall, mForegroundCall);
+                if (Log.SYSTRACE_DEBUG) {
+                    Trace.endSection();
+                }
             }
         }
+        Trace.endSection();
+    }
+
+    private void updateCanAddCall() {
+        boolean newCanAddCall = canAddCall();
+        if (newCanAddCall != mCanAddCall) {
+            mCanAddCall = newCanAddCall;
+            for (CallsManagerListener listener : mListeners) {
+                if (Log.SYSTRACE_DEBUG) {
+                    Trace.beginSection(listener.getClass().toString() + " updateCanAddCall");
+                }
+                listener.onCanAddCallChanged(mCanAddCall);
+                if (Log.SYSTRACE_DEBUG) {
+                    Trace.endSection();
+                }
+            }
+        }
+    }
+
+    private void updateCallsManagerState() {
+        updateForegroundCall();
+        updateCanAddCall();
     }
 
     private boolean isPotentialMMICode(Uri handle) {
@@ -1139,7 +1301,7 @@
         int count = 0;
         for (int state : states) {
             for (Call call : mCalls) {
-                if (call.getState() == state) {
+                if (call.getParentCall() == null && call.getState() == state) {
                     count++;
                 }
             }
@@ -1168,6 +1330,8 @@
             // NOTE: If the amount of live calls changes beyond 1, this logic will probably
             // have to change.
             Call liveCall = getFirstCallWithState(call, LIVE_CALL_STATES);
+            Log.i(this, "makeRoomForOutgoingCall call = " + call + " livecall = " +
+                   liveCall);
 
             if (call == liveCall) {
                 // If the call is already the foreground call, then we are golden.
@@ -1219,7 +1383,7 @@
             }
 
             // Try to hold the live call before attempting the new outgoing call.
-            if (liveCall.can(PhoneCapabilities.HOLD)) {
+            if (liveCall.can(Connection.CAPABILITY_HOLD)) {
                 liveCall.hold();
                 return true;
             }
@@ -1231,13 +1395,41 @@
     }
 
     /**
+     * Creates a new call for an existing connection.
+     *
+     * @param callId The id of the new call.
+     * @param connection The connection information.
+     * @return The new call.
+     */
+    Call createCallForExistingConnection(String callId, ParcelableConnection connection) {
+        Call call = new Call(
+                mContext,
+                mConnectionServiceRepository,
+                connection.getHandle() /* handle */,
+                null /* gatewayInfo */,
+                null /* connectionManagerPhoneAccount */,
+                connection.getPhoneAccount(), /* targetPhoneAccountHandle */
+                false /* isIncoming */,
+                false /* isConference */);
+
+        setCallState(call, Call.getStateFromConnectionState(connection.getState()));
+        call.setConnectionCapabilities(connection.getConnectionCapabilities());
+        call.setCallerDisplayName(connection.getCallerDisplayName(),
+                connection.getCallerDisplayNamePresentation());
+
+        call.addListener(this);
+        addCall(call);
+
+        return call;
+    }
+
+    /**
      * Dumps the state of the {@link CallsManager}.
      *
      * @param pw The {@code IndentingPrintWriter} to write the state to.
      */
     public void dump(IndentingPrintWriter pw) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
-        pw.increaseIndent();
         if (mCalls != null) {
             pw.println("mCalls: ");
             pw.increaseIndent();
@@ -1246,6 +1438,34 @@
             }
             pw.decreaseIndent();
         }
-        pw.decreaseIndent();
+        pw.println("mForegroundCall: " + (mForegroundCall == null ? "none" : mForegroundCall));
+
+        if (mCallAudioManager != null) {
+            pw.println("mCallAudioManager:");
+            pw.increaseIndent();
+            mCallAudioManager.dump(pw);
+            pw.decreaseIndent();
+        }
+
+        if (mTtyManager != null) {
+            pw.println("mTtyManager:");
+            pw.increaseIndent();
+            mTtyManager.dump(pw);
+            pw.decreaseIndent();
+        }
+
+        if (mInCallController != null) {
+            pw.println("mInCallController:");
+            pw.increaseIndent();
+            mInCallController.dump(pw);
+            pw.decreaseIndent();
+        }
+
+        if (mConnectionServiceRepository != null) {
+            pw.println("mConnectionServiceRepository:");
+            pw.increaseIndent();
+            mConnectionServiceRepository.dump(pw);
+            pw.decreaseIndent();
+        }
     }
 }
diff --git a/src/com/android/server/telecom/CallsManagerListenerBase.java b/src/com/android/server/telecom/CallsManagerListenerBase.java
index 93b2a24..ffc5947 100644
--- a/src/com/android/server/telecom/CallsManagerListenerBase.java
+++ b/src/com/android/server/telecom/CallsManagerListenerBase.java
@@ -72,4 +72,8 @@
     @Override
     public void onVideoStateChanged(Call call) {
     }
+
+    @Override
+    public void onCanAddCallChanged(boolean canAddCall) {
+    }
 }
diff --git a/src/com/android/server/telecom/ConnectionServiceRepository.java b/src/com/android/server/telecom/ConnectionServiceRepository.java
index e9a447d..0d73371 100644
--- a/src/com/android/server/telecom/ConnectionServiceRepository.java
+++ b/src/com/android/server/telecom/ConnectionServiceRepository.java
@@ -18,6 +18,10 @@
 
 import android.content.ComponentName;
 import android.content.Context;
+import android.os.UserHandle;
+import android.util.Pair;
+
+import com.android.internal.util.IndentingPrintWriter;
 
 import java.util.HashMap;
 
@@ -26,8 +30,8 @@
  */
 final class ConnectionServiceRepository
         implements ServiceBinder.Listener<ConnectionServiceWrapper> {
-    private final HashMap<ComponentName, ConnectionServiceWrapper> mServiceCache =
-            new HashMap<ComponentName, ConnectionServiceWrapper>();
+    private final HashMap<Pair<ComponentName, UserHandle>, ConnectionServiceWrapper> mServiceCache =
+            new HashMap<>();
     private final PhoneAccountRegistrar mPhoneAccountRegistrar;
     private final Context mContext;
 
@@ -36,16 +40,18 @@
         mContext = context;
     }
 
-    ConnectionServiceWrapper getService(ComponentName componentName) {
-        ConnectionServiceWrapper service = mServiceCache.get(componentName);
+    ConnectionServiceWrapper getService(ComponentName componentName, UserHandle userHandle) {
+        Pair<ComponentName, UserHandle> cacheKey = Pair.create(componentName, userHandle);
+        ConnectionServiceWrapper service = mServiceCache.get(cacheKey);
         if (service == null) {
             service = new ConnectionServiceWrapper(
                     componentName,
                     this,
                     mPhoneAccountRegistrar,
-                    mContext);
+                    mContext,
+                    userHandle);
             service.addListener(this);
-            mServiceCache.put(componentName, service);
+            mServiceCache.put(cacheKey, service);
         }
         return service;
     }
@@ -59,4 +65,19 @@
     public void onUnbind(ConnectionServiceWrapper service) {
         mServiceCache.remove(service.getComponentName());
     }
+
+    /**
+     * Dumps the state of the {@link ConnectionServiceRepository}.
+     *
+     * @param pw The {@code IndentingPrintWriter} to write the state to.
+     */
+    public void dump(IndentingPrintWriter pw) {
+        pw.println("mServiceCache:");
+        pw.increaseIndent();
+        for (Pair<ComponentName, UserHandle> cacheKey : mServiceCache.keySet()) {
+            ComponentName componentName = cacheKey.first;
+            pw.println(componentName);
+        }
+        pw.decreaseIndent();
+    }
 }
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 32c6107..d470737 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -24,6 +24,7 @@
 import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.telecom.AudioState;
 import android.telecom.Connection;
 import android.telecom.ConnectionRequest;
@@ -67,7 +68,7 @@
     private static final int MSG_SET_DISCONNECTED = 5;
     private static final int MSG_SET_ON_HOLD = 6;
     private static final int MSG_SET_RINGBACK_REQUESTED = 7;
-    private static final int MSG_SET_CALL_CAPABILITIES = 8;
+    private static final int MSG_SET_CONNECTION_CAPABILITIES = 8;
     private static final int MSG_SET_IS_CONFERENCED = 9;
     private static final int MSG_ADD_CONFERENCE_CALL = 10;
     private static final int MSG_REMOVE_CALL = 11;
@@ -80,6 +81,8 @@
     private static final int MSG_SET_CALLER_DISPLAY_NAME = 18;
     private static final int MSG_SET_VIDEO_STATE = 19;
     private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 20;
+    private static final int MSG_ADD_EXISTING_CONNECTION = 21;
+    private static final int MSG_ON_POST_DIAL_CHAR = 22;
 
     private final Handler mHandler = new Handler() {
         @Override
@@ -155,13 +158,13 @@
                     }
                     break;
                 }
-                case MSG_SET_CALL_CAPABILITIES: {
+                case MSG_SET_CONNECTION_CAPABILITIES: {
                     call = mCallIdMapper.getCall(msg.obj);
                     if (call != null) {
-                        call.setCallCapabilities(msg.arg1);
+                        call.setConnectionCapabilities(msg.arg1);
                     } else {
                         //Log.w(ConnectionServiceWrapper.this,
-                        //      "setCallCapabilities, unknown call id: %s", msg.obj);
+                        //      "setConnectionCapabilities, unknown call id: %s", msg.obj);
                     }
                     break;
                 }
@@ -208,19 +211,26 @@
                                 hasValidCalls = true;
                             }
                         }
-                        if (!hasValidCalls) {
+                        // But don't bail out if the connection count is 0, because that is a valid
+                        // IMS conference state.
+                        if (!hasValidCalls && parcelableConference.getConnectionIds().size() > 0) {
                             Log.d(this, "Attempting to add a conference with no valid calls");
                             break;
                         }
 
                         // need to create a new Call
+                        PhoneAccountHandle phAcc = null;
+                        if (parcelableConference != null &&
+                                parcelableConference.getPhoneAccount() != null) {
+                            phAcc = parcelableConference.getPhoneAccount();
+                        }
                         Call conferenceCall = mCallsManager.createConferenceCall(
-                                null, parcelableConference);
+                                phAcc, parcelableConference);
                         mCallIdMapper.addCall(conferenceCall, id);
                         conferenceCall.setConnectionService(ConnectionServiceWrapper.this);
 
-                        Log.d(this, "adding children to conference %s",
-                                parcelableConference.getConnectionIds());
+                        Log.d(this, "adding children to conference %s phAcc %s",
+                                parcelableConference.getConnectionIds(), phAcc);
                         for (String callId : parcelableConference.getConnectionIds()) {
                             Call childCall = mCallIdMapper.getCall(callId);
                             Log.d(this, "found child: %s", callId);
@@ -236,7 +246,7 @@
                 case MSG_REMOVE_CALL: {
                     call = mCallIdMapper.getCall(msg.obj);
                     if (call != null) {
-                        if (call.isActive()) {
+                        if (call.isAlive()) {
                             mCallsManager.markCallAsDisconnected(
                                     call, new DisconnectCause(DisconnectCause.REMOTE));
                         } else {
@@ -260,6 +270,21 @@
                     }
                     break;
                 }
+                case MSG_ON_POST_DIAL_CHAR: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        call = mCallIdMapper.getCall(args.arg1);
+                        if (call != null) {
+                            char nextChar = (char) args.argi1;
+                            call.onPostDialChar(nextChar);
+                        } else {
+                            //Log.w(this, "onPostDialChar, unknown call id: %s", args.arg1);
+                        }
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
                 case MSG_QUERY_REMOTE_CALL_SERVICES: {
                     queryRemoteConnectionServices((RemoteServiceCallback) msg.obj);
                     break;
@@ -350,6 +375,19 @@
                     }
                     break;
                 }
+                case MSG_ADD_EXISTING_CONNECTION: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        String callId = (String)args.arg1;
+                        ParcelableConnection connection = (ParcelableConnection)args.arg2;
+                        Call existingCall = mCallsManager.createCallForExistingConnection(callId,
+                                connection);
+                        mCallIdMapper.addCall(existingCall, callId);
+                        existingCall.setConnectionService(ConnectionServiceWrapper.this);
+                    } finally {
+                        args.recycle();
+                    }
+                }
             }
         }
     };
@@ -445,10 +483,10 @@
         }
 
         @Override
-        public void setCallCapabilities(String callId, int callCapabilities) {
-            logIncoming("setCallCapabilities %s %d", callId, callCapabilities);
+        public void setConnectionCapabilities(String callId, int connectionCapabilities) {
+            logIncoming("setConnectionCapabilities %s %d", callId, connectionCapabilities);
             if (mCallIdMapper.isValidCallId(callId) || mCallIdMapper.isValidConferenceId(callId)) {
-                mHandler.obtainMessage(MSG_SET_CALL_CAPABILITIES, callCapabilities, 0, callId)
+                mHandler.obtainMessage(MSG_SET_CONNECTION_CAPABILITIES, connectionCapabilities, 0, callId)
                         .sendToTarget();
             } else {
                 Log.w(this, "ID not valid for setCallCapabilities");
@@ -458,12 +496,10 @@
         @Override
         public void setIsConferenced(String callId, String conferenceCallId) {
             logIncoming("setIsConferenced %s %s", callId, conferenceCallId);
-            if (mCallIdMapper.isValidCallId(callId)) {
-                SomeArgs args = SomeArgs.obtain();
-                args.arg1 = callId;
-                args.arg2 = conferenceCallId;
-                mHandler.obtainMessage(MSG_SET_IS_CONFERENCED, args).sendToTarget();
-            }
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = callId;
+            args.arg2 = conferenceCallId;
+            mHandler.obtainMessage(MSG_SET_IS_CONFERENCED, args).sendToTarget();
         }
 
         @Override
@@ -489,6 +525,17 @@
         }
 
         @Override
+        public void onPostDialChar(String callId, char nextChar) throws RemoteException {
+            logIncoming("onPostDialChar %s %s", callId, nextChar);
+            if (mCallIdMapper.isValidCallId(callId)) {
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = callId;
+                args.argi1 = nextChar;
+                mHandler.obtainMessage(MSG_ON_POST_DIAL_CHAR, args).sendToTarget();
+            }
+        }
+
+        @Override
         public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
             logIncoming("queryRemoteCSs");
             mHandler.obtainMessage(MSG_QUERY_REMOTE_CALL_SERVICES, callback).sendToTarget();
@@ -558,6 +605,15 @@
                 mHandler.obtainMessage(MSG_SET_CONFERENCEABLE_CONNECTIONS, args).sendToTarget();
             }
         }
+
+        @Override
+        public void addExistingConnection(String callId, ParcelableConnection connection) {
+            logIncoming("addExistingConnection  %s %s", callId, connection);
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = callId;
+            args.arg2 = connection;
+            mHandler.obtainMessage(MSG_ADD_EXISTING_CONNECTION, args).sendToTarget();
+        }
     }
 
     private final Adapter mAdapter = new Adapter();
@@ -584,13 +640,15 @@
      * @param connectionServiceRepository Connection service repository.
      * @param phoneAccountRegistrar Phone account registrar
      * @param context The context.
+     * @param userHandle The {@link UserHandle} to use when binding.
      */
     ConnectionServiceWrapper(
             ComponentName componentName,
             ConnectionServiceRepository connectionServiceRepository,
             PhoneAccountRegistrar phoneAccountRegistrar,
-            Context context) {
-        super(ConnectionService.SERVICE_INTERFACE, componentName, context);
+            Context context,
+            UserHandle userHandle) {
+        super(ConnectionService.SERVICE_INTERFACE, componentName, context, userHandle);
         mConnectionServiceRepository = connectionServiceRepository;
         phoneAccountRegistrar.addListener(new PhoneAccountRegistrar.Listener() {
             // TODO -- Upon changes to PhoneAccountRegistrar, need to re-wire connections
@@ -950,7 +1008,8 @@
             PhoneAccount account = mPhoneAccountRegistrar.getPhoneAccount(handle);
             if ((account.getCapabilities() & PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) != 0) {
                 ConnectionServiceWrapper service =
-                        mConnectionServiceRepository.getService(handle.getComponentName());
+                        mConnectionServiceRepository.getService(handle.getComponentName(),
+                                handle.getUserHandle());
                 if (service != null) {
                     simServices.add(service);
                 }
diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java
index fab2679..eec1427 100644
--- a/src/com/android/server/telecom/CreateConnectionProcessor.java
+++ b/src/com/android/server/telecom/CreateConnectionProcessor.java
@@ -17,17 +17,24 @@
 package com.android.server.telecom;
 
 import android.content.Context;
+import android.telecom.CallState;
 import android.telecom.DisconnectCause;
 import android.telecom.ParcelableConnection;
 import android.telecom.Phone;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
+import android.telephony.TelephonyManager;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
 
 // TODO: Needed for move to system service: import com.android.internal.R;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 import java.util.Objects;
 
 /**
@@ -89,6 +96,8 @@
     private DisconnectCause mLastErrorDisconnectCause;
     private final PhoneAccountRegistrar mPhoneAccountRegistrar;
     private final Context mContext;
+    private boolean mShouldUseConnectionManager = true;
+    private CreateConnectionTimeout mTimeout;
 
     CreateConnectionProcessor(
             Call call, ConnectionServiceRepository repository, CreateConnectionResponse response,
@@ -100,8 +109,17 @@
         mContext = context;
     }
 
+    boolean isProcessingComplete() {
+        return mResponse == null;
+    }
+
+    boolean isCallTimedOut() {
+        return mTimeout != null && mTimeout.isCallTimedOut();
+    }
+
     void process() {
         Log.v(this, "process");
+        clearTimeout();
         mAttemptRecords = new ArrayList<>();
         if (mCall.getTargetPhoneAccount() != null) {
             mAttemptRecords.add(new CallAttemptRecord(
@@ -113,6 +131,18 @@
         attemptNextPhoneAccount();
     }
 
+    boolean hasMorePhoneAccounts() {
+        return mAttemptRecordIterator.hasNext();
+    }
+
+    void continueProcessingIfPossible(CreateConnectionResponse response,
+            DisconnectCause disconnectCause) {
+        Log.v(this, "continueProcessingIfPossible");
+        mResponse = response;
+        mLastErrorDisconnectCause = disconnectCause;
+        attemptNextPhoneAccount();
+    }
+
     void abort() {
         Log.v(this, "abort");
 
@@ -120,6 +150,7 @@
         // more services.
         CreateConnectionResponse response = mResponse;
         mResponse = null;
+        clearTimeout();
 
         ConnectionServiceWrapper service = mCall.getConnectionService();
         if (service != null) {
@@ -160,9 +191,11 @@
 
         if (mResponse != null && attempt != null) {
             Log.i(this, "Trying attempt %s", attempt);
+            PhoneAccountHandle phoneAccount = attempt.connectionManagerPhoneAccount;
             ConnectionServiceWrapper service =
                     mRepository.getService(
-                            attempt.connectionManagerPhoneAccount.getComponentName());
+                            phoneAccount.getComponentName(),
+                            phoneAccount.getUserHandle());
             if (service == null) {
                 Log.i(this, "Found no connection service for attempt %s", attempt);
                 attemptNextPhoneAccount();
@@ -170,12 +203,15 @@
                 mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount);
                 mCall.setTargetPhoneAccount(attempt.targetPhoneAccount);
                 mCall.setConnectionService(service);
+                setTimeoutIfNeeded(service, attempt);
+
                 Log.i(this, "Attempting to call from %s", service.getComponentName());
                 service.createConnection(mCall, new Response(service));
             }
         } else {
             Log.v(this, "attemptNextPhoneAccount, no more accounts, failing");
             if (mResponse != null) {
+                clearTimeout();
                 mResponse.handleCreateConnectionFailure(mLastErrorDisconnectCause != null ?
                         mLastErrorDisconnectCause : new DisconnectCause(DisconnectCause.ERROR));
                 mResponse = null;
@@ -184,7 +220,30 @@
         }
     }
 
+    private void setTimeoutIfNeeded(ConnectionServiceWrapper service, CallAttemptRecord attempt) {
+        clearTimeout();
+
+        CreateConnectionTimeout timeout = new CreateConnectionTimeout(
+                mContext, mPhoneAccountRegistrar, service, mCall);
+        if (timeout.isTimeoutNeededForCall(getConnectionServices(mAttemptRecords),
+                attempt.connectionManagerPhoneAccount)) {
+            mTimeout = timeout;
+            timeout.registerTimeout();
+        }
+    }
+
+    private void clearTimeout() {
+        if (mTimeout != null) {
+            mTimeout.unregisterTimeout();
+            mTimeout = null;
+        }
+    }
+
     private boolean shouldSetConnectionManager() {
+        if (!mShouldUseConnectionManager) {
+            return false;
+        }
+
         if (mAttemptRecords.size() == 0) {
             return false;
         }
@@ -223,8 +282,7 @@
             CallAttemptRecord record = new CallAttemptRecord(
                     mPhoneAccountRegistrar.getSimCallManager(),
                     mAttemptRecords.get(0).targetPhoneAccount);
-            Log.v(this, "setConnectionManager, changing %s -> %s",
-                    mAttemptRecords.get(0).targetPhoneAccount, record);
+            Log.v(this, "setConnectionManager, changing %s -> %s", mAttemptRecords.get(0), record);
             mAttemptRecords.set(0, record);
         } else {
             Log.v(this, "setConnectionManager, not changing");
@@ -265,7 +323,7 @@
 
             // Next, add the connection manager account as a backup if it can place emergency calls.
             PhoneAccountHandle callManagerHandle = mPhoneAccountRegistrar.getSimCallManager();
-            if (callManagerHandle != null) {
+            if (mShouldUseConnectionManager && callManagerHandle != null) {
                 PhoneAccount callManager = mPhoneAccountRegistrar
                         .getPhoneAccount(callManagerHandle);
                 if (callManager.hasCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)) {
@@ -284,6 +342,16 @@
         }
     }
 
+    /** Returns all connection services used by the call attempt records. */
+    private static Collection<PhoneAccountHandle> getConnectionServices(
+            List<CallAttemptRecord> records) {
+        HashSet<PhoneAccountHandle> result = new HashSet<>();
+        for (CallAttemptRecord record : records) {
+            result.add(record.connectionManagerPhoneAccount);
+        }
+        return result;
+    }
+
     private class Response implements CreateConnectionResponse {
         private final ConnectionServiceWrapper mService;
 
@@ -304,15 +372,49 @@
                 // in hearing about any more attempts
                 mResponse.handleCreateConnectionSuccess(idMapper, connection);
                 mResponse = null;
+                // If there's a timeout running then don't clear it. The timeout can be triggered
+                // after the call has successfully been created but before it has become active.
             }
         }
 
+        private boolean shouldFallbackToNoConnectionManager(DisconnectCause cause) {
+            PhoneAccountHandle handle = mCall.getConnectionManagerPhoneAccount();
+            if (handle == null || !handle.equals(mPhoneAccountRegistrar.getSimCallManager())) {
+                return false;
+            }
+
+            ConnectionServiceWrapper connectionManager = mCall.getConnectionService();
+            if (connectionManager == null) {
+                return false;
+            }
+
+            if (cause.getCode() == DisconnectCause.CONNECTION_MANAGER_NOT_SUPPORTED) {
+                Log.d(CreateConnectionProcessor.this, "Connection manager declined to handle the "
+                        + "call, falling back to not using a connection manager");
+                return true;
+            }
+
+            if (!connectionManager.isServiceValid("createConnection")) {
+                Log.d(CreateConnectionProcessor.this, "Connection manager unbound while trying "
+                        + "create a connection, falling back to not using a connection manager");
+                return true;
+            }
+
+            return false;
+        }
+
         @Override
         public void handleCreateConnectionFailure(DisconnectCause errorDisconnectCause) {
             // Failure of some sort; record the reasons for failure and try again if possible
             Log.d(CreateConnectionProcessor.this, "Connection failed: (%s)", errorDisconnectCause);
             mLastErrorDisconnectCause = errorDisconnectCause;
-            attemptNextPhoneAccount();
+            if (shouldFallbackToNoConnectionManager(errorDisconnectCause)) {
+                mShouldUseConnectionManager = false;
+                // Restart from the beginning.
+                process();
+            } else {
+                attemptNextPhoneAccount();
+            }
         }
     }
 }
diff --git a/src/com/android/server/telecom/CreateConnectionTimeout.java b/src/com/android/server/telecom/CreateConnectionTimeout.java
new file mode 100644
index 0000000..3f308cc
--- /dev/null
+++ b/src/com/android/server/telecom/CreateConnectionTimeout.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 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.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Handler;
+import android.telecom.CallState;
+import android.telecom.PhoneAccountHandle;
+import android.telephony.TelephonyManager;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+
+import java.util.Collection;
+import java.util.Objects;
+
+/**
+ * Registers a timeout for a call and disconnects the call when the timeout expires.
+ */
+final class CreateConnectionTimeout extends PhoneStateListener implements Runnable {
+    private final Context mContext;
+    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
+    private final ConnectionServiceWrapper mConnectionService;
+    private final Call mCall;
+    private final Handler mHandler = new Handler();
+    private boolean mIsRegistered;
+    private boolean mIsCallTimedOut;
+
+    CreateConnectionTimeout(Context context, PhoneAccountRegistrar phoneAccountRegistrar,
+            ConnectionServiceWrapper service, Call call) {
+        mContext = context;
+        mPhoneAccountRegistrar = phoneAccountRegistrar;
+        mConnectionService = service;
+        mCall = call;
+    }
+
+    boolean isTimeoutNeededForCall(Collection<PhoneAccountHandle> accounts,
+            PhoneAccountHandle currentAccount) {
+        // Non-emergency calls timeout automatically at the radio layer. No need for a timeout here.
+        if (!TelephonyUtil.shouldProcessAsEmergency(mContext, mCall.getHandle())) {
+            return false;
+        }
+
+        // If there's no connection manager to fallback on then there's no point in having a
+        // timeout.
+        PhoneAccountHandle connectionManager = mPhoneAccountRegistrar.getSimCallManager();
+        if (!accounts.contains(connectionManager)) {
+            return false;
+        }
+
+        // No need to add a timeout if the current attempt is over the connection manager.
+        if (Objects.equals(connectionManager, currentAccount)) {
+            return false;
+        }
+
+        // To reduce the number of scenarios where a timeout is needed, only use a timeout if
+        // we're connected to Wi-Fi. This ensures that the fallback connection manager has an
+        // alternate route to place the call. TODO: remove this condition or allow connection
+        // managers to specify transports. See http://b/19199181.
+        if (!isConnectedToWifi()) {
+            return false;
+        }
+
+        Log.d(this, "isTimeoutNeededForCall, returning true");
+        return true;
+    }
+
+    void registerTimeout() {
+        Log.d(this, "registerTimeout");
+        mIsRegistered = true;
+        // First find out the cellular service state. Based on the state we decide whether a timeout
+        // will actually be enforced and if so how long it should be.
+        TelephonyManager telephonyManager =
+            (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+        telephonyManager.listen(this, PhoneStateListener.LISTEN_SERVICE_STATE);
+        telephonyManager.listen(this, 0);
+    }
+
+    void unregisterTimeout() {
+        Log.d(this, "unregisterTimeout");
+        mIsRegistered = false;
+        mHandler.removeCallbacksAndMessages(null);
+    }
+
+    boolean isCallTimedOut() {
+        return mIsCallTimedOut;
+    }
+
+    @Override
+    public void onServiceStateChanged(ServiceState serviceState) {
+        long timeoutLengthMillis = getTimeoutLengthMillis(serviceState);
+        if (!mIsRegistered) {
+            Log.d(this, "onServiceStateChanged, timeout no longer registered, skipping");
+        } else if (timeoutLengthMillis  <= 0) {
+            Log.d(this, "onServiceStateChanged, timeout set to %d, skipping", timeoutLengthMillis);
+        } else if (serviceState.getState() == ServiceState.STATE_IN_SERVICE) {
+            // If cellular service is available then don't bother with a timeout.
+            Log.d(this, "onServiceStateChanged, cellular service available, skipping");
+        } else {
+            mHandler.postDelayed(this, timeoutLengthMillis);
+        }
+    }
+
+    @Override
+    public void run() {
+        if (mIsRegistered && isCallBeingPlaced(mCall)) {
+            Log.d(this, "run, call timed out, calling disconnect");
+            mIsCallTimedOut = true;
+            mConnectionService.disconnect(mCall);
+        }
+    }
+
+    static boolean isCallBeingPlaced(Call call) {
+        int state = call.getState();
+        return state == CallState.NEW
+            || state == CallState.CONNECTING
+            || state == CallState.DIALING;
+    }
+
+    private long getTimeoutLengthMillis(ServiceState serviceState) {
+        // If the radio is off then use a longer timeout. This gives us more time to power on the
+        // radio.
+        if (serviceState.getState() == ServiceState.STATE_POWER_OFF) {
+            return Timeouts.getEmergencyCallTimeoutRadioOffMillis(
+                    mContext.getContentResolver());
+        } else {
+            return Timeouts.getEmergencyCallTimeoutMillis(mContext.getContentResolver());
+        }
+    }
+
+    private boolean isConnectedToWifi() {
+        ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
+            Context.CONNECTIVITY_SERVICE);
+        if (cm != null) {
+          NetworkInfo ni = cm.getActiveNetworkInfo();
+          return ni != null && ni.isConnected() && ni.getType() == ConnectivityManager.TYPE_WIFI;
+        }
+        return false;
+    }
+}
diff --git a/src/com/android/server/telecom/DtmfLocalTonePlayer.java b/src/com/android/server/telecom/DtmfLocalTonePlayer.java
index 6b4b74d..562f8d3 100644
--- a/src/com/android/server/telecom/DtmfLocalTonePlayer.java
+++ b/src/com/android/server/telecom/DtmfLocalTonePlayer.java
@@ -22,9 +22,6 @@
 import android.provider.Settings;
 
 // TODO: Needed for move to system service: import com.android.internal.R;
-import com.google.common.collect.ImmutableMap;
-
-import java.util.Map;
 
 /**
  * Plays DTMF tones locally for the caller to hear. In order to reduce (1) the amount of times we
@@ -33,22 +30,6 @@
  * changes.
  */
 class DtmfLocalTonePlayer extends CallsManagerListenerBase {
-    private static final Map<Character, Integer> TONE_MAP =
-            ImmutableMap.<Character, Integer>builder()
-                    .put('1', ToneGenerator.TONE_DTMF_1)
-                    .put('2', ToneGenerator.TONE_DTMF_2)
-                    .put('3', ToneGenerator.TONE_DTMF_3)
-                    .put('4', ToneGenerator.TONE_DTMF_4)
-                    .put('5', ToneGenerator.TONE_DTMF_5)
-                    .put('6', ToneGenerator.TONE_DTMF_6)
-                    .put('7', ToneGenerator.TONE_DTMF_7)
-                    .put('8', ToneGenerator.TONE_DTMF_8)
-                    .put('9', ToneGenerator.TONE_DTMF_9)
-                    .put('0', ToneGenerator.TONE_DTMF_0)
-                    .put('#', ToneGenerator.TONE_DTMF_P)
-                    .put('*', ToneGenerator.TONE_DTMF_S)
-                    .build();
-
     /** Generator used to actually play the tone. */
     private ToneGenerator mToneGenerator;
 
@@ -85,8 +66,9 @@
             Log.d(this, "playTone: mToneGenerator == null, %c.", c);
         } else {
             Log.d(this, "starting local tone: %c.", c);
-            if (TONE_MAP.containsKey(c)) {
-                mToneGenerator.startTone(TONE_MAP.get(c), -1 /* toneDuration */);
+            int tone = getMappedTone(c);
+            if (tone != ToneGenerator.TONE_UNKNOWN) {
+                mToneGenerator.startTone(tone, -1 /* toneDuration */);
             }
         }
     }
@@ -160,4 +142,15 @@
             }
         }
     }
+
+    private static final int getMappedTone(char digit) {
+        if (digit >= '0' && digit <= '9') {
+            return ToneGenerator.TONE_DTMF_0 + digit - '0';
+        } else if (digit == '#') {
+            return ToneGenerator.TONE_DTMF_P;
+        } else if (digit == '*') {
+            return ToneGenerator.TONE_DTMF_S;
+        }
+        return ToneGenerator.TONE_UNKNOWN;
+    }
 }
diff --git a/src/com/android/server/telecom/InCallAdapter.java b/src/com/android/server/telecom/InCallAdapter.java
index d4af791..e39b5a5 100644
--- a/src/com/android/server/telecom/InCallAdapter.java
+++ b/src/com/android/server/telecom/InCallAdapter.java
@@ -102,8 +102,6 @@
                     break;
                 case MSG_POST_DIAL_CONTINUE:
                     call = mCallIdMapper.getCall(msg.obj);
-                    mCallsManager.postDialContinue(call, msg.arg1 == 1);
-                    call = mCallIdMapper.getCall(msg.obj);
                     if (call != null) {
                         mCallsManager.postDialContinue(call, msg.arg1 == 1);
                     } else {
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index 78553ad..eef75e3 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -28,21 +28,23 @@
 import android.net.Uri;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.telecom.AudioState;
 import android.telecom.CallProperties;
 import android.telecom.CallState;
+import android.telecom.Connection;
 import android.telecom.InCallService;
 import android.telecom.ParcelableCall;
-import android.telecom.PhoneCapabilities;
 import android.telecom.TelecomManager;
 import android.util.ArrayMap;
 
 // TODO: Needed for move to system service: import com.android.internal.R;
 import com.android.internal.telecom.IInCallService;
-import com.google.common.collect.ImmutableCollection;
+import com.android.internal.util.IndentingPrintWriter;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -74,7 +76,7 @@
 
     private final Call.Listener mCallListener = new Call.ListenerBase() {
         @Override
-        public void onCallCapabilitiesChanged(Call call) {
+        public void onConnectionCapabilitiesChanged(Call call) {
             updateCall(call);
         }
 
@@ -150,7 +152,7 @@
     @Override
     public void onCallAdded(Call call) {
         if (mInCallServices.isEmpty()) {
-            bind();
+            bind(call);
         } else {
             Log.i(this, "onCallAdded: %s", call);
             // Track the call if we don't already know about it.
@@ -208,6 +210,19 @@
         }
     }
 
+    @Override
+    public void onCanAddCallChanged(boolean canAddCall) {
+        if (!mInCallServices.isEmpty()) {
+            Log.i(this, "onCanAddCallChanged : %b", canAddCall);
+            for (IInCallService inCallService : mInCallServices.values()) {
+                try {
+                    inCallService.onCanAddCallChanged(canAddCall);
+                } catch (RemoteException ignored) {
+                }
+            }
+        }
+    }
+
     void onPostDialWait(Call call, String remaining) {
         if (!mInCallServices.isEmpty()) {
             Log.i(this, "Calling onPostDialWait, remaining = %s", remaining);
@@ -257,8 +272,10 @@
     /**
      * Binds to the in-call app if not already connected by binding directly to the saved
      * component name of the {@link IInCallService} implementation.
+     *
+     * @param call The newly added call that triggered the binding to the in-call services.
      */
-    private void bind() {
+    private void bind(Call call) {
         ThreadUtil.checkOnMainThread();
         if (mInCallServices.isEmpty()) {
             PackageManager packageManager = mContext.getPackageManager();
@@ -299,8 +316,21 @@
                         Intent intent = new Intent(InCallService.SERVICE_INTERFACE);
                         intent.setComponent(componentName);
 
-                        if (mContext.bindServiceAsUser(intent, inCallServiceConnection,
-                                Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) {
+                        final int bindFlags;
+                        if (mInCallComponentName.equals(componentName)) {
+                            bindFlags = Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT;
+                            if (!call.isIncoming()) {
+                                intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS,
+                                        call.getExtras());
+                                intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
+                                        call.getTargetPhoneAccount());
+                            }
+                        } else {
+                            bindFlags = Context.BIND_AUTO_CREATE;
+                        }
+
+                        if (mContext.bindServiceAsUser(intent, inCallServiceConnection, bindFlags,
+                                UserHandle.CURRENT)) {
                             mServiceConnections.put(componentName, inCallServiceConnection);
                         }
                     }
@@ -319,7 +349,7 @@
      */
     private void onConnected(ComponentName componentName, IBinder service) {
         ThreadUtil.checkOnMainThread();
-
+        Trace.beginSection("onConnected: " + componentName);
         Log.i(this, "onConnected to %s", componentName);
 
         IInCallService inCallService = IInCallService.Stub.asInterface(service);
@@ -330,11 +360,12 @@
             mInCallServices.put(componentName, inCallService);
         } catch (RemoteException e) {
             Log.e(this, e, "Failed to set the in-call adapter.");
+            Trace.endSection();
             return;
         }
 
         // Upon successful connection, send the state of the world to the service.
-        ImmutableCollection<Call> calls = CallsManager.getInstance().getCalls();
+        Collection<Call> calls = CallsManager.getInstance().getCalls();
         if (!calls.isEmpty()) {
             Log.i(this, "Adding %s calls to InCallService after onConnected: %s", calls.size(),
                     componentName);
@@ -350,9 +381,11 @@
                 }
             }
             onAudioStateChanged(null, CallsManager.getInstance().getAudioState());
+            onCanAddCallChanged(CallsManager.getInstance().canAddCall());
         } else {
             unbind();
         }
+        Trace.endSection();
     }
 
     /**
@@ -406,7 +439,6 @@
                 IInCallService inCallService = entry.getValue();
                 ParcelableCall parcelableCall = toParcelableCall(call,
                         componentName.equals(mInCallComponentName) /* includeVideoProvider */);
-
                 Log.v(this, "updateCall %s ==> %s", call, parcelableCall);
                 try {
                     inCallService.updateCall(parcelableCall);
@@ -421,26 +453,35 @@
      *
      * @param call The {@link Call} to parcel.
      * @param includeVideoProvider When {@code true}, the {@link IVideoProvider} is included in the
-     *      parcelled call.  When {@code false}, the {@link IVideoProvider} is not included.
+     *      parceled call.  When {@code false}, the {@link IVideoProvider} is not included.
      * @return The {@link ParcelableCall} containing all call information from the {@link Call}.
      */
     private ParcelableCall toParcelableCall(Call call, boolean includeVideoProvider) {
         String callId = mCallIdMapper.getCallId(call);
 
-        int capabilities = call.getCallCapabilities();
-        if (CallsManager.getInstance().isAddCallCapable(call)) {
-            capabilities |= PhoneCapabilities.ADD_CALL;
-        }
-
-        // Disable mute and add call for emergency calls.
-        if (call.isEmergencyCall()) {
-            capabilities &= ~PhoneCapabilities.MUTE;
-            capabilities &= ~PhoneCapabilities.ADD_CALL;
-        }
-
-        int properties = call.isConference() ? CallProperties.CONFERENCE : 0;
-
         int state = call.getState();
+        int capabilities = convertConnectionToCallCapabilities(call.getConnectionCapabilities());
+
+        // If this is a single-SIM device, the "default SIM" will always be the only SIM.
+        boolean isDefaultSmsAccount =
+                CallsManager.getInstance().getPhoneAccountRegistrar().isUserSelectedSmsPhoneAccount(
+                        call.getTargetPhoneAccount());
+        if (call.isRespondViaSmsCapable() && isDefaultSmsAccount) {
+            capabilities |= android.telecom.Call.Details.CAPABILITY_RESPOND_VIA_TEXT;
+        }
+
+        if (call.isEmergencyCall()) {
+            capabilities = removeCapability(
+                    capabilities, android.telecom.Call.Details.CAPABILITY_MUTE);
+        }
+
+        if (state == CallState.DIALING) {
+            capabilities = removeCapability(
+                    capabilities, android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL);
+            capabilities = removeCapability(
+                    capabilities, android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE);
+        }
+
         if (state == CallState.ABORTED) {
             state = CallState.DISCONNECTED;
         }
@@ -459,17 +500,18 @@
         List<Call> childCalls = call.getChildCalls();
         List<String> childCallIds = new ArrayList<>();
         if (!childCalls.isEmpty()) {
-            connectTimeMillis = Long.MAX_VALUE;
+            long childConnectTimeMillis = Long.MAX_VALUE;
             for (Call child : childCalls) {
                 if (child.getConnectTimeMillis() > 0) {
-                    connectTimeMillis = Math.min(child.getConnectTimeMillis(), connectTimeMillis);
+                    childConnectTimeMillis = Math.min(child.getConnectTimeMillis(),
+                            childConnectTimeMillis);
                 }
                 childCallIds.add(mCallIdMapper.getCallId(child));
             }
-        }
 
-        if (call.isRespondViaSmsCapable()) {
-            capabilities |= PhoneCapabilities.RESPOND_VIA_TEXT;
+            if (childConnectTimeMillis != Long.MAX_VALUE) {
+                connectTimeMillis = childConnectTimeMillis;
+            }
         }
 
         Uri handle = call.getHandlePresentation() == TelecomManager.PRESENTATION_ALLOWED ?
@@ -486,6 +528,7 @@
             }
         }
 
+        int properties = call.isConference() ? CallProperties.CONFERENCE : 0;
         return new ParcelableCall(
                 callId,
                 state,
@@ -509,6 +552,63 @@
                 call.getExtras());
     }
 
+    private static final int[] CONNECTION_TO_CALL_CAPABILITY = new int[] {
+        Connection.CAPABILITY_HOLD,
+        android.telecom.Call.Details.CAPABILITY_HOLD,
+
+        Connection.CAPABILITY_SUPPORT_HOLD,
+        android.telecom.Call.Details.CAPABILITY_SUPPORT_HOLD,
+
+        Connection.CAPABILITY_MERGE_CONFERENCE,
+        android.telecom.Call.Details.CAPABILITY_MERGE_CONFERENCE,
+
+        Connection.CAPABILITY_SWAP_CONFERENCE,
+        android.telecom.Call.Details.CAPABILITY_SWAP_CONFERENCE,
+
+        Connection.CAPABILITY_UNUSED,
+        android.telecom.Call.Details.CAPABILITY_UNUSED,
+
+        Connection.CAPABILITY_RESPOND_VIA_TEXT,
+        android.telecom.Call.Details.CAPABILITY_RESPOND_VIA_TEXT,
+
+        Connection.CAPABILITY_MUTE,
+        android.telecom.Call.Details.CAPABILITY_MUTE,
+
+        Connection.CAPABILITY_MANAGE_CONFERENCE,
+        android.telecom.Call.Details.CAPABILITY_MANAGE_CONFERENCE,
+
+        Connection.CAPABILITY_SUPPORTS_VT_LOCAL,
+        android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL,
+
+        Connection.CAPABILITY_SUPPORTS_VT_REMOTE,
+        android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE,
+
+        Connection.CAPABILITY_HIGH_DEF_AUDIO,
+        android.telecom.Call.Details.CAPABILITY_HIGH_DEF_AUDIO,
+
+        Connection.CAPABILITY_VoWIFI,
+        android.telecom.Call.Details.CAPABILITY_VoWIFI,
+
+        Connection.CAPABILITY_SEPARATE_FROM_CONFERENCE,
+        android.telecom.Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE,
+
+        Connection.CAPABILITY_DISCONNECT_FROM_CONFERENCE,
+        android.telecom.Call.Details.CAPABILITY_DISCONNECT_FROM_CONFERENCE,
+
+        Connection.CAPABILITY_GENERIC_CONFERENCE,
+        android.telecom.Call.Details.CAPABILITY_GENERIC_CONFERENCE
+    };
+
+    private static int convertConnectionToCallCapabilities(int connectionCapabilities) {
+        int callCapabilities = 0;
+        for (int i = 0; i < CONNECTION_TO_CALL_CAPABILITY.length; i += 2) {
+            if ((CONNECTION_TO_CALL_CAPABILITY[i] & connectionCapabilities) != 0) {
+                callCapabilities |= CONNECTION_TO_CALL_CAPABILITY[i + 1];
+            }
+        }
+        return callCapabilities;
+    }
+
     /**
      * Adds the call to the list of calls tracked by the {@link InCallController}.
      * @param call The call to add.
@@ -519,4 +619,32 @@
             call.addListener(mCallListener);
         }
     }
+
+    /**
+     * Removes the specified capability from the set of capabilities bits and returns the new set.
+     */
+    private static int removeCapability(int capabilities, int capability) {
+        return capabilities & ~capability;
+    }
+
+    /**
+     * Dumps the state of the {@link InCallController}.
+     *
+     * @param pw The {@code IndentingPrintWriter} to write the state to.
+     */
+    public void dump(IndentingPrintWriter pw) {
+        pw.println("mInCallServices (InCalls registered):");
+        pw.increaseIndent();
+        for (ComponentName componentName : mInCallServices.keySet()) {
+            pw.println(componentName);
+        }
+        pw.decreaseIndent();
+
+        pw.println("mServiceConnections (InCalls bound):");
+        pw.increaseIndent();
+        for (ComponentName componentName : mServiceConnections.keySet()) {
+            pw.println(componentName);
+        }
+        pw.decreaseIndent();
+    }
 }
diff --git a/src/com/android/server/telecom/InCallWakeLockController.java b/src/com/android/server/telecom/InCallWakeLockController.java
new file mode 100644
index 0000000..d97e171
--- /dev/null
+++ b/src/com/android/server/telecom/InCallWakeLockController.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2014 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.os.PowerManager;
+import android.telecom.CallState;
+
+/**
+ * Handles acquisition and release of wake locks relating to call state.
+ */
+class InCallWakeLockController extends CallsManagerListenerBase {
+
+    private static final String TAG = "InCallWakeLockContoller";
+
+    private final Context mContext;
+    private final PowerManager.WakeLock mFullWakeLock;
+    private final CallsManager mCallsManager;
+
+    InCallWakeLockController(Context context, CallsManager callsManager) {
+        mContext = context;
+        mCallsManager = callsManager;
+
+        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        mFullWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
+
+        callsManager.addListener(this);
+    }
+
+    @Override
+    public void onCallAdded(Call call) {
+        handleWakeLock();
+    }
+
+    @Override
+    public void onCallRemoved(Call call) {
+        handleWakeLock();
+    }
+
+    @Override
+    public void onCallStateChanged(Call call, int oldState, int newState) {
+        handleWakeLock();
+    }
+
+    private void handleWakeLock() {
+        // We grab a full lock as long as there exists a ringing call.
+        Call ringingCall = mCallsManager.getRingingCall();
+        if (ringingCall != null) {
+            mFullWakeLock.acquire();
+            Log.i(this, "Acquiring full wake lock");
+        } else if (mFullWakeLock.isHeld()) {
+            mFullWakeLock.release();
+            Log.i(this, "Releasing full wake lock");
+        }
+    }
+}
diff --git a/src/com/android/server/telecom/Log.java b/src/com/android/server/telecom/Log.java
index 6e3ff6d..3ec8267 100644
--- a/src/com/android/server/telecom/Log.java
+++ b/src/com/android/server/telecom/Log.java
@@ -34,6 +34,7 @@
     private static final String TAG = "Telecom";
 
     public static final boolean FORCE_LOGGING = false; /* STOP SHIP if true */
+    public static final boolean SYSTRACE_DEBUG = false; /* STOP SHIP if true */
     public static final boolean DEBUG = isLoggable(android.util.Log.DEBUG);
     public static final boolean INFO = isLoggable(android.util.Log.INFO);
     public static final boolean VERBOSE = isLoggable(android.util.Log.VERBOSE);
diff --git a/src/com/android/server/telecom/MissedCallNotifier.java b/src/com/android/server/telecom/MissedCallNotifier.java
index 2c1ffb8..2c1e78b 100644
--- a/src/com/android/server/telecom/MissedCallNotifier.java
+++ b/src/com/android/server/telecom/MissedCallNotifier.java
@@ -29,6 +29,7 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.UserHandle;
 import android.provider.CallLog;
 import android.provider.CallLog.Calls;
@@ -45,7 +46,6 @@
 /**
  * Creates a notification for calls that the user missed (neither answered nor rejected).
  * TODO: Make TelephonyManager.clearMissedCalls call into this class.
- * STOPSHIP: Resolve b/13769374 about moving this class to InCall.
  */
 class MissedCallNotifier extends CallsManagerListenerBase {
 
@@ -57,6 +57,14 @@
         Calls.DURATION,
         Calls.TYPE,
     };
+
+    private static final int CALL_LOG_COLUMN_ID = 0;
+    private static final int CALL_LOG_COLUMN_NUMBER = 1;
+    private static final int CALL_LOG_COLUMN_NUMBER_PRESENTATION = 2;
+    private static final int CALL_LOG_COLUMN_DATE = 3;
+    private static final int CALL_LOG_COLUMN_DURATION = 4;
+    private static final int CALL_LOG_COLUMN_TYPE = 5;
+
     private static final int MISSED_CALL_NOTIFICATION_ID = 1;
 
     private final Context mContext;
@@ -84,18 +92,22 @@
 
     /** Clears missed call notification and marks the call log's missed calls as read. */
     void clearMissedCalls() {
-        // Clear the list of new missed calls from the call log.
-        ContentValues values = new ContentValues();
-        values.put(Calls.NEW, 0);
-        values.put(Calls.IS_READ, 1);
-        StringBuilder where = new StringBuilder();
-        where.append(Calls.NEW);
-        where.append(" = 1 AND ");
-        where.append(Calls.TYPE);
-        where.append(" = ?");
-        mContext.getContentResolver().update(Calls.CONTENT_URI, values, where.toString(),
-                new String[]{ Integer.toString(Calls.MISSED_TYPE) });
-
+        AsyncTask.execute(new Runnable() {
+            @Override
+            public void run() {
+                // Clear the list of new missed calls from the call log.
+                ContentValues values = new ContentValues();
+                values.put(Calls.NEW, 0);
+                values.put(Calls.IS_READ, 1);
+                StringBuilder where = new StringBuilder();
+                where.append(Calls.NEW);
+                where.append(" = 1 AND ");
+                where.append(Calls.TYPE);
+                where.append(" = ?");
+                mContext.getContentResolver().update(Calls.CONTENT_URI, values, where.toString(),
+                        new String[]{ Integer.toString(Calls.MISSED_TYPE) });
+            }
+        });
         cancelMissedCallNotification();
     }
 
@@ -280,10 +292,10 @@
                     try {
                         while (cursor.moveToNext()) {
                             // Get data about the missed call from the cursor
-                            final String handleString = cursor.getString(
-                                    cursor.getColumnIndexOrThrow(Calls.NUMBER));
-                            final int presentation = cursor.getInt(cursor.getColumnIndexOrThrow(
-                                    Calls.NUMBER_PRESENTATION));
+                            final String handleString = cursor.getString(CALL_LOG_COLUMN_NUMBER);
+                            final int presentation =
+                                    cursor.getInt(CALL_LOG_COLUMN_NUMBER_PRESENTATION);
+                            final long date = cursor.getLong(CALL_LOG_COLUMN_DATE);
 
                             final Uri handle;
                             if (presentation != Calls.PRESENTATION_ALLOWED
@@ -300,6 +312,7 @@
                                     false);
                             call.setDisconnectCause(new DisconnectCause(DisconnectCause.MISSED));
                             call.setState(CallState.DISCONNECTED);
+                            call.setCreationTimeMillis(date);
 
                             // Listen for the update to the caller information before posting the
                             // notification so that we have the contact info and photo.
diff --git a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
index dbdf79d..c52f2bb 100644
--- a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
+++ b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.content.res.Resources;
 import android.net.Uri;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.telecom.GatewayInfo;
 import android.telecom.PhoneAccount;
@@ -96,6 +97,7 @@
 
         @Override
         public void onReceive(Context context, Intent intent) {
+            Trace.beginSection("onReceiveNewOutgoingCallBroadcast");
             Log.v(this, "onReceive: %s", intent);
 
             // Once the NEW_OUTGOING_CALL broadcast is finished, the resultData is used as the
@@ -114,8 +116,9 @@
 
             if (endEarly) {
                 if (mCall != null) {
-                    mCall.disconnect();
+                    mCall.disconnect(true /* wasViaNewOutgoingCall */);
                 }
+                Trace.endSection();
                 return;
             }
 
@@ -139,6 +142,7 @@
                             false),
                     mIntent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
                             VideoProfile.VideoState.AUDIO_ONLY));
+            Trace.endSection();
         }
     }
 
diff --git a/src/com/android/server/telecom/PhoneAccountBroadcastReceiver.java b/src/com/android/server/telecom/PhoneAccountBroadcastReceiver.java
index 74f63cd..9634eda 100644
--- a/src/com/android/server/telecom/PhoneAccountBroadcastReceiver.java
+++ b/src/com/android/server/telecom/PhoneAccountBroadcastReceiver.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
+import android.telecom.TelecomManager;
 
 import java.lang.String;
 
@@ -61,9 +62,9 @@
      * @param packageName The name of the removed package.
      */
     private void handlePackageRemoved(Context context, String packageName) {
-        final CallsManager callsManager = CallsManager.getInstance();
-        if (callsManager != null) {
-            callsManager.getPhoneAccountRegistrar().clearAccounts(packageName);
+        final TelecomManager telecomManager = TelecomManager.from(context);
+        if (telecomManager != null) {
+            telecomManager.clearAccountsForPackage(packageName);
         }
     }
 }
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index 4ee2c88..eb3248e 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -17,28 +17,34 @@
 package com.android.server.telecom;
 
 import android.Manifest;
+import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.os.Environment;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.Process;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.telecom.ConnectionService;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
-import android.telecom.TelecomManager;
 import android.telephony.PhoneNumberUtils;
-import android.content.ComponentName;
-import android.content.Context;
-import android.net.Uri;
+import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
 import android.util.AtomicFile;
+import android.util.Base64;
 import android.util.Xml;
 
 // TODO: Needed for move to system service: import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -47,6 +53,7 @@
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
@@ -56,7 +63,6 @@
 import java.lang.SecurityException;
 import java.lang.String;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
@@ -82,7 +88,7 @@
 
     private static final String FILE_NAME = "phone-account-registrar-state.xml";
     @VisibleForTesting
-    public static final int EXPECTED_STATE_VERSION = 3;
+    public static final int EXPECTED_STATE_VERSION = 5;
 
     /** Keep in sync with the same in SipSettings.java */
     private static final String SIP_SHARED_PREFERENCES = "SIP_PREFERENCES";
@@ -90,7 +96,10 @@
     private final List<Listener> mListeners = new CopyOnWriteArrayList<>();
     private final AtomicFile mAtomicFile;
     private final Context mContext;
+    private final UserManager mUserManager;
+    private final SubscriptionManager mSubscriptionManager;
     private State mState;
+    private UserHandle mCurrentUserHandle;
 
     @VisibleForTesting
     public PhoneAccountRegistrar(Context context) {
@@ -111,41 +120,38 @@
 
         mState = new State();
         mContext = context;
+        mUserManager = UserManager.get(context);
+        mSubscriptionManager = SubscriptionManager.from(mContext);
+        mCurrentUserHandle = Process.myUserHandle();
         read();
     }
 
     /**
-     * Retrieves the phone account id for a given subscription id if it exists. Subscription ids
-     * apply only to PSTN/SIM card phone accounts so all other accounts should not have a
-     * subscription id.
-     * @param subscriptionId The subscription id for which to construct the phone account id
-     * @return The string representing the phone account id for the subscription id.
-     */
-    public String getPhoneAccountIdForSubscriptionId(long subscriptionId) {
-        return String.valueOf(subscriptionId);
-    }
-
-    /**
      * Retrieves the subscription id for a given phone account if it exists. Subscription ids
      * apply only to PSTN/SIM card phone accounts so all other accounts should not have a
      * subscription id.
      * @param accountHandle The handle for the phone account for which to retrieve the
      * subscription id.
-     * @return The value of the subscription id (long) or -1 if it does not exist or is not valid.
+     * @return The value of the subscription id or -1 if it does not exist or is not valid.
      */
-    public long getSubscriptionIdForPhoneAccount(PhoneAccountHandle accountHandle) {
-        PhoneAccount account = getPhoneAccount(accountHandle);
-        if (account == null || !account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) ||
-                !TextUtils.isDigitsOnly(accountHandle.getId())) {
+    public int getSubscriptionIdForPhoneAccount(PhoneAccountHandle accountHandle) {
+        PhoneAccount account = getPhoneAccountInternal(accountHandle);
+        if (account == null
+                || !account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
+                || !TextUtils.isDigitsOnly(accountHandle.getId())
+                || !isVisibleForUser(accountHandle)) {
             // Since no decimals or negative numbers can be valid subscription ids, only a string of
             // numbers can be subscription id
-            return -1;
+            return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
         }
-        return Long.parseLong(accountHandle.getId());
+        return Integer.parseInt(accountHandle.getId());
     }
 
     /**
-     * Retrieves the default outgoing phone account supporting the specified uriScheme.
+     * Retrieves the default outgoing phone account supporting the specified uriScheme. Note that if
+     * {@link #mCurrentUserHandle} does not have visibility into the current default, {@code null}
+     * will be returned.
+     *
      * @param uriScheme The URI scheme for the outgoing call.
      * @return The {@link PhoneAccountHandle} to use.
      */
@@ -155,8 +161,9 @@
         if (userSelected != null) {
             // If there is a default PhoneAccount, ensure it supports calls to handles with the
             // specified uriScheme.
-            final PhoneAccount userSelectedAccount = getPhoneAccount(userSelected);
-            if (userSelectedAccount.supportsUriScheme(uriScheme)) {
+            final PhoneAccount userSelectedAccount = getPhoneAccountInternal(userSelected);
+            if (userSelectedAccount.supportsUriScheme(uriScheme)
+                    && isVisibleForUser(userSelected)) {
                 return userSelected;
             }
         }
@@ -167,20 +174,29 @@
                 // There are no accounts, so there can be no default
                 return null;
             case 1:
-                // There is only one account, which is by definition the default
-                return outgoing.get(0);
+                // There is only one account, which is by definition the default.
+                PhoneAccountHandle onlyHandle = outgoing.get(0);
+                if (isVisibleForUser(onlyHandle)) {
+                    return outgoing.get(0);
+                }
+                return null;
             default:
                 // There are multiple accounts with no selected default
                 return null;
         }
     }
 
+    /**
+     * @return The user-selected outgoing {@link PhoneAccount}, or null if it hasn't been set (or
+     *      if it was set by another user).
+     */
     PhoneAccountHandle getUserSelectedOutgoingPhoneAccount() {
         if (mState.defaultOutgoing != null) {
             // Return the registered outgoing default iff it still exists (we keep a sticky
             // default to survive account deletion and re-addition)
             for (int i = 0; i < mState.accounts.size(); i++) {
-                if (mState.accounts.get(i).getAccountHandle().equals(mState.defaultOutgoing)) {
+                if (mState.accounts.get(i).getAccountHandle().equals(mState.defaultOutgoing)
+                        && isVisibleForUser(mState.defaultOutgoing)) {
                     return mState.defaultOutgoing;
                 }
             }
@@ -209,13 +225,21 @@
                 return;
             }
 
-            if (!getPhoneAccount(accountHandle).hasCapabilities(
+            if (!getPhoneAccountInternal(accountHandle).hasCapabilities(
                     PhoneAccount.CAPABILITY_CALL_PROVIDER)) {
                 Log.w(this, "Trying to set non-call-provider default outgoing %s",
                         accountHandle);
                 return;
             }
 
+            if (getPhoneAccountInternal(accountHandle).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);
+            }
+
             mState.defaultOutgoing = accountHandle;
         }
 
@@ -223,9 +247,14 @@
         fireDefaultOutgoingChanged();
     }
 
+    boolean isUserSelectedSmsPhoneAccount(PhoneAccountHandle accountHandle) {
+        return getSubscriptionIdForPhoneAccount(accountHandle) ==
+                SubscriptionManager.getDefaultSmsSubId();
+    }
+
     public void setSimCallManager(PhoneAccountHandle callManager) {
         if (callManager != null) {
-            PhoneAccount callManagerAccount = getPhoneAccount(callManager);
+            PhoneAccount callManagerAccount = getPhoneAccountInternal(callManager);
             if (callManagerAccount == null) {
                 Log.d(this, "setSimCallManager: Nonexistent call manager: %s", callManager);
                 return;
@@ -243,6 +272,9 @@
         fireSimCallManagerChanged();
     }
 
+    /**
+     * @return The {@link PhoneAccount}s which are visible to {@link #mCurrentUserHandle}.
+     */
     public PhoneAccountHandle getSimCallManager() {
         if (mState.simCallManager != null) {
             if (NO_ACCOUNT_SELECTED.equals(mState.simCallManager)) {
@@ -251,7 +283,9 @@
             // Return the registered sim call manager iff it still exists (we keep a sticky
             // setting to survive account deletion and re-addition)
             for (int i = 0; i < mState.accounts.size(); i++) {
-                if (mState.accounts.get(i).getAccountHandle().equals(mState.simCallManager)) {
+                if (mState.accounts.get(i).getAccountHandle().equals(mState.simCallManager)
+                        && !resolveComponent(mState.simCallManager).isEmpty()
+                        && isVisibleForUser(mState.simCallManager)) {
                     return mState.simCallManager;
                 }
             }
@@ -261,19 +295,15 @@
         String defaultConnectionMgr =
                 mContext.getResources().getString(R.string.default_connection_manager_component);
         if (!TextUtils.isEmpty(defaultConnectionMgr)) {
-            PackageManager pm = mContext.getPackageManager();
-
             ComponentName componentName = ComponentName.unflattenFromString(defaultConnectionMgr);
-            Intent intent = new Intent(ConnectionService.SERVICE_INTERFACE);
-            intent.setComponent(componentName);
-
             // Make sure that the component can be resolved.
-            List<ResolveInfo> resolveInfos = pm.queryIntentServices(intent, 0);
+            List<ResolveInfo> resolveInfos = resolveComponent(componentName, null);
             if (!resolveInfos.isEmpty()) {
                 // See if there is registered PhoneAccount by this component.
                 List<PhoneAccountHandle> handles = getAllPhoneAccountHandles();
                 for (PhoneAccountHandle handle : handles) {
-                    if (componentName.equals(handle.getComponentName())) {
+                    if (componentName.equals(handle.getComponentName())
+                            && isVisibleForUser(handle)) {
                         return handle;
                     }
                 }
@@ -289,6 +319,97 @@
     }
 
     /**
+     * A version of {@link #getPhoneAccount} which does not guard for the current user.
+     *
+     * @param handle
+     * @return
+     */
+    PhoneAccount getPhoneAccountInternal(PhoneAccountHandle handle) {
+        for (PhoneAccount m : mState.accounts) {
+            if (Objects.equals(handle, m.getAccountHandle())) {
+                return m;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Update the current UserHandle to track when users are switched. This will allow the
+     * PhoneAccountRegistar to self-filter the PhoneAccounts to make sure we don't leak anything
+     * across users.
+     *
+     * @param userHandle The {@link UserHandle}, as delivered by
+     *          {@link Intent#ACTION_USER_SWITCHED}.
+     */
+    public void setCurrentUserHandle(UserHandle userHandle) {
+        if (userHandle == null) {
+            Log.d(this, "setCurrentUserHandle, userHandle = null");
+            userHandle = Process.myUserHandle();
+        }
+        Log.d(this, "setCurrentUserHandle, %s", userHandle);
+        mCurrentUserHandle = userHandle;
+    }
+
+    private boolean isVisibleForUser(PhoneAccountHandle accountHandle) {
+        if (accountHandle == null) {
+            return false;
+        }
+
+        return isVisibleForUser(getPhoneAccountInternal(accountHandle));
+    }
+
+    private boolean isVisibleForUser(PhoneAccount account) {
+        if (account == null) {
+            return false;
+        }
+
+        // If this PhoneAccount has CAPABILITY_MULTI_USER, it should be visible to all users and
+        // all profiles. Only Telephony and SIP accounts should have this capability.
+        if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
+            return true;
+        }
+
+        UserHandle phoneAccountUserHandle = account.getAccountHandle().getUserHandle();
+        if (phoneAccountUserHandle == null) {
+            return false;
+        }
+
+        if (mCurrentUserHandle == null) {
+            Log.d(this, "Current user is null; assuming true");
+            return true;
+        }
+
+        // Unlike in TelecomServiceImpl, we only care about *profiles* here. We want to make sure
+        // that we don't resolve PhoneAccount across *users*, but resolving across *profiles* is
+        // fine.
+        List<UserInfo> profileUsers = mUserManager.getProfiles(mCurrentUserHandle.getIdentifier());
+
+        for (UserInfo profileInfo : profileUsers) {
+            if (profileInfo.getUserHandle().equals(phoneAccountUserHandle)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private List<ResolveInfo> resolveComponent(PhoneAccountHandle phoneAccountHandle) {
+        return resolveComponent(phoneAccountHandle.getComponentName(),
+                    phoneAccountHandle.getUserHandle());
+    }
+
+    private List<ResolveInfo> resolveComponent(ComponentName componentName,
+            UserHandle userHandle) {
+        PackageManager pm = mContext.getPackageManager();
+        Intent intent = new Intent(ConnectionService.SERVICE_INTERFACE);
+        intent.setComponent(componentName);
+        if (userHandle != null) {
+            return pm.queryIntentServicesAsUser(intent, 0, userHandle.getIdentifier());
+        } else {
+            return pm.queryIntentServices(intent, 0);
+        }
+    }
+
+    /**
      * Retrieves a list of all {@link PhoneAccountHandle}s registered.
      *
      * @return The list of {@link PhoneAccountHandle}s.
@@ -296,22 +417,21 @@
     public List<PhoneAccountHandle> getAllPhoneAccountHandles() {
         List<PhoneAccountHandle> accountHandles = new ArrayList<>();
         for (PhoneAccount m : mState.accounts) {
-            accountHandles.add(m.getAccountHandle());
+            if (isVisibleForUser(m)) {
+                accountHandles.add(m.getAccountHandle());
+            }
         }
         return accountHandles;
     }
 
     public List<PhoneAccount> getAllPhoneAccounts() {
-        return new ArrayList<>(mState.accounts);
-    }
-
-    /**
-     * Determines the number of all {@link PhoneAccount}s.
-     *
-     * @return The total number {@link PhoneAccount}s.
-     */
-    public int getAllPhoneAccountsCount() {
-        return mState.accounts.size();
+        List<PhoneAccount> accounts = new ArrayList<>(mState.accounts.size());
+        for (PhoneAccount account : mState.accounts) {
+            if (isVisibleForUser(account)) {
+                accounts.add(account);
+            }
+        }
+        return accounts;
     }
 
     /**
@@ -345,7 +465,8 @@
         for (PhoneAccount m : mState.accounts) {
             if (Objects.equals(
                     packageName,
-                    m.getAccountHandle().getComponentName().getPackageName())) {
+                    m.getAccountHandle().getComponentName().getPackageName())
+                    && isVisibleForUser(m)) {
                 accountHandles.add(m.getAccountHandle());
             }
         }
@@ -364,7 +485,8 @@
 
     public PhoneAccount getPhoneAccount(PhoneAccountHandle handle) {
         for (PhoneAccount m : mState.accounts) {
-            if (Objects.equals(handle, m.getAccountHandle())) {
+            if (Objects.equals(handle, m.getAccountHandle())
+                    && isVisibleForUser(m)) {
                 return m;
             }
         }
@@ -392,6 +514,9 @@
      * @param account The {@code PhoneAccount} to add or replace.
      */
     private void addOrReplacePhoneAccount(PhoneAccount account) {
+        Log.d(this, "addOrReplacePhoneAccount(%s -> %s)",
+                account.getAccountHandle(), account);
+
         mState.accounts.add(account);
         // Search for duplicates and remove any that are found.
         for (int i = 0; i < mState.accounts.size() - 1; i++) {
@@ -409,7 +534,8 @@
 
     public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
         for (int i = 0; i < mState.accounts.size(); i++) {
-            if (Objects.equals(accountHandle, mState.accounts.get(i).getAccountHandle())) {
+            PhoneAccountHandle handle = mState.accounts.get(i).getAccountHandle();
+            if (Objects.equals(accountHandle, handle)) {
                 mState.accounts.remove(i);
                 break;
             }
@@ -423,15 +549,16 @@
      * Un-registers all phone accounts associated with a specified package.
      *
      * @param packageName The package for which phone accounts will be removed.
+     * @param userHandle The {@link UserHandle} the package is running under.
      */
-    public void clearAccounts(String packageName) {
+    public void clearAccounts(String packageName, UserHandle userHandle) {
         boolean accountsRemoved = false;
         Iterator<PhoneAccount> it = mState.accounts.iterator();
         while (it.hasNext()) {
             PhoneAccount phoneAccount = it.next();
-            if (Objects.equals(
-                    packageName,
-                    phoneAccount.getAccountHandle().getComponentName().getPackageName())) {
+            PhoneAccountHandle handle = phoneAccount.getAccountHandle();
+            if (Objects.equals(packageName, handle.getComponentName().getPackageName())
+                    && Objects.equals(userHandle, handle.getUserHandle())) {
                 Log.i(this, "Removing phone account " + phoneAccount.getLabel());
                 it.remove();
                 accountsRemoved = true;
@@ -445,7 +572,7 @@
     }
 
     public boolean isVoiceMailNumber(PhoneAccountHandle accountHandle, String number) {
-        long subId = getSubscriptionIdForPhoneAccount(accountHandle);
+        int subId = getSubscriptionIdForPhoneAccount(accountHandle);
         return PhoneNumberUtils.isVoiceMailNumber(subId, number);
     }
 
@@ -520,9 +647,23 @@
     private List<PhoneAccountHandle> getPhoneAccountHandles(int flags, String uriScheme) {
         List<PhoneAccountHandle> accountHandles = new ArrayList<>();
         for (PhoneAccount m : mState.accounts) {
-            if (m.hasCapabilities(flags) && (uriScheme == null || m.supportsUriScheme(uriScheme))) {
-                accountHandles.add(m.getAccountHandle());
+            if (!m.hasCapabilities(flags)) {
+                // Account doesn't have the right capabilities; skip this one.
+                continue;
             }
+            if (uriScheme != null && !m.supportsUriScheme(uriScheme)) {
+                // Account doesn't support this URI scheme; skip this one.
+                continue;
+            }
+            if (resolveComponent(m.getAccountHandle()).isEmpty()) {
+                // This component cannot be resolved anymore; skip this one.
+                continue;
+            }
+            if (!isVisibleForUser(m)) {
+                // Account is not visible for the current user; skip this one.
+                continue;
+            }
+            accountHandles.add(m.getAccountHandle());
         }
         return accountHandles;
     }
@@ -555,6 +696,27 @@
         public int versionNumber;
     }
 
+    /**
+     * Dumps the state of the {@link CallsManager}.
+     *
+     * @param pw The {@code IndentingPrintWriter} to write the state to.
+     */
+    public void dump(IndentingPrintWriter pw) {
+        if (mState != null) {
+            pw.println("xmlVersion: " + mState.versionNumber);
+            pw.println("defaultOutgoing: " + (mState.defaultOutgoing == null ? "none" :
+                    mState.defaultOutgoing));
+            pw.println("simCallManager: " + (mState.simCallManager == null ? "none" :
+                    mState.simCallManager));
+            pw.println("phoneAccounts:");
+            pw.increaseIndent();
+            for (PhoneAccount phoneAccount : mState.accounts) {
+                pw.println(phoneAccount);
+            }
+            pw.decreaseIndent();
+        }
+    }
+
     ////////////////////////////////////////////////////////////////////////////////////////////////
     //
     // State management
@@ -568,7 +730,7 @@
             try {
                 XmlSerializer serializer = new FastXmlSerializer();
                 serializer.setOutput(new BufferedOutputStream(os), "utf-8");
-                writeToXml(mState, serializer);
+                writeToXml(mState, serializer, mContext);
                 serializer.flush();
                 success = true;
             } finally {
@@ -612,15 +774,29 @@
             }
         }
 
+        // Verify all of the UserHandles.
+        List<PhoneAccount> badAccounts = new ArrayList<>();
+        for (PhoneAccount phoneAccount : mState.accounts) {
+            UserHandle userHandle = phoneAccount.getAccountHandle().getUserHandle();
+            if (userHandle == null) {
+                Log.w(this, "Missing UserHandle for %s", phoneAccount);
+                badAccounts.add(phoneAccount);
+            } else if (mUserManager.getSerialNumberForUser(userHandle) == -1) {
+                Log.w(this, "User does not exist for %s", phoneAccount);
+                badAccounts.add(phoneAccount);
+            }
+        }
+        mState.accounts.removeAll(badAccounts);
+
         // If an upgrade occurred, write out the changed data.
-        if (versionChanged) {
+        if (versionChanged || !badAccounts.isEmpty()) {
             write();
         }
     }
 
-    private static void writeToXml(State state, XmlSerializer serializer)
+    private static void writeToXml(State state, XmlSerializer serializer, Context context)
             throws IOException {
-        sStateXml.writeToXml(state, serializer);
+        sStateXml.writeToXml(state, serializer, context);
     }
 
     private static State readFromXml(XmlPullParser parser, Context context)
@@ -642,7 +818,7 @@
         /**
          * Write the supplied object to XML
          */
-        public abstract void writeToXml(T o, XmlSerializer serializer)
+        public abstract void writeToXml(T o, XmlSerializer serializer, Context context)
                 throws IOException;
 
         /**
@@ -655,7 +831,7 @@
         public abstract T readFromXml(XmlPullParser parser, int version, Context context)
                 throws IOException, XmlPullParserException;
 
-        protected void writeTextSafely(String tagName, Object value, XmlSerializer serializer)
+        protected void writeTextIfNonNull(String tagName, Object value, XmlSerializer serializer)
                 throws IOException {
             if (value != null) {
                 serializer.startTag(null, tagName);
@@ -690,7 +866,27 @@
                 serializer.attribute(null, LENGTH_ATTRIBUTE, "0");
             }
             serializer.endTag(null, tagName);
+        }
 
+        protected void writeBitmapIfNonNull(String tagName, Bitmap value, XmlSerializer serializer)
+                throws IOException {
+            if (value != null && value.getByteCount() > 0) {
+                ByteArrayOutputStream stream = new ByteArrayOutputStream();
+                value.compress(Bitmap.CompressFormat.PNG, 100, stream);
+                byte[] imageByteArray = stream.toByteArray();
+                String text = Base64.encodeToString(imageByteArray, 0, imageByteArray.length, 0);
+
+                serializer.startTag(null, tagName);
+                serializer.text(text);
+                serializer.endTag(null, tagName);
+            }
+        }
+
+        protected void writeLong(String tagName, long value, XmlSerializer serializer)
+                throws IOException {
+            serializer.startTag(null, tagName);
+            serializer.text(Long.valueOf(value).toString());
+            serializer.endTag(null, tagName);
         }
 
         /**
@@ -723,6 +919,12 @@
 
             return arrayEntries;
         }
+
+        protected Bitmap readBitmap(XmlPullParser parser)
+                throws IOException, XmlPullParserException {
+            byte[] imageByteArray = Base64.decode(parser.getText(), 0);
+            return BitmapFactory.decodeByteArray(imageByteArray, 0, imageByteArray.length);
+        }
     }
 
     @VisibleForTesting
@@ -735,7 +937,7 @@
         private static final String VERSION = "version";
 
         @Override
-        public void writeToXml(State o, XmlSerializer serializer)
+        public void writeToXml(State o, XmlSerializer serializer, Context context)
                 throws IOException {
             if (o != null) {
                 serializer.startTag(null, CLASS_STATE);
@@ -743,19 +945,19 @@
 
                 if (o.defaultOutgoing != null) {
                     serializer.startTag(null, DEFAULT_OUTGOING);
-                    sPhoneAccountHandleXml.writeToXml(o.defaultOutgoing, serializer);
+                    sPhoneAccountHandleXml.writeToXml(o.defaultOutgoing, serializer, context);
                     serializer.endTag(null, DEFAULT_OUTGOING);
                 }
 
                 if (o.simCallManager != null) {
                     serializer.startTag(null, SIM_CALL_MANAGER);
-                    sPhoneAccountHandleXml.writeToXml(o.simCallManager, serializer);
+                    sPhoneAccountHandleXml.writeToXml(o.simCallManager, serializer, context);
                     serializer.endTag(null, SIM_CALL_MANAGER);
                 }
 
                 serializer.startTag(null, ACCOUNTS);
                 for (PhoneAccount m : o.accounts) {
-                    sPhoneAccountXml.writeToXml(m, serializer);
+                    sPhoneAccountXml.writeToXml(m, serializer, context);
                 }
                 serializer.endTag(null, ACCOUNTS);
 
@@ -783,6 +985,13 @@
                         parser.nextTag();
                         s.simCallManager = sPhoneAccountHandleXml.readFromXml(parser,
                                 s.versionNumber, context);
+                        if (s.simCallManager.getUserHandle() == null) {
+                            // This should never happen, but handle the upgrade case.
+                            s.simCallManager = new PhoneAccountHandle(
+                                    s.simCallManager.getComponentName(),
+                                    s.simCallManager.getId(),
+                                    Process.myUserHandle());
+                        }
                     } else if (parser.getName().equals(ACCOUNTS)) {
                         int accountsDepth = parser.getDepth();
                         while (XmlUtils.nextElementWithin(parser, accountsDepth)) {
@@ -810,32 +1019,37 @@
         private static final String SUBSCRIPTION_ADDRESS = "subscription_number";
         private static final String CAPABILITIES = "capabilities";
         private static final String ICON_RES_ID = "icon_res_id";
-        private static final String COLOR = "color";
+        private static final String ICON_PACKAGE_NAME = "icon_package_name";
+        private static final String ICON_BITMAP = "icon_bitmap";
+        private static final String ICON_TINT = "icon_tint";
+        private static final String HIGHLIGHT_COLOR = "highlight_color";
         private static final String LABEL = "label";
         private static final String SHORT_DESCRIPTION = "short_description";
         private static final String SUPPORTED_URI_SCHEMES = "supported_uri_schemes";
-        private static final String TRUE = "true";
-        private static final String FALSE = "false";
 
         @Override
-        public void writeToXml(PhoneAccount o, XmlSerializer serializer)
+        public void writeToXml(PhoneAccount o, XmlSerializer serializer, Context context)
                 throws IOException {
             if (o != null) {
                 serializer.startTag(null, CLASS_PHONE_ACCOUNT);
 
                 if (o.getAccountHandle() != null) {
                     serializer.startTag(null, ACCOUNT_HANDLE);
-                    sPhoneAccountHandleXml.writeToXml(o.getAccountHandle(), serializer);
+                    sPhoneAccountHandleXml.writeToXml(o.getAccountHandle(), serializer, context);
                     serializer.endTag(null, ACCOUNT_HANDLE);
                 }
 
-                writeTextSafely(ADDRESS, o.getAddress(), serializer);
-                writeTextSafely(SUBSCRIPTION_ADDRESS, o.getSubscriptionAddress(), serializer);
-                writeTextSafely(CAPABILITIES, Integer.toString(o.getCapabilities()), serializer);
-                writeTextSafely(ICON_RES_ID, Integer.toString(o.getIconResId()), serializer);
-                writeTextSafely(COLOR, Integer.toString(o.getColor()), serializer);
-                writeTextSafely(LABEL, o.getLabel(), serializer);
-                writeTextSafely(SHORT_DESCRIPTION, o.getShortDescription(), serializer);
+                writeTextIfNonNull(ADDRESS, o.getAddress(), serializer);
+                writeTextIfNonNull(SUBSCRIPTION_ADDRESS, o.getSubscriptionAddress(), serializer);
+                writeTextIfNonNull(CAPABILITIES, Integer.toString(o.getCapabilities()), serializer);
+                writeTextIfNonNull(ICON_RES_ID, Integer.toString(o.getIconResId()), serializer);
+                writeTextIfNonNull(ICON_PACKAGE_NAME, o.getIconPackageName(), serializer);
+                writeBitmapIfNonNull(ICON_BITMAP, o.getIconBitmap(), serializer);
+                writeTextIfNonNull(ICON_TINT, Integer.toString(o.getIconTint()), serializer);
+                writeTextIfNonNull(HIGHLIGHT_COLOR,
+                        Integer.toString(o.getHighlightColor()), serializer);
+                writeTextIfNonNull(LABEL, o.getLabel(), serializer);
+                writeTextIfNonNull(SHORT_DESCRIPTION, o.getShortDescription(), serializer);
                 writeStringList(SUPPORTED_URI_SCHEMES, o.getSupportedUriSchemes(), serializer);
 
                 serializer.endTag(null, CLASS_PHONE_ACCOUNT);
@@ -850,8 +1064,11 @@
                 Uri address = null;
                 Uri subscriptionAddress = null;
                 int capabilities = 0;
-                int iconResId = 0;
-                int color = 0;
+                int iconResId = PhoneAccount.NO_RESOURCE_ID;
+                String iconPackageName = null;
+                Bitmap iconBitmap = null;
+                int iconTint = PhoneAccount.NO_ICON_TINT;
+                int highlightColor = PhoneAccount.NO_HIGHLIGHT_COLOR;
                 String label = null;
                 String shortDescription = null;
                 List<String> supportedUriSchemes = null;
@@ -874,9 +1091,18 @@
                     } else if (parser.getName().equals(ICON_RES_ID)) {
                         parser.next();
                         iconResId = Integer.parseInt(parser.getText());
-                    } else if (parser.getName().equals(COLOR)) {
+                    } else if (parser.getName().equals(ICON_PACKAGE_NAME)) {
                         parser.next();
-                        color = Integer.parseInt(parser.getText());
+                        iconPackageName = parser.getText();
+                    } else if (parser.getName().equals(ICON_BITMAP)) {
+                        parser.next();
+                        iconBitmap = readBitmap(parser);
+                    } else if (parser.getName().equals(ICON_TINT)) {
+                        parser.next();
+                        iconTint = Integer.parseInt(parser.getText());
+                    } else if (parser.getName().equals(HIGHLIGHT_COLOR)) {
+                        parser.next();
+                        highlightColor = Integer.parseInt(parser.getText());
                     } else if (parser.getName().equals(LABEL)) {
                         parser.next();
                         label = parser.getText();
@@ -909,15 +1135,28 @@
                     }
                 }
 
-                return PhoneAccount.builder(accountHandle, label)
+                // Upgrade older phone accounts with explicit package name
+                if (version < 5) {
+                    if (iconBitmap == null) {
+                        iconPackageName = accountHandle.getComponentName().getPackageName();
+                    }
+                }
+
+                PhoneAccount.Builder builder = PhoneAccount.builder(accountHandle, label)
                         .setAddress(address)
                         .setSubscriptionAddress(subscriptionAddress)
                         .setCapabilities(capabilities)
-                        .setIconResId(iconResId)
-                        .setColor(color)
                         .setShortDescription(shortDescription)
                         .setSupportedUriSchemes(supportedUriSchemes)
-                        .build();
+                        .setHighlightColor(highlightColor);
+
+                if (iconBitmap == null) {
+                    builder.setIcon(iconPackageName, iconResId, iconTint);
+                } else {
+                    builder.setIcon(iconBitmap);
+                }
+
+                return builder.build();
             }
             return null;
         }
@@ -942,19 +1181,26 @@
         private static final String CLASS_PHONE_ACCOUNT_HANDLE = "phone_account_handle";
         private static final String COMPONENT_NAME = "component_name";
         private static final String ID = "id";
+        private static final String USER_SERIAL_NUMBER = "user_serial_number";
 
         @Override
-        public void writeToXml(PhoneAccountHandle o, XmlSerializer serializer)
+        public void writeToXml(PhoneAccountHandle o, XmlSerializer serializer, Context context)
                 throws IOException {
             if (o != null) {
                 serializer.startTag(null, CLASS_PHONE_ACCOUNT_HANDLE);
 
                 if (o.getComponentName() != null) {
-                    writeTextSafely(
+                    writeTextIfNonNull(
                             COMPONENT_NAME, o.getComponentName().flattenToString(), serializer);
                 }
 
-                writeTextSafely(ID, o.getId(), serializer);
+                writeTextIfNonNull(ID, o.getId(), serializer);
+
+                if (o.getUserHandle() != null && context != null) {
+                    UserManager userManager = UserManager.get(context);
+                    writeLong(USER_SERIAL_NUMBER,
+                            userManager.getSerialNumberForUser(o.getUserHandle()), serializer);
+                }
 
                 serializer.endTag(null, CLASS_PHONE_ACCOUNT_HANDLE);
             }
@@ -966,7 +1212,11 @@
             if (parser.getName().equals(CLASS_PHONE_ACCOUNT_HANDLE)) {
                 String componentNameString = null;
                 String idString = null;
+                String userSerialNumberString = null;
                 int outerDepth = parser.getDepth();
+
+                UserManager userManager = UserManager.get(context);
+
                 while (XmlUtils.nextElementWithin(parser, outerDepth)) {
                     if (parser.getName().equals(COMPONENT_NAME)) {
                         parser.next();
@@ -974,12 +1224,25 @@
                     } else if (parser.getName().equals(ID)) {
                         parser.next();
                         idString = parser.getText();
+                    } else if (parser.getName().equals(USER_SERIAL_NUMBER)) {
+                        parser.next();
+                        userSerialNumberString = parser.getText();
                     }
                 }
                 if (componentNameString != null) {
+                    UserHandle userHandle = null;
+                    if (userSerialNumberString != null) {
+                        try {
+                            long serialNumber = Long.parseLong(userSerialNumberString);
+                            userHandle = userManager.getUserForSerialNumber(serialNumber);
+                        } catch (NumberFormatException e) {
+                            Log.e(this, e, "Could not parse UserHandle " + userSerialNumberString);
+                        }
+                    }
                     return new PhoneAccountHandle(
                             ComponentName.unflattenFromString(componentNameString),
-                            idString);
+                            idString,
+                            userHandle);
                 }
             }
             return null;
diff --git a/src/com/android/server/telecom/ProximitySensorManager.java b/src/com/android/server/telecom/ProximitySensorManager.java
index 289366f..5b82c43 100644
--- a/src/com/android/server/telecom/ProximitySensorManager.java
+++ b/src/com/android/server/telecom/ProximitySensorManager.java
@@ -42,7 +42,7 @@
     @Override
     public void onCallRemoved(Call call) {
         if (CallsManager.getInstance().getCalls().isEmpty()) {
-            Log.v(this, "all calls removed, resetting proximity sensor to default state");
+            Log.i(this, "All calls removed, resetting proximity sensor to default state");
             turnOff(true);
         }
         super.onCallRemoved(call);
diff --git a/src/com/android/server/telecom/RespondViaSmsManager.java b/src/com/android/server/telecom/RespondViaSmsManager.java
index 2ac9379..ebedf9f 100644
--- a/src/com/android/server/telecom/RespondViaSmsManager.java
+++ b/src/com/android/server/telecom/RespondViaSmsManager.java
@@ -18,6 +18,7 @@
 
 // TODO: Needed for move to system service: import com.android.internal.R;
 import com.android.internal.os.SomeArgs;
+import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.SmsApplication;
 
 import android.content.ComponentName;
@@ -29,6 +30,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.telecom.Response;
+import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.widget.Toast;
 
@@ -108,7 +110,8 @@
                 QuickResponseUtils.maybeMigrateLegacyQuickResponses(context);
 
                 final SharedPreferences prefs = context.getSharedPreferences(
-                        QuickResponseUtils.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
+                        QuickResponseUtils.SHARED_PREFERENCES_NAME,
+                        Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS);
                 final Resources res = context.getResources();
 
                 final ArrayList<String> textMessages = new ArrayList<>(
@@ -139,10 +142,13 @@
 
     @Override
     public void onIncomingCallRejected(Call call, boolean rejectWithMessage, String textMessage) {
-        if (rejectWithMessage) {
-
+        if (rejectWithMessage && call.getHandle() != null) {
+            PhoneAccountRegistrar phoneAccountRegistrar =
+                    CallsManager.getInstance().getPhoneAccountRegistrar();
+            int subId = phoneAccountRegistrar.getSubscriptionIdForPhoneAccount(
+                    call.getTargetPhoneAccount());
             rejectCallWithMessage(call.getContext(), call.getHandle().getSchemeSpecificPart(),
-                    textMessage);
+                    textMessage, subId);
         }
     }
 
@@ -175,7 +181,8 @@
     /**
      * Reject the call with the specified message. If message is null this call is ignored.
      */
-    private void rejectCallWithMessage(Context context, String phoneNumber, String textMessage) {
+    private void rejectCallWithMessage(Context context, String phoneNumber, String textMessage,
+            int subId) {
         if (textMessage != null) {
             final ComponentName component =
                     SmsApplication.getDefaultRespondViaMessageApplication(context,
@@ -185,6 +192,9 @@
                 final Uri uri = Uri.fromParts(Constants.SCHEME_SMSTO, phoneNumber, null);
                 final Intent intent = new Intent(TelephonyManager.ACTION_RESPOND_VIA_MESSAGE, uri);
                 intent.putExtra(Intent.EXTRA_TEXT, textMessage);
+                if (SubscriptionManager.isValidSubscriptionId(subId)) {
+                    intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+                }
 
                 SomeArgs args = SomeArgs.obtain();
                 args.arg1 = phoneNumber;
diff --git a/src/com/android/server/telecom/RespondViaSmsSettings.java b/src/com/android/server/telecom/RespondViaSmsSettings.java
index b537162..f5876a0 100644
--- a/src/com/android/server/telecom/RespondViaSmsSettings.java
+++ b/src/com/android/server/telecom/RespondViaSmsSettings.java
@@ -33,9 +33,6 @@
  * Helper class to manage the "Respond via SMS Message" feature for incoming calls.
  */
 public class RespondViaSmsSettings {
-    private static final String KEY_PREFERRED_PACKAGE = "preferred_package_pref";
-    private static final String KEY_INSTANT_TEXT_DEFAULT_COMPONENT = "instant_text_def_component";
-
     // TODO: This class is newly copied into Telecom (com.android.server.telecom) from it previous
     // location in Telephony (com.android.phone). User's preferences stored in the old location
     // will be lost. We need code here to migrate KLP -> LMP settings values.
@@ -125,25 +122,10 @@
                 case android.R.id.home:
                     goUpToTopLevelSetting(this);
                     return true;
-                case R.id.respond_via_message_reset:
-                    // Reset the preferences settings
-                    SharedPreferences prefs = getSharedPreferences(
-                            QuickResponseUtils.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
-                    SharedPreferences.Editor editor = prefs.edit();
-                    editor.remove(KEY_INSTANT_TEXT_DEFAULT_COMPONENT);
-                    editor.apply();
-
-                    return true;
                 default:
             }
             return super.onOptionsItemSelected(item);
         }
-
-        @Override
-        public boolean onCreateOptionsMenu(Menu menu) {
-            getMenuInflater().inflate(R.menu.respond_via_message_settings_menu, menu);
-            return super.onCreateOptionsMenu(menu);
-        }
     }
 
     /**
diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java
index 5945306..6b46a71 100644
--- a/src/com/android/server/telecom/Ringer.java
+++ b/src/com/android/server/telecom/Ringer.java
@@ -252,7 +252,7 @@
 
     private boolean shouldVibrate(Context context) {
         AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-        int ringerMode = audioManager.getRingerMode();
+        int ringerMode = audioManager.getRingerModeInternal();
         if (getVibrateWhenRinging(context)) {
             return ringerMode != AudioManager.RINGER_MODE_SILENT;
         } else {
diff --git a/src/com/android/server/telecom/ServiceBinder.java b/src/com/android/server/telecom/ServiceBinder.java
index fb747f2..9a5ad03 100644
--- a/src/com/android/server/telecom/ServiceBinder.java
+++ b/src/com/android/server/telecom/ServiceBinder.java
@@ -22,11 +22,12 @@
 import android.content.ServiceConnection;
 import android.os.IBinder;
 import android.os.IInterface;
+import android.os.Process;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.ArraySet;
 
 import com.android.internal.util.Preconditions;
-import com.google.common.base.Strings;
-
-import com.google.common.collect.Sets;
 
 import java.util.Collections;
 import java.util.Set;
@@ -83,7 +84,15 @@
                 ServiceConnection connection = new ServiceBinderConnection();
 
                 Log.d(ServiceBinder.this, "Binding to service with intent: %s", serviceIntent);
-                if (!mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) {
+                final boolean binding;
+                if (mUserHandle != null) {
+                    binding = mContext.bindServiceAsUser(serviceIntent, connection,
+                        Context.BIND_AUTO_CREATE, mUserHandle);
+                } else {
+                    binding = mContext.bindService(serviceIntent, connection,
+                        Context.BIND_AUTO_CREATE);
+                }
+                if (!binding) {
                     handleFailedConnection();
                     return;
                 }
@@ -136,11 +145,14 @@
     private final ComponentName mComponentName;
 
     /** The set of callbacks waiting for notification of the binding's success or failure. */
-    private final Set<BindCallback> mCallbacks = Sets.newHashSet();
+    private final Set<BindCallback> mCallbacks = new ArraySet<>();
 
     /** Used to bind and unbind from the service. */
     private ServiceConnection mServiceConnection;
 
+    /** {@link UserHandle} to use for binding, to support work profiles and multi-user. */
+    private UserHandle mUserHandle;
+
     /** The binder provided by {@link ServiceConnection#onServiceConnected} */
     private IBinder mBinder;
 
@@ -167,14 +179,17 @@
      * @param serviceAction The intent-action used with {@link Context#bindService}.
      * @param componentName The component name of the service with which to bind.
      * @param context The context.
+     * @param userHandle The {@link UserHandle} to use for binding.
      */
-    protected ServiceBinder(String serviceAction, ComponentName componentName, Context context) {
-        Preconditions.checkState(!Strings.isNullOrEmpty(serviceAction));
+    protected ServiceBinder(String serviceAction, ComponentName componentName, Context context,
+            UserHandle userHandle) {
+        Preconditions.checkState(!TextUtils.isEmpty(serviceAction));
         Preconditions.checkNotNull(componentName);
 
         mContext = context;
         mServiceAction = serviceAction;
         mComponentName = componentName;
+        mUserHandle = userHandle;
     }
 
     final void incrementAssociatedCallCount() {
diff --git a/src/com/android/server/telecom/TelecomApp.java b/src/com/android/server/telecom/TelecomApp.java
deleted file mode 100644
index 4941a35..0000000
--- a/src/com/android/server/telecom/TelecomApp.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2014 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.Application;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-
-/**
- * Top-level Application class for Telecom.
- */
-public final class TelecomApp extends Application {
-    /**
-     * The Telecom service implementation.
-     */
-    private TelecomServiceImpl mTelecomService;
-
-    /**
-     * Missed call notifier. Exists here so that the instance can be shared with
-     * {@link TelecomBroadcastReceiver}.
-     */
-    private MissedCallNotifier mMissedCallNotifier;
-
-    /**
-     * Maintains the list of registered {@link android.telecom.PhoneAccountHandle}s.
-     */
-    private PhoneAccountRegistrar mPhoneAccountRegistrar;
-
-    /**
-     * The calls manager for the Telecom service.
-     */
-    private CallsManager mCallsManager;
-
-    /** {@inheritDoc} */
-    @Override
-    public void onCreate() {
-        super.onCreate();
-
-        if (UserHandle.myUserId() == UserHandle.USER_OWNER) {
-            // Note: This style of initialization mimics what will be performed once Telecom is
-            // moved
-            // to run in the system service. The emphasis is on ensuring that initialization of all
-            // telecom classes happens in one place without relying on Singleton initialization.
-            mMissedCallNotifier = new MissedCallNotifier(this);
-            mPhoneAccountRegistrar = new PhoneAccountRegistrar(this);
-
-            mCallsManager = new CallsManager(this, mMissedCallNotifier, mPhoneAccountRegistrar);
-            CallsManager.initialize(mCallsManager);
-
-            mTelecomService = new TelecomServiceImpl(mMissedCallNotifier, mPhoneAccountRegistrar,
-                    mCallsManager, this);
-            ServiceManager.addService(Context.TELECOM_SERVICE, mTelecomService);
-
-            // Start the BluetoothPhoneService
-            BluetoothPhoneService.start(this);
-        }
-    }
-
-    MissedCallNotifier getMissedCallNotifier() {
-        return mMissedCallNotifier;
-    }
-
-    PhoneAccountRegistrar getPhoneAccountRegistrar() {
-        return mPhoneAccountRegistrar;
-    }
-}
diff --git a/src/com/android/server/telecom/TelecomGlobals.java b/src/com/android/server/telecom/TelecomGlobals.java
new file mode 100644
index 0000000..cf0936c
--- /dev/null
+++ b/src/com/android/server/telecom/TelecomGlobals.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 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.Application;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.UserHandle;
+
+/**
+ * Top-level Application class for Telecom.
+ */
+public final class TelecomGlobals {
+    private static final String TAG = TelecomGlobals.class.getSimpleName();
+
+    private static final IntentFilter USER_SWITCHED_FILTER =
+            new IntentFilter(Intent.ACTION_USER_SWITCHED);
+
+    private static final TelecomGlobals INSTANCE = new TelecomGlobals();
+
+    /**
+     * The Telecom service implementation.
+     */
+    private TelecomService mTelecomService;
+
+    /**
+     * Missed call notifier. Exists here so that the instance can be shared with
+     * {@link TelecomBroadcastReceiver}.
+     */
+    private MissedCallNotifier mMissedCallNotifier;
+
+    /**
+     * Maintains the list of registered {@link android.telecom.PhoneAccountHandle}s.
+     */
+    private PhoneAccountRegistrar mPhoneAccountRegistrar;
+
+    /**
+     * The calls manager for the Telecom service.
+     */
+    private CallsManager mCallsManager;
+
+    /**
+     * The application context.
+     */
+    private Context mContext;
+
+    private final BroadcastReceiver mUserSwitchedReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+            UserHandle currentUserHandle = new UserHandle(userHandleId);
+            mPhoneAccountRegistrar.setCurrentUserHandle(currentUserHandle);
+        }
+    };
+
+    static TelecomGlobals getInstance() {
+        return INSTANCE;
+    }
+
+    void initialize(Context context) {
+        if (mContext != null) {
+            Log.e(TAG, new Exception(), "Attempting to intialize TelecomGlobals a second time.");
+            return;
+        } else {
+            Log.i(TAG, "TelecomGlobals initializing");
+        }
+        mContext = context.getApplicationContext();
+
+        mMissedCallNotifier = new MissedCallNotifier(mContext);
+        mPhoneAccountRegistrar = new PhoneAccountRegistrar(mContext);
+
+        mCallsManager = new CallsManager(mContext, mMissedCallNotifier, mPhoneAccountRegistrar);
+        CallsManager.initialize(mCallsManager);
+        Log.i(this, "CallsManager initialized");
+
+        // Start the BluetoothPhoneService
+        BluetoothPhoneService.start(mContext);
+
+        mContext.registerReceiver(mUserSwitchedReceiver, USER_SWITCHED_FILTER);
+    }
+
+    MissedCallNotifier getMissedCallNotifier() {
+        return mMissedCallNotifier;
+    }
+
+    PhoneAccountRegistrar getPhoneAccountRegistrar() {
+        return mPhoneAccountRegistrar;
+    }
+
+    CallsManager getCallsManager() {
+        return mCallsManager;
+    }
+}
diff --git a/src/com/android/server/telecom/TelecomService.java b/src/com/android/server/telecom/TelecomService.java
new file mode 100644
index 0000000..77fb1d2
--- /dev/null
+++ b/src/com/android/server/telecom/TelecomService.java
@@ -0,0 +1,1029 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.telecom;
+
+import android.Manifest;
+import android.annotation.SdkConstant;
+import android.app.AppOpsManager;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.telecom.CallState;
+import android.telecom.PhoneAccount;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import android.util.EventLog;
+
+// TODO: Needed for move to system service: import com.android.internal.R;
+import com.android.internal.telecom.ITelecomService;
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implementation of the ITelecom interface.
+ */
+public class TelecomService extends Service {
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE = "android.telecom.ITelecomService";
+
+    /** The context. */
+    private Context mContext;
+
+    /**
+     * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
+     * request after sending. The main thread will notify the request when it is complete.
+     */
+    private static final class MainThreadRequest {
+        /** The result of the request that is run on the main thread */
+        public Object result;
+        /** Object that can be used to store non-integer arguments */
+        public Object arg;
+    }
+
+    /**
+     * A handler that processes messages on the main thread. Since many of the method calls are not
+     * thread safe this is needed to shuttle the requests from the inbound binder threads to the
+     * main thread.
+     */
+    private final class MainThreadHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+            if (msg.obj instanceof MainThreadRequest) {
+                MainThreadRequest request = (MainThreadRequest) msg.obj;
+                Object result = null;
+                switch (msg.what) {
+                    case MSG_SILENCE_RINGER:
+                        mCallsManager.getRinger().silence();
+                        break;
+                    case MSG_SHOW_CALL_SCREEN:
+                        mCallsManager.getInCallController().bringToForeground(msg.arg1 == 1);
+                        break;
+                    case MSG_END_CALL:
+                        result = endCallInternal();
+                        break;
+                    case MSG_ACCEPT_RINGING_CALL:
+                        acceptRingingCallInternal();
+                        break;
+                    case MSG_CANCEL_MISSED_CALLS_NOTIFICATION:
+                        mMissedCallNotifier.clearMissedCalls();
+                        break;
+                    case MSG_IS_TTY_SUPPORTED:
+                        result = mCallsManager.isTtySupported();
+                        break;
+                    case MSG_GET_CURRENT_TTY_MODE:
+                        result = mCallsManager.getCurrentTtyMode();
+                        break;
+                    case MSG_NEW_INCOMING_CALL:
+                        if (request.arg == null || !(request.arg instanceof Intent)) {
+                            Log.w(this, "Invalid new incoming call request");
+                            break;
+                        }
+                        CallReceiver.processIncomingCallIntent((Intent) request.arg);
+                        break;
+                }
+
+                if (result != null) {
+                    request.result = result;
+                    synchronized(request) {
+                        request.notifyAll();
+                    }
+                }
+            }
+        }
+    }
+
+    private static final String TAG = TelecomService.class.getSimpleName();
+
+    private static final String SERVICE_NAME = "telecom";
+
+    private static final int MSG_SILENCE_RINGER = 1;
+    private static final int MSG_SHOW_CALL_SCREEN = 2;
+    private static final int MSG_END_CALL = 3;
+    private static final int MSG_ACCEPT_RINGING_CALL = 4;
+    private static final int MSG_CANCEL_MISSED_CALLS_NOTIFICATION = 5;
+    private static final int MSG_IS_TTY_SUPPORTED = 6;
+    private static final int MSG_GET_CURRENT_TTY_MODE = 7;
+    private static final int MSG_NEW_INCOMING_CALL = 8;
+
+    private final MainThreadHandler mMainThreadHandler = new MainThreadHandler();
+
+    private CallsManager mCallsManager;
+    private MissedCallNotifier mMissedCallNotifier;
+    private PhoneAccountRegistrar mPhoneAccountRegistrar;
+    private AppOpsManager mAppOpsManager;
+    private UserManager mUserManager;
+    private PackageManager mPackageManager;
+    private TelecomServiceImpl mServiceImpl;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        Log.d(this, "onCreate");
+        mContext = this;
+        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
+        mServiceImpl = new TelecomServiceImpl();
+
+        TelecomGlobals globals = TelecomGlobals.getInstance();
+        globals.initialize(this);
+
+        mMissedCallNotifier = globals.getMissedCallNotifier();
+        mPhoneAccountRegistrar = globals.getPhoneAccountRegistrar();
+        mCallsManager = globals.getCallsManager();
+        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        mPackageManager = mContext.getPackageManager();
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        Log.d(this, "onBind");
+        return mServiceImpl;
+    }
+
+    /**
+     * Implementation of the ITelecomService interface.
+     * TODO: Reorganize this inner class to top of file.
+     */
+    class TelecomServiceImpl extends ITelecomService.Stub {
+        @Override
+        public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme) {
+            enforceReadPermission();
+            long token = Binder.clearCallingIdentity();
+            try {
+                PhoneAccountHandle defaultOutgoingPhoneAccount =
+                        mPhoneAccountRegistrar.getDefaultOutgoingPhoneAccount(uriScheme);
+                // Make sure that the calling user can see this phone account.
+                if (defaultOutgoingPhoneAccount != null
+                        && !isVisibleToCaller(defaultOutgoingPhoneAccount)) {
+                    Log.w(this, "No account found for the calling user");
+                    return null;
+                }
+                return defaultOutgoingPhoneAccount;
+            } catch (Exception e) {
+                Log.e(this, e, "getDefaultOutgoingPhoneAccount");
+                throw e;
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public PhoneAccountHandle getUserSelectedOutgoingPhoneAccount() {
+            try {
+                PhoneAccountHandle userSelectedOutgoingPhoneAccount =
+                        mPhoneAccountRegistrar.getUserSelectedOutgoingPhoneAccount();
+                // Make sure that the calling user can see this phone account.
+                if (!isVisibleToCaller(userSelectedOutgoingPhoneAccount)) {
+                    Log.w(this, "No account found for the calling user");
+                    return null;
+                }
+                return userSelectedOutgoingPhoneAccount;
+            } catch (Exception e) {
+                Log.e(this, e, "getUserSelectedOutgoingPhoneAccount");
+                throw e;
+            }
+        }
+
+        @Override
+        public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
+            enforceModifyPermission();
+
+            try {
+                mPhoneAccountRegistrar.setUserSelectedOutgoingPhoneAccount(accountHandle);
+            } catch (Exception e) {
+                Log.e(this, e, "setUserSelectedOutgoingPhoneAccount");
+                throw e;
+            }
+        }
+
+        @Override
+        public List<PhoneAccountHandle> getCallCapablePhoneAccounts() {
+            enforceReadPermission();
+            long token = Binder.clearCallingIdentity();
+            try {
+                return filterForAccountsVisibleToCaller(
+                        mPhoneAccountRegistrar.getCallCapablePhoneAccounts());
+            } catch (Exception e) {
+                Log.e(this, e, "getCallCapablePhoneAccounts");
+                throw e;
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme) {
+            enforceReadPermission();
+            long token = Binder.clearCallingIdentity();
+            try {
+                return filterForAccountsVisibleToCaller(
+                        mPhoneAccountRegistrar.getCallCapablePhoneAccounts(uriScheme));
+            } catch (Exception e) {
+                Log.e(this, e, "getPhoneAccountsSupportingScheme %s", uriScheme);
+                throw e;
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public List<PhoneAccountHandle> getPhoneAccountsForPackage(String packageName) {
+            try {
+                return filterForAccountsVisibleToCaller(
+                        mPhoneAccountRegistrar.getPhoneAccountsForPackage(packageName));
+            } catch (Exception e) {
+                Log.e(this, e, "getPhoneAccountsForPackage %s", packageName);
+                throw e;
+            }
+        }
+
+        @Override
+        public PhoneAccount getPhoneAccount(PhoneAccountHandle accountHandle) {
+            try {
+                if (!isVisibleToCaller(accountHandle)) {
+                    Log.w(this, "%s is not visible for the calling user", accountHandle);
+                    return null;
+                }
+                return mPhoneAccountRegistrar.getPhoneAccountInternal(accountHandle);
+            } catch (Exception e) {
+                Log.e(this, e, "getPhoneAccount %s", accountHandle);
+                throw e;
+            }
+        }
+
+        @Override
+        public int getAllPhoneAccountsCount() {
+            try {
+                // This list is pre-filtered for the calling user.
+                return getAllPhoneAccounts().size();
+            } catch (Exception e) {
+                Log.e(this, e, "getAllPhoneAccountsCount");
+                throw e;
+            }
+        }
+
+        @Override
+        public List<PhoneAccount> getAllPhoneAccounts() {
+            try {
+                List<PhoneAccount> allPhoneAccounts = mPhoneAccountRegistrar.getAllPhoneAccounts();
+                List<PhoneAccount> profilePhoneAccounts = new ArrayList<>(allPhoneAccounts.size());
+                for (PhoneAccount phoneAccount : profilePhoneAccounts) {
+                    if (isVisibleToCaller(phoneAccount)) {
+                        profilePhoneAccounts.add(phoneAccount);
+                    }
+                }
+                return profilePhoneAccounts;
+            } catch (Exception e) {
+                Log.e(this, e, "getAllPhoneAccounts");
+                throw e;
+            }
+        }
+
+        @Override
+        public List<PhoneAccountHandle> getAllPhoneAccountHandles() {
+            try {
+                return filterForAccountsVisibleToCaller(
+                        mPhoneAccountRegistrar.getAllPhoneAccountHandles());
+            } catch (Exception e) {
+                Log.e(this, e, "getAllPhoneAccounts");
+                throw e;
+            }
+        }
+
+        @Override
+        public PhoneAccountHandle getSimCallManager() {
+            try {
+                PhoneAccountHandle accountHandle = mPhoneAccountRegistrar.getSimCallManager();
+                if (!isVisibleToCaller(accountHandle)) {
+                    Log.w(this, "%s is not visible for the calling user", accountHandle);
+                    return null;
+                }
+                return accountHandle;
+            } catch (Exception e) {
+                Log.e(this, e, "getSimCallManager");
+                throw e;
+            }
+        }
+
+        @Override
+        public void setSimCallManager(PhoneAccountHandle accountHandle) {
+            enforceModifyPermission();
+
+            try {
+                mPhoneAccountRegistrar.setSimCallManager(accountHandle);
+            } catch (Exception e) {
+                Log.e(this, e, "setSimCallManager");
+                throw e;
+            }
+        }
+
+        @Override
+        public List<PhoneAccountHandle> getSimCallManagers() {
+            enforceReadPermission();
+            long token = Binder.clearCallingIdentity();
+            try {
+                return filterForAccountsVisibleToCaller(
+                        mPhoneAccountRegistrar.getConnectionManagerPhoneAccounts());
+            } catch (Exception e) {
+                Log.e(this, e, "getSimCallManagers");
+                throw e;
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void registerPhoneAccount(PhoneAccount account) {
+            try {
+                enforcePhoneAccountModificationForPackage(
+                        account.getAccountHandle().getComponentName().getPackageName());
+                if (account.hasCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)) {
+                    enforceRegisterCallProviderPermission();
+                }
+                if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
+                    enforceRegisterSimSubscriptionPermission();
+                }
+                if (account.hasCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)) {
+                    enforceRegisterConnectionManagerPermission();
+                }
+                if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
+                    enforceRegisterMultiUser();
+                }
+                enforceUserHandleMatchesCaller(account.getAccountHandle());
+
+                mPhoneAccountRegistrar.registerPhoneAccount(account);
+            } catch (Exception e) {
+                Log.e(this, e, "registerPhoneAccount %s", account);
+                throw e;
+            }
+        }
+
+        @Override
+        public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
+            try {
+                enforcePhoneAccountModificationForPackage(
+                        accountHandle.getComponentName().getPackageName());
+                enforceUserHandleMatchesCaller(accountHandle);
+                mPhoneAccountRegistrar.unregisterPhoneAccount(accountHandle);
+            } catch (Exception e) {
+                Log.e(this, e, "unregisterPhoneAccount %s", accountHandle);
+                throw e;
+            }
+        }
+
+        @Override
+        public void clearAccounts(String packageName) {
+            try {
+                enforcePhoneAccountModificationForPackage(packageName);
+                mPhoneAccountRegistrar.clearAccounts(packageName, Binder.getCallingUserHandle());
+            } catch (Exception e) {
+                Log.e(this, e, "clearAccounts %s", packageName);
+                throw e;
+            }
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#isVoiceMailNumber
+         */
+        @Override
+        public boolean isVoiceMailNumber(PhoneAccountHandle accountHandle, String number) {
+            enforceReadPermissionOrDefaultDialer();
+            try {
+                if (!isVisibleToCaller(accountHandle)) {
+                    Log.w(this, "%s is not visible for the calling user", accountHandle);
+                    return false;
+                }
+                return mPhoneAccountRegistrar.isVoiceMailNumber(accountHandle, number);
+            } catch (Exception e) {
+                Log.e(this, e, "getSubscriptionIdForPhoneAccount");
+                throw e;
+            }
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#hasVoiceMailNumber
+         */
+        @Override
+        public boolean hasVoiceMailNumber(PhoneAccountHandle accountHandle) {
+            enforceReadPermissionOrDefaultDialer();
+            try {
+                if (!isVisibleToCaller(accountHandle)) {
+                    Log.w(this, "%s is not visible for the calling user", accountHandle);
+                    return false;
+                }
+
+                int subId = mPhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(accountHandle);
+                return !TextUtils.isEmpty(getTelephonyManager().getVoiceMailNumber(subId));
+            } catch (Exception e) {
+                Log.e(this, e, "getSubscriptionIdForPhoneAccount");
+                throw e;
+            }
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#getLine1Number
+         */
+        @Override
+        public String getLine1Number(PhoneAccountHandle accountHandle) {
+            enforceReadPermissionOrDefaultDialer();
+            try {
+                if (!isVisibleToCaller(accountHandle)) {
+                    Log.w(this, "%s is not visible for the calling user", accountHandle);
+                    return null;
+                }
+                int subId = mPhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(accountHandle);
+                return getTelephonyManager().getLine1NumberForSubscriber(subId);
+            } catch (Exception e) {
+                Log.e(this, e, "getSubscriptionIdForPhoneAccount");
+                throw e;
+            }
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#silenceRinger
+         */
+        @Override
+        public void silenceRinger() {
+            Log.d(this, "silenceRinger");
+            enforceModifyPermission();
+            sendRequestAsync(MSG_SILENCE_RINGER, 0);
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#getDefaultPhoneApp
+         */
+        @Override
+        public ComponentName getDefaultPhoneApp() {
+            Resources resources = mContext.getResources();
+            return new ComponentName(
+                    resources.getString(R.string.ui_default_package),
+                    resources.getString(R.string.dialer_default_class));
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#isInCall
+         */
+        @Override
+        public boolean isInCall() {
+            enforceReadPermission();
+            // Do not use sendRequest() with this method since it could cause a deadlock with
+            // audio service, which we call into from the main thread: AudioManager.setMode().
+            final int callState = mCallsManager.getCallState();
+            return callState == TelephonyManager.CALL_STATE_OFFHOOK
+                    || callState == TelephonyManager.CALL_STATE_RINGING;
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#isRinging
+         */
+        @Override
+        public boolean isRinging() {
+            enforceReadPermission();
+            return mCallsManager.getCallState() == TelephonyManager.CALL_STATE_RINGING;
+        }
+
+        /**
+         * @see TelecomManager#getCallState
+         */
+        @Override
+        public int getCallState() {
+            return mCallsManager.getCallState();
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#endCall
+         */
+        @Override
+        public boolean endCall() {
+            enforceModifyPermission();
+            return (boolean) sendRequest(MSG_END_CALL);
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#acceptRingingCall
+         */
+        @Override
+        public void acceptRingingCall() {
+            enforceModifyPermission();
+            sendRequestAsync(MSG_ACCEPT_RINGING_CALL, 0);
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#showInCallScreen
+         */
+        @Override
+        public void showInCallScreen(boolean showDialpad) {
+            enforceReadPermissionOrDefaultDialer();
+            sendRequestAsync(MSG_SHOW_CALL_SCREEN, showDialpad ? 1 : 0);
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#cancelMissedCallsNotification
+         */
+        @Override
+        public void cancelMissedCallsNotification() {
+            enforceModifyPermissionOrDefaultDialer();
+            sendRequestAsync(MSG_CANCEL_MISSED_CALLS_NOTIFICATION, 0);
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#handleMmi
+         */
+        @Override
+        public boolean handlePinMmi(String dialString) {
+            enforceModifyPermissionOrDefaultDialer();
+
+            // Switch identity so that TelephonyManager checks Telecom's permissions instead.
+            long token = Binder.clearCallingIdentity();
+            boolean retval = false;
+            try {
+                retval = getTelephonyManager().handlePinMmi(dialString);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+
+            return retval;
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#handleMmi
+         */
+        @Override
+        public boolean handlePinMmiForPhoneAccount(PhoneAccountHandle accountHandle,
+                String dialString) {
+            enforceModifyPermissionOrDefaultDialer();
+
+            if (!isVisibleToCaller(accountHandle)) {
+                Log.w(this, "%s is not visible for the calling user", accountHandle);
+                return false;
+            }
+
+            // Switch identity so that TelephonyManager checks Telecom's permissions instead.
+            long token = Binder.clearCallingIdentity();
+            boolean retval = false;
+            try {
+                int subId = mPhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(accountHandle);
+                retval = getTelephonyManager().handlePinMmiForSubscriber(subId, dialString);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+
+            return retval;
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#getAdnUriForPhoneAccount
+         */
+        @Override
+        public Uri getAdnUriForPhoneAccount(PhoneAccountHandle accountHandle) {
+            enforceModifyPermissionOrDefaultDialer();
+
+            if (!isVisibleToCaller(accountHandle)) {
+                Log.w(this, "%s is not visible for the calling user", accountHandle);
+                return null;
+            }
+
+            // Switch identity so that TelephonyManager checks Telecom's permissions instead.
+            long token = Binder.clearCallingIdentity();
+            String retval = "content://icc/adn/";
+            try {
+                long subId = mPhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(accountHandle);
+                retval = retval + "subId/" + subId;
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+
+            return Uri.parse(retval);
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#isTtySupported
+         */
+        @Override
+        public boolean isTtySupported() {
+            enforceReadPermission();
+            return (boolean) sendRequest(MSG_IS_TTY_SUPPORTED);
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#getCurrentTtyMode
+         */
+        @Override
+        public int getCurrentTtyMode() {
+            enforceReadPermission();
+            return (int) sendRequest(MSG_GET_CURRENT_TTY_MODE);
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#addNewIncomingCall
+         */
+        @Override
+        public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
+            Log.i(this, "Adding new incoming call with phoneAccountHandle %s", phoneAccountHandle);
+            if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null) {
+                // TODO(sail): Add unit tests for adding incoming calls from a SIM call manager.
+                if (isCallerSimCallManager() && TelephonyUtil.isPstnComponentName(
+                        phoneAccountHandle.getComponentName())) {
+                    Log.v(this, "Allowing call manager to add incoming call with PSTN handle");
+                } else {
+                    mAppOpsManager.checkPackage(Binder.getCallingUid(),
+                            phoneAccountHandle.getComponentName().getPackageName());
+
+                    enforcePhoneAccountIsRegistered(phoneAccountHandle);
+                    // Make sure it doesn't cross the UserHandle boundary
+                    enforceUserHandleMatchesCaller(phoneAccountHandle);
+                }
+
+                Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL);
+                intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
+                intent.putExtra(CallReceiver.KEY_IS_INCOMING_CALL, true);
+                if (extras != null) {
+                    intent.putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras);
+                }
+                sendRequestAsync(MSG_NEW_INCOMING_CALL, 0, intent);
+            } else {
+                Log.w(this, "Null phoneAccountHandle. Ignoring request to add new incoming call");
+            }
+        }
+
+        /**
+         * @see android.telecom.TelecomManager#addNewUnknownCall
+         */
+        @Override
+        public void addNewUnknownCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
+            if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null &&
+                    TelephonyUtil.isPstnComponentName(phoneAccountHandle.getComponentName())) {
+                mAppOpsManager.checkPackage(
+                        Binder.getCallingUid(), phoneAccountHandle.getComponentName().getPackageName());
+
+                enforcePhoneAccountIsRegistered(phoneAccountHandle);
+                // Make sure it doesn't cross the UserHandle boundary
+                enforceUserHandleMatchesCaller(phoneAccountHandle);
+
+                Intent intent = new Intent(TelecomManager.ACTION_NEW_UNKNOWN_CALL);
+                intent.setClass(mContext, CallReceiver.class);
+                intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+                intent.putExtras(extras);
+                intent.putExtra(CallReceiver.KEY_IS_UNKNOWN_CALL, true);
+                intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
+                mContext.sendBroadcastAsUser(intent, phoneAccountHandle.getUserHandle());
+            } else {
+                Log.i(this, "Null phoneAccountHandle or not initiated by Telephony. Ignoring request"
+                        + " to add new unknown call.");
+            }
+        }
+
+        /**
+         * Dumps the current state of the TelecomService.  Used when generating problem reports.
+         *
+         * @param fd The file descriptor.
+         * @param writer The print writer to dump the state to.
+         * @param args Optional dump arguments.
+         */
+        @Override
+        protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
+            if (mContext.checkCallingOrSelfPermission(
+                    android.Manifest.permission.DUMP)
+                    != PackageManager.PERMISSION_GRANTED) {
+                writer.println("Permission Denial: can't dump TelecomService " +
+                        "from from pid=" + Binder.getCallingPid() + ", uid=" +
+                        Binder.getCallingUid());
+                return;
+            }
+
+            final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
+            if (mCallsManager != null) {
+                pw.println("mCallsManager: ");
+                pw.increaseIndent();
+                mCallsManager.dump(pw);
+                pw.decreaseIndent();
+
+                pw.println("mPhoneAccountRegistrar: ");
+                pw.increaseIndent();
+                mPhoneAccountRegistrar.dump(pw);
+                pw.decreaseIndent();
+            }
+        }
+    }
+
+    //
+    // Supporting methods for the ITelecomService interface implementation.
+    //
+
+    private boolean isVisibleToCaller(PhoneAccountHandle accountHandle) {
+        if (accountHandle == null) {
+            return false;
+        }
+
+        return isVisibleToCaller(mPhoneAccountRegistrar.getPhoneAccountInternal(accountHandle));
+    }
+
+    private boolean isVisibleToCaller(PhoneAccount account) {
+        if (account == null) {
+            return false;
+        }
+
+        // If this PhoneAccount has CAPABILITY_MULTI_USER, it should be visible to all users and
+        // all profiles. Only Telephony and SIP accounts should have this capability.
+        if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
+            return true;
+        }
+
+        UserHandle phoneAccountUserHandle = account.getAccountHandle().getUserHandle();
+        if (phoneAccountUserHandle == null) {
+            return false;
+        }
+
+        List<UserHandle> profileUserHandles;
+        if (isCallerSystemApp()) {
+            // If the caller lives in /system/priv-app, it can see PhoneAccounts for all of the
+            // *profiles* that the calling user owns, but not for any other *users*.
+            profileUserHandles = mUserManager.getUserProfiles();
+        } else {
+            // Otherwise, it has to be owned by the current caller's profile.
+            profileUserHandles = new ArrayList<>(1);
+            profileUserHandles.add(Binder.getCallingUserHandle());
+        }
+
+        return profileUserHandles.contains(phoneAccountUserHandle);
+    }
+
+    /**
+     * Given a list of {@link PhoneAccountHandle}s, filter them to the ones that the calling
+     * user can see.
+     *
+     * @param phoneAccountHandles Unfiltered list of account handles.
+     *
+     * @return {@link PhoneAccountHandle}s visible to the calling user and its profiles.
+     */
+    private List<PhoneAccountHandle> filterForAccountsVisibleToCaller(
+            List<PhoneAccountHandle> phoneAccountHandles) {
+        List<PhoneAccountHandle> profilePhoneAccountHandles =
+                new ArrayList<>(phoneAccountHandles.size());
+        for (PhoneAccountHandle phoneAccountHandle : phoneAccountHandles) {
+            if (isVisibleToCaller(phoneAccountHandle)) {
+                profilePhoneAccountHandles.add(phoneAccountHandle);
+            }
+        }
+        return profilePhoneAccountHandles;
+    }
+
+    private boolean isCallerSystemApp() {
+        int uid = Binder.getCallingUid();
+        String[] packages = mPackageManager.getPackagesForUid(uid);
+        for (String packageName : packages) {
+            if (isPackageSystemApp(packageName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isPackageSystemApp(String packageName) {
+        try {
+            ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(packageName,
+                    PackageManager.GET_META_DATA);
+            if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                return true;
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+        }
+        return false;
+    }
+
+    private void acceptRingingCallInternal() {
+        Call call = mCallsManager.getFirstCallWithState(CallState.RINGING);
+        if (call != null) {
+            call.answer(call.getVideoState());
+        }
+    }
+
+    private boolean endCallInternal() {
+        // Always operate on the foreground call if one exists, otherwise get the first call in
+        // priority order by call-state.
+        Call call = mCallsManager.getForegroundCall();
+        if (call == null) {
+            call = mCallsManager.getFirstCallWithState(
+                    CallState.ACTIVE,
+                    CallState.DIALING,
+                    CallState.RINGING,
+                    CallState.ON_HOLD);
+        }
+
+        if (call != null) {
+            if (call.getState() == CallState.RINGING) {
+                call.reject(false /* rejectWithMessage */, null);
+            } else {
+                call.disconnect();
+            }
+            return true;
+        }
+
+        return false;
+    }
+
+    // Enforce that the PhoneAccountHandle being passed in is registered to a valid PhoneAccount. 
+    private void enforcePhoneAccountIsRegistered(PhoneAccountHandle phoneAccountHandle) {
+        PhoneAccount phoneAccount = mPhoneAccountRegistrar.getPhoneAccount(phoneAccountHandle);
+        if(phoneAccount == null) {
+            EventLog.writeEvent(0x534e4554, "26864502", Binder.getCallingUid(), "R");
+            throw new SecurityException("This PhoneAccountHandle is not registered to a valid " +
+                    "PhoneAccount!");
+        }
+    }
+
+    private void enforcePhoneAccountModificationForPackage(String packageName) {
+        // TODO: Use a new telecomm permission for this instead of reusing modify.
+
+        int result = mContext.checkCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
+
+        // Callers with MODIFY_PHONE_STATE can use the PhoneAccount mechanism to implement
+        // built-in behavior even when PhoneAccounts are not exposed as a third-part API. They
+        // may also modify PhoneAccounts on behalf of any 'packageName'.
+
+        if (result != PackageManager.PERMISSION_GRANTED) {
+            // Other callers are only allowed to modify PhoneAccounts if the relevant system
+            // feature is enabled ...
+            enforceConnectionServiceFeature();
+            // ... and the PhoneAccounts they refer to are for their own package.
+            enforceCallingPackage(packageName);
+        }
+    }
+
+    private void enforceReadPermissionOrDefaultDialer() {
+        if (!isDefaultDialerCalling()) {
+            enforceReadPermission();
+        }
+    }
+
+    private void enforceModifyPermissionOrDefaultDialer() {
+        if (!isDefaultDialerCalling()) {
+            enforceModifyPermission();
+        }
+    }
+
+    private void enforceCallingPackage(String packageName) {
+        mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
+    }
+
+    private void enforceConnectionServiceFeature() {
+        enforceFeature(PackageManager.FEATURE_CONNECTION_SERVICE);
+    }
+
+    private void enforceRegisterCallProviderPermission() {
+        enforcePermission(android.Manifest.permission.REGISTER_CALL_PROVIDER);
+    }
+
+    private void enforceRegisterSimSubscriptionPermission() {
+        enforcePermission(android.Manifest.permission.REGISTER_SIM_SUBSCRIPTION);
+    }
+
+    private void enforceRegisterConnectionManagerPermission() {
+        enforcePermission(android.Manifest.permission.REGISTER_CONNECTION_MANAGER);
+    }
+
+    private void enforceReadPermission() {
+        enforcePermission(Manifest.permission.READ_PHONE_STATE);
+    }
+
+    private void enforceModifyPermission() {
+        enforcePermission(Manifest.permission.MODIFY_PHONE_STATE);
+    }
+
+    private void enforcePermission(String permission) {
+        mContext.enforceCallingOrSelfPermission(permission, null);
+    }
+
+    private void enforceRegisterMultiUser() {
+        if (!isCallerSystemApp()) {
+            throw new SecurityException("CAPABILITY_MULTI_USER 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");
+        }
+    }
+
+    private void enforceFeature(String feature) {
+        PackageManager pm = mContext.getPackageManager();
+        if (!pm.hasSystemFeature(feature)) {
+            throw new UnsupportedOperationException(
+                    "System does not support feature " + feature);
+        }
+    }
+
+    private boolean isCallerSimCallManager() {
+        PhoneAccountHandle accountHandle = mPhoneAccountRegistrar.getSimCallManager();
+        if (accountHandle != null) {
+            try {
+                mAppOpsManager.checkPackage(
+                        Binder.getCallingUid(), accountHandle.getComponentName().getPackageName());
+                return true;
+            } catch (SecurityException e) {
+            }
+        }
+        return false;
+    }
+
+    private boolean isDefaultDialerCalling() {
+        ComponentName defaultDialerComponent = getDefaultPhoneAppInternal();
+        if (defaultDialerComponent != null) {
+            try {
+                mAppOpsManager.checkPackage(
+                        Binder.getCallingUid(), defaultDialerComponent.getPackageName());
+                return true;
+            } catch (SecurityException e) {
+                Log.e(TAG, e, "Could not get default dialer.");
+            }
+        }
+        return false;
+    }
+
+    private ComponentName getDefaultPhoneAppInternal() {
+        Resources resources = mContext.getResources();
+        return new ComponentName(
+                resources.getString(R.string.ui_default_package),
+                resources.getString(R.string.dialer_default_class));
+    }
+
+    private TelephonyManager getTelephonyManager() {
+        return (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
+    }
+
+    private MainThreadRequest sendRequestAsync(int command, int arg1) {
+        return sendRequestAsync(command, arg1, null);
+    }
+
+    private MainThreadRequest sendRequestAsync(int command, int arg1, Object arg) {
+        MainThreadRequest request = new MainThreadRequest();
+        request.arg = arg;
+        mMainThreadHandler.obtainMessage(command, arg1, 0, request).sendToTarget();
+        return request;
+    }
+
+    /**
+     * Posts the specified command to be executed on the main thread, waits for the request to
+     * complete, and returns the result.
+     */
+    private Object sendRequest(int command) {
+        if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
+            MainThreadRequest request = new MainThreadRequest();
+            mMainThreadHandler.handleMessage(mMainThreadHandler.obtainMessage(command, request));
+            return request.result;
+        } else {
+            MainThreadRequest request = sendRequestAsync(command, 0);
+
+            // Wait for the request to complete
+            synchronized (request) {
+                while (request.result == null) {
+                    try {
+                        request.wait();
+                    } catch (InterruptedException e) {
+                        // Do nothing, go back and wait until the request is complete
+                    }
+                }
+            }
+            return request.result;
+        }
+    }
+}
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
deleted file mode 100644
index 094d8ca..0000000
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ /dev/null
@@ -1,694 +0,0 @@
-/*
- * Copyright (C) 2014 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.app.AppOpsManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-import android.telecom.CallState;
-import android.telecom.PhoneAccount;
-import android.telecom.PhoneAccountHandle;
-import android.telecom.TelecomManager;
-import android.telephony.PhoneNumberUtils;
-import android.telephony.TelephonyManager;
-
-import android.util.EventLog;
-
-// TODO: Needed for move to system service: import com.android.internal.R;
-import com.android.internal.telecom.ITelecomService;
-import com.android.internal.util.IndentingPrintWriter;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.List;
-
-/**
- * Implementation of the ITelecom interface.
- */
-public class TelecomServiceImpl extends ITelecomService.Stub {
-    private static final String REGISTER_PROVIDER_OR_SUBSCRIPTION =
-            "com.android.server.telecom.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION";
-    private static final String REGISTER_CONNECTION_MANAGER =
-            "com.android.server.telecom.permission.REGISTER_CONNECTION_MANAGER";
-
-    /** The context. */
-    private Context mContext;
-
-    /** ${inheritDoc} */
-    @Override
-    public IBinder asBinder() {
-        return super.asBinder();
-    }
-
- /**
-     * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
-     * request after sending. The main thread will notify the request when it is complete.
-     */
-    private static final class MainThreadRequest {
-        /** The result of the request that is run on the main thread */
-        public Object result;
-    }
-
-    /**
-     * A handler that processes messages on the main thread in the phone process. Since many
-     * of the Phone calls are not thread safe this is needed to shuttle the requests from the
-     * inbound binder threads to the main thread in the phone process.
-     */
-    private final class MainThreadHandler extends Handler {
-        @Override
-        public void handleMessage(Message msg) {
-            if (msg.obj instanceof MainThreadRequest) {
-                MainThreadRequest request = (MainThreadRequest) msg.obj;
-                Object result = null;
-                switch (msg.what) {
-                    case MSG_SILENCE_RINGER:
-                        mCallsManager.getRinger().silence();
-                        break;
-                    case MSG_SHOW_CALL_SCREEN:
-                        mCallsManager.getInCallController().bringToForeground(msg.arg1 == 1);
-                        break;
-                    case MSG_END_CALL:
-                        result = endCallInternal();
-                        break;
-                    case MSG_ACCEPT_RINGING_CALL:
-                        acceptRingingCallInternal();
-                        break;
-                    case MSG_CANCEL_MISSED_CALLS_NOTIFICATION:
-                        mMissedCallNotifier.clearMissedCalls();
-                        break;
-                    case MSG_IS_TTY_SUPPORTED:
-                        result = mCallsManager.isTtySupported();
-                        break;
-                    case MSG_GET_CURRENT_TTY_MODE:
-                        result = mCallsManager.getCurrentTtyMode();
-                        break;
-                }
-
-                if (result != null) {
-                    request.result = result;
-                    synchronized(request) {
-                        request.notifyAll();
-                    }
-                }
-            }
-        }
-    }
-
-    /** Private constructor; @see init() */
-    private static final String TAG = TelecomServiceImpl.class.getSimpleName();
-
-    private static final String SERVICE_NAME = "telecom";
-
-    private static final int MSG_SILENCE_RINGER = 1;
-    private static final int MSG_SHOW_CALL_SCREEN = 2;
-    private static final int MSG_END_CALL = 3;
-    private static final int MSG_ACCEPT_RINGING_CALL = 4;
-    private static final int MSG_CANCEL_MISSED_CALLS_NOTIFICATION = 5;
-    private static final int MSG_IS_TTY_SUPPORTED = 6;
-    private static final int MSG_GET_CURRENT_TTY_MODE = 7;
-
-    /** The singleton instance. */
-    private static TelecomServiceImpl sInstance;
-
-    private final MainThreadHandler mMainThreadHandler = new MainThreadHandler();
-    private final CallsManager mCallsManager;
-    private final MissedCallNotifier mMissedCallNotifier;
-    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
-    private final AppOpsManager mAppOpsManager;
-
-    public TelecomServiceImpl(
-            MissedCallNotifier missedCallNotifier, PhoneAccountRegistrar phoneAccountRegistrar,
-            CallsManager callsManager, Context context) {
-        mMissedCallNotifier = missedCallNotifier;
-        mPhoneAccountRegistrar = phoneAccountRegistrar;
-        mCallsManager = callsManager;
-        mContext = context;
-        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
-    }
-
-    //
-    // Implementation of the ITelecomService interface.
-    //
-
-    @Override
-    public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme) {
-        try {
-            return mPhoneAccountRegistrar.getDefaultOutgoingPhoneAccount(uriScheme);
-        } catch (Exception e) {
-            Log.e(this, e, "getDefaultOutgoingPhoneAccount");
-            throw e;
-        }
-    }
-
-    @Override
-    public PhoneAccountHandle getUserSelectedOutgoingPhoneAccount() {
-        try {
-            return mPhoneAccountRegistrar.getUserSelectedOutgoingPhoneAccount();
-        } catch (Exception e) {
-            Log.e(this, e, "getUserSelectedOutgoingPhoneAccount");
-            throw e;
-        }
-    }
-
-    @Override
-    public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
-        enforceModifyPermission();
-
-        try {
-            mPhoneAccountRegistrar.setUserSelectedOutgoingPhoneAccount(accountHandle);
-        } catch (Exception e) {
-            Log.e(this, e, "setUserSelectedOutgoingPhoneAccount");
-            throw e;
-        }
-    }
-
-    @Override
-    public List<PhoneAccountHandle> getCallCapablePhoneAccounts() {
-        try {
-            return mPhoneAccountRegistrar.getCallCapablePhoneAccounts();
-        } catch (Exception e) {
-            Log.e(this, e, "getCallCapablePhoneAccounts");
-            throw e;
-        }
-    }
-
-    @Override
-    public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme) {
-        try {
-            return mPhoneAccountRegistrar.getCallCapablePhoneAccounts(uriScheme);
-        } catch (Exception e) {
-            Log.e(this, e, "getPhoneAccountsSupportingScheme");
-            throw e;
-        }
-    }
-
-    @Override
-    public List<PhoneAccountHandle> getPhoneAccountsForPackage(String packageName) {
-        try {
-            return mPhoneAccountRegistrar.getPhoneAccountsForPackage(packageName);
-        } catch (Exception e) {
-            Log.e(this, e, "getPhoneAccountsForPackage");
-            throw e;
-        }
-    }
-
-    @Override
-    public PhoneAccount getPhoneAccount(PhoneAccountHandle accountHandle) {
-        try {
-            return mPhoneAccountRegistrar.getPhoneAccount(accountHandle);
-        } catch (Exception e) {
-            Log.e(this, e, "getPhoneAccount %s", accountHandle);
-            throw e;
-        }
-    }
-
-    @Override
-    public int getAllPhoneAccountsCount() {
-        try {
-            return mPhoneAccountRegistrar.getAllPhoneAccountsCount();
-        } catch (Exception e) {
-            Log.e(this, e, "getAllPhoneAccountsCount");
-            throw e;
-        }
-    }
-
-    @Override
-    public List<PhoneAccount> getAllPhoneAccounts() {
-        try {
-            return mPhoneAccountRegistrar.getAllPhoneAccounts();
-        } catch (Exception e) {
-            Log.e(this, e, "getAllPhoneAccounts");
-            throw e;
-        }
-    }
-
-    @Override
-    public List<PhoneAccountHandle> getAllPhoneAccountHandles() {
-        try {
-            return mPhoneAccountRegistrar.getAllPhoneAccountHandles();
-        } catch (Exception e) {
-            Log.e(this, e, "getAllPhoneAccounts");
-            throw e;
-        }
-    }
-
-    @Override
-    public PhoneAccountHandle getSimCallManager() {
-        try {
-            return mPhoneAccountRegistrar.getSimCallManager();
-        } catch (Exception e) {
-            Log.e(this, e, "getSimCallManager");
-            throw e;
-        }
-    }
-
-    @Override
-    public void setSimCallManager(PhoneAccountHandle accountHandle) {
-        enforceModifyPermission();
-
-        try {
-            mPhoneAccountRegistrar.setSimCallManager(accountHandle);
-        } catch (Exception e) {
-            Log.e(this, e, "setSimCallManager");
-            throw e;
-        }
-    }
-
-    @Override
-    public List<PhoneAccountHandle> getSimCallManagers() {
-        try {
-            return mPhoneAccountRegistrar.getConnectionManagerPhoneAccounts();
-        } catch (Exception e) {
-            Log.e(this, e, "getSimCallManagers");
-            throw e;
-        }
-    }
-
-    @Override
-    public void registerPhoneAccount(PhoneAccount account) {
-        try {
-            enforcePhoneAccountModificationForPackage(
-                    account.getAccountHandle().getComponentName().getPackageName());
-            if (account.hasCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) ||
-                account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
-                enforceRegisterProviderOrSubscriptionPermission();
-            }
-            if (account.hasCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)) {
-                enforceRegisterConnectionManagerPermission();
-            }
-
-            mPhoneAccountRegistrar.registerPhoneAccount(account);
-        } catch (Exception e) {
-            Log.e(this, e, "registerPhoneAccount %s", account);
-            throw e;
-        }
-    }
-
-    @Override
-    public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
-        try {
-            enforcePhoneAccountModificationForPackage(
-                    accountHandle.getComponentName().getPackageName());
-            mPhoneAccountRegistrar.unregisterPhoneAccount(accountHandle);
-        } catch (Exception e) {
-            Log.e(this, e, "unregisterPhoneAccount %s", accountHandle);
-            throw e;
-        }
-    }
-
-    @Override
-    public void clearAccounts(String packageName) {
-        try {
-            enforcePhoneAccountModificationForPackage(packageName);
-            mPhoneAccountRegistrar.clearAccounts(packageName);
-        } catch (Exception e) {
-            Log.e(this, e, "clearAccounts %s", packageName);
-            throw e;
-        }
-    }
-
-    /**
-     * @see android.telecom.TelecomManager#isVoiceMailNumber
-     */
-    @Override
-    public boolean isVoiceMailNumber(PhoneAccountHandle accountHandle, String number) {
-        enforceReadPermissionOrDefaultDialer();
-        try {
-            return mPhoneAccountRegistrar.isVoiceMailNumber(accountHandle, number);
-        } catch (Exception e) {
-            Log.e(this, e, "getSubscriptionIdForPhoneAccount");
-            throw e;
-        }
-    }
-
-    /**
-     * @see android.telecom.TelecomManager#silenceRinger
-     */
-    @Override
-    public void silenceRinger() {
-        Log.d(this, "silenceRinger");
-        enforceModifyPermission();
-        sendRequestAsync(MSG_SILENCE_RINGER, 0);
-    }
-
-    /**
-     * @see android.telecom.TelecomManager#getDefaultPhoneApp
-     */
-    @Override
-    public ComponentName getDefaultPhoneApp() {
-        Resources resources = mContext.getResources();
-        return new ComponentName(
-                resources.getString(R.string.ui_default_package),
-                resources.getString(R.string.dialer_default_class));
-    }
-
-    /**
-     * @see android.telecom.TelecomManager#isInCall
-     */
-    @Override
-    public boolean isInCall() {
-        enforceReadPermission();
-        // Do not use sendRequest() with this method since it could cause a deadlock with
-        // audio service, which we call into from the main thread: AudioManager.setMode().
-        final int callState = mCallsManager.getCallState();
-        return callState == TelephonyManager.CALL_STATE_OFFHOOK
-                || callState == TelephonyManager.CALL_STATE_RINGING;
-    }
-
-    /**
-     * @see android.telecom.TelecomManager#isRinging
-     */
-    @Override
-    public boolean isRinging() {
-        enforceReadPermission();
-        return mCallsManager.getCallState() == TelephonyManager.CALL_STATE_RINGING;
-    }
-
-    /**
-     * @see TelecomManager#getCallState
-     */
-    @Override
-    public int getCallState() {
-        return mCallsManager.getCallState();
-    }
-
-    /**
-     * @see android.telecom.TelecomManager#endCall
-     */
-    @Override
-    public boolean endCall() {
-        enforceModifyPermission();
-        return (boolean) sendRequest(MSG_END_CALL);
-    }
-
-    /**
-     * @see android.telecom.TelecomManager#acceptRingingCall
-     */
-    @Override
-    public void acceptRingingCall() {
-        enforceModifyPermission();
-        sendRequestAsync(MSG_ACCEPT_RINGING_CALL, 0);
-    }
-
-    /**
-     * @see android.telecom.TelecomManager#showInCallScreen
-     */
-    @Override
-    public void showInCallScreen(boolean showDialpad) {
-        enforceReadPermissionOrDefaultDialer();
-        sendRequestAsync(MSG_SHOW_CALL_SCREEN, showDialpad ? 1 : 0);
-    }
-
-    /**
-     * @see android.telecom.TelecomManager#cancelMissedCallsNotification
-     */
-    @Override
-    public void cancelMissedCallsNotification() {
-        enforceModifyPermissionOrDefaultDialer();
-        sendRequestAsync(MSG_CANCEL_MISSED_CALLS_NOTIFICATION, 0);
-    }
-
-    /**
-     * @see android.telecom.TelecomManager#handleMmi
-     */
-    @Override
-    public boolean handlePinMmi(String dialString) {
-        enforceModifyPermissionOrDefaultDialer();
-
-        // Switch identity so that TelephonyManager checks Telecom's permissions instead.
-        long token = Binder.clearCallingIdentity();
-        boolean retval = false;
-        try {
-            retval = getTelephonyManager().handlePinMmi(dialString);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-
-        return retval;
-    }
-
-    /**
-     * @see android.telecom.TelecomManager#isTtySupported
-     */
-    @Override
-    public boolean isTtySupported() {
-        enforceReadPermission();
-        return (boolean) sendRequest(MSG_IS_TTY_SUPPORTED);
-    }
-
-    /**
-     * @see android.telecom.TelecomManager#getCurrentTtyMode
-     */
-    @Override
-    public int getCurrentTtyMode() {
-        enforceReadPermission();
-        return (int) sendRequest(MSG_GET_CURRENT_TTY_MODE);
-    }
-
-    /**
-     * @see android.telecom.TelecomManager#addNewIncomingCall
-     */
-    @Override
-    public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
-        if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null) {
-            mAppOpsManager.checkPackage(
-                    Binder.getCallingUid(), phoneAccountHandle.getComponentName().getPackageName());
-            enforcePhoneAccountIsRegistered(phoneAccountHandle);
-
-            Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL);
-            intent.setPackage(mContext.getPackageName());
-            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
-            if (extras != null) {
-                intent.putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras);
-            }
-
-            long token = Binder.clearCallingIdentity();
-            mContext.startActivityAsUser(intent, UserHandle.CURRENT);
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    /**
-     * @see android.telecom.TelecomManager#addNewUnknownCall
-     */
-    @Override
-    public void addNewUnknownCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
-        if (phoneAccountHandle != null && phoneAccountHandle.getComponentName() != null &&
-                TelephonyUtil.isPstnComponentName(phoneAccountHandle.getComponentName())) {
-            mAppOpsManager.checkPackage(
-                    Binder.getCallingUid(), phoneAccountHandle.getComponentName().getPackageName());
-            enforcePhoneAccountIsRegistered(phoneAccountHandle);
-
-            Intent intent = new Intent(TelecomManager.ACTION_NEW_UNKNOWN_CALL);
-            intent.setClass(mContext, CallReceiver.class);
-            intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-            intent.putExtras(extras);
-            intent.putExtra(CallReceiver.KEY_IS_UNKNOWN_CALL, true);
-            intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
-            mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);
-        } else {
-            Log.i(this, "Null phoneAccountHandle or not initiated by Telephony. Ignoring request"
-                    + " to add new unknown call.");
-        }
-    }
-
-    //
-    // Supporting methods for the ITelecomService interface implementation.
-    //
-
-    private void acceptRingingCallInternal() {
-        Call call = mCallsManager.getFirstCallWithState(CallState.RINGING);
-        if (call != null) {
-            call.answer(call.getVideoState());
-        }
-    }
-
-    private boolean endCallInternal() {
-        // Always operate on the foreground call if one exists, otherwise get the first call in
-        // priority order by call-state.
-        Call call = mCallsManager.getForegroundCall();
-        if (call == null) {
-            call = mCallsManager.getFirstCallWithState(
-                    CallState.ACTIVE,
-                    CallState.DIALING,
-                    CallState.RINGING,
-                    CallState.ON_HOLD);
-        }
-
-        if (call != null) {
-            if (call.getState() == CallState.RINGING) {
-                call.reject(false /* rejectWithMessage */, null);
-            } else {
-                call.disconnect();
-            }
-            return true;
-        }
-
-        return false;
-    }
-
-    // Enforce that the PhoneAccountHandle being passed in is registered to a valid PhoneAccount.
-    private void enforcePhoneAccountIsRegistered(PhoneAccountHandle phoneAccountHandle) {
-        PhoneAccount phoneAccount = mPhoneAccountRegistrar.getPhoneAccount(phoneAccountHandle);
-        if(phoneAccount == null) {
-            EventLog.writeEvent(0x534e4554, "26864502", Binder.getCallingUid(), "R");
-            throw new SecurityException("This PhoneAccountHandle is not registered to a valid " +
-                    "PhoneAccount!");
-        }
-    }
-
-    private void enforcePhoneAccountModificationForPackage(String packageName) {
-        // TODO: Use a new telecomm permission for this instead of reusing modify.
-
-        int result = mContext.checkCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
-
-        // Callers with MODIFY_PHONE_STATE can use the PhoneAccount mechanism to implement
-        // built-in behavior even when PhoneAccounts are not exposed as a third-part API. They
-        // may also modify PhoneAccounts on behalf of any 'packageName'.
-
-        if (result != PackageManager.PERMISSION_GRANTED) {
-            // Other callers are only allowed to modify PhoneAccounts if the relevant system
-            // feature is enabled ...
-            enforceConnectionServiceFeature();
-            // ... and the PhoneAccounts they refer to are for their own package.
-            enforceCallingPackage(packageName);
-        }
-    }
-
-    private void enforceReadPermissionOrDefaultDialer() {
-        if (!isDefaultDialerCalling()) {
-            enforceReadPermission();
-        }
-    }
-
-    private void enforceModifyPermissionOrDefaultDialer() {
-        if (!isDefaultDialerCalling()) {
-            enforceModifyPermission();
-        }
-    }
-
-    private void enforceCallingPackage(String packageName) {
-        mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
-    }
-
-    private void enforceConnectionServiceFeature() {
-        enforceFeature(PackageManager.FEATURE_CONNECTION_SERVICE);
-    }
-
-    private void enforceRegisterProviderOrSubscriptionPermission() {
-        enforcePermission(REGISTER_PROVIDER_OR_SUBSCRIPTION);
-    }
-
-    private void enforceRegisterConnectionManagerPermission() {
-        enforcePermission(REGISTER_CONNECTION_MANAGER);
-    }
-
-    private void enforceReadPermission() {
-        enforcePermission(Manifest.permission.READ_PHONE_STATE);
-    }
-
-    private void enforceModifyPermission() {
-        enforcePermission(Manifest.permission.MODIFY_PHONE_STATE);
-    }
-
-    private void enforcePermission(String permission) {
-        mContext.enforceCallingOrSelfPermission(permission, null);
-    }
-
-    private void enforceFeature(String feature) {
-        PackageManager pm = mContext.getPackageManager();
-        if (!pm.hasSystemFeature(feature)) {
-            throw new UnsupportedOperationException(
-                    "System does not support feature " + feature);
-        }
-    }
-
-    private boolean isDefaultDialerCalling() {
-        ComponentName defaultDialerComponent = getDefaultPhoneApp();
-        if (defaultDialerComponent != null) {
-            try {
-                mAppOpsManager.checkPackage(
-                        Binder.getCallingUid(), defaultDialerComponent.getPackageName());
-                return true;
-            } catch (SecurityException e) {
-                Log.e(TAG, e, "Could not get default dialer.");
-            }
-        }
-        return false;
-    }
-
-    private TelephonyManager getTelephonyManager() {
-        return (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
-    }
-
-    private MainThreadRequest sendRequestAsync(int command, int arg1) {
-        MainThreadRequest request = new MainThreadRequest();
-        mMainThreadHandler.obtainMessage(command, arg1, 0, request).sendToTarget();
-        return request;
-    }
-
-    /**
-     * Posts the specified command to be executed on the main thread, waits for the request to
-     * complete, and returns the result.
-     */
-    private Object sendRequest(int command) {
-        if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
-            MainThreadRequest request = new MainThreadRequest();
-            mMainThreadHandler.handleMessage(mMainThreadHandler.obtainMessage(command, request));
-            return request.result;
-        } else {
-            MainThreadRequest request = sendRequestAsync(command, 0);
-
-            // Wait for the request to complete
-            synchronized (request) {
-                while (request.result == null) {
-                    try {
-                        request.wait();
-                    } catch (InterruptedException e) {
-                        // Do nothing, go back and wait until the request is complete
-                    }
-                }
-            }
-            return request.result;
-        }
-    }
-
-    @Override
-    protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
-        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
-        if (mCallsManager != null) {
-            pw.println("mCallsManager: ");
-            pw.increaseIndent();
-            mCallsManager.dump(pw);
-            pw.decreaseIndent();
-        }
-    }
-}
diff --git a/src/com/android/server/telecom/Timeouts.java b/src/com/android/server/telecom/Timeouts.java
index 35f61ae..b5cf39a 100644
--- a/src/com/android/server/telecom/Timeouts.java
+++ b/src/com/android/server/telecom/Timeouts.java
@@ -52,4 +52,41 @@
     public static long getDirectToVoicemailMillis(ContentResolver contentResolver) {
         return get(contentResolver, "direct_to_voicemail_ms", 500L);
     }
+
+    /**
+     * Returns the amount of time to wait before disconnecting a call that was canceled via
+     * NEW_OUTGOING_CALL broadcast. This timeout allows apps which repost the call using a gateway
+     * to reuse the existing call, preventing the call from causing a start->end->start jank in the
+     * in-call UI.
+     */
+    public static long getNewOutgoingCallCancelMillis(ContentResolver contentResolver) {
+        return get(contentResolver, "new_outgoing_call_cancel_ms", 300L);
+    }
+
+    /**
+     * Returns the amount of time to play each DTMF tone after post dial continue.
+     * This timeout allows the current tone to play for a certain amount of time before either being
+     * interrupted by the next tone or terminated.
+     */
+    public static long getDelayBetweenDtmfTonesMillis(ContentResolver contentResolver) {
+        return get(contentResolver, "delay_between_dtmf_tones_ms", 300L);
+    }
+
+    /**
+     * Returns the amount of time to wait for an emergency call to be placed before routing to
+     * a different call service. A value of 0 or less means no timeout should be used.
+     */
+    public static long getEmergencyCallTimeoutMillis(ContentResolver contentResolver) {
+        return get(contentResolver, "emergency_call_timeout_millis", 25000L /* 25 seconds */);
+    }
+
+    /**
+     * Returns the amount of time to wait for an emergency call to be placed before routing to
+     * a different call service. This timeout is used only when the radio is powered off (for
+     * example in airplane mode). A value of 0 or less means no timeout should be used.
+     */
+    public static long getEmergencyCallTimeoutRadioOffMillis(ContentResolver contentResolver) {
+        return get(contentResolver, "emergency_call_timeout_radio_off_millis",
+                60000L /* 1 minute */);
+    }
 }
diff --git a/src/com/android/server/telecom/TtyManager.java b/src/com/android/server/telecom/TtyManager.java
index b21f165..e0a9e9c 100644
--- a/src/com/android/server/telecom/TtyManager.java
+++ b/src/com/android/server/telecom/TtyManager.java
@@ -25,6 +25,8 @@
 import android.provider.Settings;
 import android.telecom.TelecomManager;
 
+import com.android.internal.util.IndentingPrintWriter;
+
 // TODO: Needed for move to system service: import com.android.internal.R;
 
 final class TtyManager implements WiredHeadsetManager.Listener {
@@ -122,4 +124,13 @@
             }
         }
     }
+
+    /**
+     * Dumps the state of the {@link TtyManager}.
+     *
+     * @param pw The {@code IndentingPrintWriter} to write the state to.
+     */
+    public void dump(IndentingPrintWriter pw) {
+        pw.println("mCurrentTtyMode: " + mCurrentTtyMode);
+    }
 }
diff --git a/src/com/android/server/telecom/WiredHeadsetManager.java b/src/com/android/server/telecom/WiredHeadsetManager.java
index 8ce7b61..a61dd6e 100644
--- a/src/com/android/server/telecom/WiredHeadsetManager.java
+++ b/src/com/android/server/telecom/WiredHeadsetManager.java
@@ -22,6 +22,8 @@
 import android.content.IntentFilter;
 import android.media.AudioManager;
 
+import com.android.internal.util.IndentingPrintWriter;
+
 import java.util.Collections;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
@@ -91,4 +93,13 @@
             }
         }
     }
+
+    /**
+     * Dumps the state of the {@link WiredHeadsetManager}.
+     *
+     * @param pw The {@code IndentingPrintWriter} to write the state to.
+     */
+    public void dump(IndentingPrintWriter pw) {
+        pw.println("mIsPluggedIn: " + mIsPluggedIn);
+    }
 }
diff --git a/tests/Android.mk b/tests/Android.mk
index b122183..f293b80 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -20,6 +20,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
         android-ex-camera2 \
         guava \
+        mockito-target \
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 9c09a40..e987dee 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -19,11 +19,11 @@
           package="com.android.server.telecom.tests"
           android:debuggable="true">
 
-    <!-- Test connection service outgoing video preview. -->
     <uses-permission android:name="android.permission.CAMERA" />
-    <uses-permission
-            android:name="com.android.server.telecom.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION" />
     <uses-permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE" />
+    <uses-permission android:name="android.permission.REGISTER_CALL_PROVIDER" />
+    <uses-permission android:name="android.permission.REGISTER_CONNECTION_MANAGER" />
+    <uses-permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION" />
 
     <application android:label="@string/app_name"
                  android:debuggable="true">
@@ -72,6 +72,7 @@
                 <action android:name="android.telecom.testapps.ACTION_NEW_UNKNOWN_CALL" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:scheme="tel" />
+                <data android:scheme="sip" />
             </intent-filter>
         </activity>
 
diff --git a/tests/src/com/android/server/telecom/testapps/CallServiceNotifier.java b/tests/src/com/android/server/telecom/testapps/CallServiceNotifier.java
index b82f4af..23e8222 100644
--- a/tests/src/com/android/server/telecom/testapps/CallServiceNotifier.java
+++ b/tests/src/com/android/server/telecom/testapps/CallServiceNotifier.java
@@ -24,6 +24,9 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
 import android.net.Uri;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
@@ -100,28 +103,30 @@
         telecomManager.clearAccounts();
 
         telecomManager.registerPhoneAccount(PhoneAccount.builder(
-                        new PhoneAccountHandle(
-                                new ComponentName(context, TestConnectionService.class),
-                                CALL_PROVIDER_ID),
-                        "TelecomTestApp Call Provider")
+                new PhoneAccountHandle(
+                        new ComponentName(context, TestConnectionService.class),
+                        CALL_PROVIDER_ID),
+                "TelecomTestApp Call Provider")
                 .setAddress(Uri.parse("tel:555-TEST"))
                 .setSubscriptionAddress(Uri.parse("tel:555-TEST"))
                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
-                .setIconResId(R.drawable.stat_sys_phone_call)
+                .setIcon(context, R.drawable.stat_sys_phone_call, Color.RED)
+                .setHighlightColor(Color.RED)
                 .setShortDescription("a short description for the call provider")
                 .setSupportedUriSchemes(Arrays.asList("tel"))
                 .build());
 
         telecomManager.registerPhoneAccount(PhoneAccount.builder(
-                        new PhoneAccountHandle(
-                                new ComponentName(context, TestConnectionService.class),
-                                SIM_SUBSCRIPTION_ID),
-                        "TelecomTestApp SIM Subscription")
+                new PhoneAccountHandle(
+                        new ComponentName(context, TestConnectionService.class),
+                        SIM_SUBSCRIPTION_ID),
+                "TelecomTestApp SIM Subscription")
                 .setAddress(Uri.parse("tel:555-TSIM"))
                 .setSubscriptionAddress(Uri.parse("tel:555-TSIM"))
                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
-                    PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
-                .setIconResId(R.drawable.stat_sys_phone_call)
+                        PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
+                .setIcon(context, R.drawable.stat_sys_phone_call, Color.GREEN)
+                .setHighlightColor(Color.GREEN)
                 .setShortDescription("a short description for the sim subscription")
                 .build());
 
@@ -133,7 +138,7 @@
                 .setAddress(Uri.parse("tel:555-CMGR"))
                 .setSubscriptionAddress(Uri.parse("tel:555-CMGR"))
                 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
-                .setIconResId(R.drawable.stat_sys_phone_call)
+                .setIcon(context, R.drawable.stat_sys_phone_call, Color.BLUE)
                 .setShortDescription("a short description for the connection manager")
                 .build());
     }
diff --git a/tests/src/com/android/server/telecom/testapps/TestCallActivity.java b/tests/src/com/android/server/telecom/testapps/TestCallActivity.java
index 9c9a40b..6f4ae20 100644
--- a/tests/src/com/android/server/telecom/testapps/TestCallActivity.java
+++ b/tests/src/com/android/server/telecom/testapps/TestCallActivity.java
@@ -50,7 +50,7 @@
         final Uri data = intent != null ? intent.getData() : null;
         if (ACTION_NEW_INCOMING_CALL.equals(action) && data != null) {
             CallNotificationReceiver.sendIncomingCallIntent(this, data, false);
-        } if (ACTION_NEW_UNKNOWN_CALL.equals(action) && data != null) {
+        } else if (ACTION_NEW_UNKNOWN_CALL.equals(action) && data != null) {
             CallNotificationReceiver.addNewUnknownCall(this, data, intent.getExtras());
         } else {
             CallServiceNotifier.getInstance().updateNotification(this);
diff --git a/tests/src/com/android/server/telecom/testapps/TestConnectionManager.java b/tests/src/com/android/server/telecom/testapps/TestConnectionManager.java
index 66b8749..a27be39 100644
--- a/tests/src/com/android/server/telecom/testapps/TestConnectionManager.java
+++ b/tests/src/com/android/server/telecom/testapps/TestConnectionManager.java
@@ -60,9 +60,9 @@
             }
 
             @Override
-            public void onCallCapabilitiesChanged(RemoteConnection connection,
-                    int callCapabilities) {
-                setCallCapabilities(callCapabilities);
+            public void onConnectionCapabilitiesChanged(RemoteConnection connection,
+                    int connectionCapabilities) {
+                setConnectionCapabilities(connectionCapabilities);
             }
 
             @Override
@@ -246,8 +246,9 @@
             }
 
             @Override
-            public void onCapabilitiesChanged(RemoteConference conference, int capabilities) {
-                setCapabilities(capabilities);
+            public void onConnectionCapabilitiesChanged(RemoteConference conference,
+                    int connectionCapabilities) {
+                setConnectionCapabilities(connectionCapabilities);
             }
 
             @Override
diff --git a/tests/src/com/android/server/telecom/testapps/TestConnectionService.java b/tests/src/com/android/server/telecom/testapps/TestConnectionService.java
index 389373f..2e01276 100644
--- a/tests/src/com/android/server/telecom/testapps/TestConnectionService.java
+++ b/tests/src/com/android/server/telecom/testapps/TestConnectionService.java
@@ -27,12 +27,9 @@
 import android.telecom.Connection;
 import android.telecom.DisconnectCause;
 import android.telecom.PhoneAccount;
-import android.telecom.PhoneCapabilities;
 import android.telecom.ConnectionRequest;
 import android.telecom.ConnectionService;
 import android.telecom.PhoneAccountHandle;
-import android.telecom.RemoteConnection;
-import android.telecom.StatusHints;
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
 import android.util.Log;
@@ -77,7 +74,11 @@
 
         public TestConference(Connection a, Connection b) {
             super(null);
-
+            setConnectionCapabilities(
+                    Connection.CAPABILITY_SUPPORT_HOLD |
+                    Connection.CAPABILITY_HOLD |
+                    Connection.CAPABILITY_MUTE |
+                    Connection.CAPABILITY_MANAGE_CONFERENCE);
             addConnection(a);
             addConnection(b);
 
@@ -133,13 +134,12 @@
         TestConnection(boolean isIncoming) {
             mIsIncoming = isIncoming;
             // Assume all calls are video capable.
-            int capabilities = getCallCapabilities();
-            capabilities |= PhoneCapabilities.SUPPORTS_VT_LOCAL;
-            capabilities |= PhoneCapabilities.ADD_CALL;
-            capabilities |= PhoneCapabilities.MUTE;
-            capabilities |= PhoneCapabilities.SUPPORT_HOLD;
-            capabilities |= PhoneCapabilities.HOLD;
-            setCallCapabilities(capabilities);
+            int capabilities = getConnectionCapabilities();
+            capabilities |= CAPABILITY_SUPPORTS_VT_LOCAL;
+            capabilities |= CAPABILITY_MUTE;
+            capabilities |= CAPABILITY_SUPPORT_HOLD;
+            capabilities |= CAPABILITY_HOLD;
+            setConnectionCapabilities(capabilities);
         }
 
         void startOutgoing() {
diff --git a/tests/src/com/android/server/telecom/testapps/TestManagedVideoProvider.java b/tests/src/com/android/server/telecom/testapps/TestManagedVideoProvider.java
index 50b77ed..649d0c0 100644
--- a/tests/src/com/android/server/telecom/testapps/TestManagedVideoProvider.java
+++ b/tests/src/com/android/server/telecom/testapps/TestManagedVideoProvider.java
@@ -111,7 +111,7 @@
     }
 
     @Override
-    public void onRequestCallDataUsage() {
+    public void onRequestConnectionDataUsage() {
         mRemoteVideoProvider.requestCallDataUsage();
     }
 
diff --git a/tests/src/com/android/server/telecom/testapps/TestVideoProvider.java b/tests/src/com/android/server/telecom/testapps/TestVideoProvider.java
index 58f093a..494eacc 100644
--- a/tests/src/com/android/server/telecom/testapps/TestVideoProvider.java
+++ b/tests/src/com/android/server/telecom/testapps/TestVideoProvider.java
@@ -169,8 +169,8 @@
      * Randomly reports data usage of value ranging from 10MB to 60MB.
      */
     @Override
-    public void onRequestCallDataUsage() {
-        log("Requested call data usage");
+    public void onRequestConnectionDataUsage() {
+        log("Requested connection data usage");
         int dataUsageKb = (10 *1024) + random.nextInt(50 * 1024);
         changeCallDataUsage(dataUsageKb);
     }
diff --git a/tests/src/com/android/server/telecom/tests/unit/InCallWakeLockControllerTest.java b/tests/src/com/android/server/telecom/tests/unit/InCallWakeLockControllerTest.java
new file mode 100644
index 0000000..5af9440
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/unit/InCallWakeLockControllerTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2014 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 static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.never;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.telecom.CallState;
+import android.test.AndroidTestCase;
+
+import com.android.server.telecom.Call;
+import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.InCallWakeLockController;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class InCallWakeLockControllerTest extends AndroidTestCase {
+
+    @Mock Context mContext;
+    @Mock PowerManager mPowerManager;
+    @Mock PowerManager.WakeLock mWakeLock;
+    @Mock CallsManager mCallsManager;
+    @Mock Call mCall;
+
+    private InCallWakeLockController mInCallWakeLockController;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+
+        when(mContext.getSystemService(Context.POWER_SERVICE)).thenReturn(mPowerManager);
+        when(mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "InCallWakeLockController"))
+                .thenReturn(mWakeLock);
+        mInCallWakeLockController = new InCallWakeLockController(mContext, mCallsManager);
+    }
+
+    @Override
+    public void tearDown() {
+    }
+
+    public void test_RingingCallAdded() throws Exception {
+        when(mCallsManager.getRingingCall()).thenReturn(mCall);
+        mInCallWakeLockController.onCallAdded(mCall);
+        verify(mWakeLock).acquire();
+    }
+
+    public void test_NonRingingCallAdded() throws Exception {
+        when(mCallsManager.getRingingCall()).thenReturn(null);
+        when(mWakeLock.isHeld()).thenReturn(false);
+
+        mInCallWakeLockController.onCallAdded(mCall);
+        verify(mWakeLock, never()).acquire();
+    }
+
+    public void test_RingingCallTransition() throws Exception {
+        when(mCallsManager.getRingingCall()).thenReturn(mCall);
+        mInCallWakeLockController.onCallStateChanged(mCall, CallState.NEW, CallState.RINGING);
+        verify(mWakeLock).acquire();
+    }
+
+    public void test_RingingCallRemoved() throws Exception {
+        when(mCallsManager.getRingingCall()).thenReturn(null);
+        when(mWakeLock.isHeld()).thenReturn(false);
+
+        mInCallWakeLockController.onCallRemoved(mCall);
+        verify(mWakeLock, never()).acquire();
+    }
+
+    public void test_WakeLockReleased() throws Exception {
+        when(mCallsManager.getRingingCall()).thenReturn(null);
+        when(mWakeLock.isHeld()).thenReturn(true);
+
+        mInCallWakeLockController.onCallRemoved(mCall);
+        verify(mWakeLock).release();
+    }
+}
diff --git a/tests/src/com/android/server/telecom/tests/unit/PhoneAccountRegistrarTest.java b/tests/src/com/android/server/telecom/tests/unit/PhoneAccountRegistrarTest.java
index cd1bbd1..e63e79f 100644
--- a/tests/src/com/android/server/telecom/tests/unit/PhoneAccountRegistrarTest.java
+++ b/tests/src/com/android/server/telecom/tests/unit/PhoneAccountRegistrarTest.java
@@ -16,16 +16,21 @@
 
 package com.android.server.telecom.tests.unit;
 
+import android.os.UserHandle;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.server.telecom.Log;
 import com.android.server.telecom.PhoneAccountRegistrar;
+import com.android.server.telecom.tests.R;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlSerializer;
 
 import android.content.ComponentName;
 import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.net.Uri;
+import android.os.Parcel;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.test.AndroidTestCase;
@@ -36,9 +41,11 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.util.Arrays;
 
 public class PhoneAccountRegistrarTest extends AndroidTestCase {
 
+    private static final int MAX_VERSION = Integer.MAX_VALUE;
     private static final String FILE_NAME = "phone-account-registrar-test.xml";
     private PhoneAccountRegistrar mRegistrar;
 
@@ -55,12 +62,12 @@
 
     public void testPhoneAccountHandle() throws Exception {
         PhoneAccountHandle input = new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), "id0");
-        PhoneAccountHandle result = roundTrip(this, input,
+        PhoneAccountHandle result = roundTripXml(this, input,
                 PhoneAccountRegistrar.sPhoneAccountHandleXml, mContext);
         assertPhoneAccountHandleEquals(input, result);
 
         PhoneAccountHandle inputN = new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), null);
-        PhoneAccountHandle resultN = roundTrip(this, inputN,
+        PhoneAccountHandle resultN = roundTripXml(this, inputN,
                 PhoneAccountRegistrar.sPhoneAccountHandleXml, mContext);
         Log.i(this, "inputN = %s, resultN = %s", inputN, resultN);
         assertPhoneAccountHandleEquals(inputN, resultN);
@@ -71,14 +78,15 @@
                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
                 .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
                 .build();
-        PhoneAccount result = roundTrip(this, input, PhoneAccountRegistrar.sPhoneAccountXml,
+        PhoneAccount result = roundTripXml(this, input, PhoneAccountRegistrar.sPhoneAccountXml,
                 mContext);
         assertPhoneAccountEquals(input, result);
     }
 
     public void testState() throws Exception {
         PhoneAccountRegistrar.State input = makeQuickState();
-        PhoneAccountRegistrar.State result = roundTrip(this, input, PhoneAccountRegistrar.sStateXml,
+        PhoneAccountRegistrar.State result = roundTripXml(this, input,
+                PhoneAccountRegistrar.sStateXml,
                 mContext);
         assertStateEquals(input, result);
     }
@@ -181,21 +189,52 @@
         assertNull(mRegistrar.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL));
     }
 
+    public void testPhoneAccountParceling() throws Exception {
+        PhoneAccountHandle handle = makeQuickAccountHandle("foo");
+        roundTripPhoneAccount(new PhoneAccount.Builder(handle, null).build());
+        roundTripPhoneAccount(new PhoneAccount.Builder(handle, "foo").build());
+        roundTripPhoneAccount(
+                new PhoneAccount.Builder(handle, "foo")
+                        .setAddress(Uri.parse("tel:123456"))
+                        .setCapabilities(23)
+                        .setHighlightColor(0xf0f0f0)
+                        .setIcon(
+                                "com.android.server.telecom.tests",
+                                R.drawable.stat_sys_phone_call,
+                                0xfefefe)
+                        .setShortDescription("short description")
+                        .setSubscriptionAddress(Uri.parse("tel:2345678"))
+                        .setSupportedUriSchemes(Arrays.asList("tel", "sip"))
+                        .build());
+        roundTripPhoneAccount(
+                new PhoneAccount.Builder(handle, "foo")
+                        .setAddress(Uri.parse("tel:123456"))
+                        .setCapabilities(23)
+                        .setHighlightColor(0xf0f0f0)
+                        .setIcon(
+                                BitmapFactory.decodeResource(
+                                        getContext().getResources(),
+                                        R.drawable.stat_sys_phone_call))
+                        .setShortDescription("short description")
+                        .setSubscriptionAddress(Uri.parse("tel:2345678"))
+                        .setSupportedUriSchemes(Arrays.asList("tel", "sip"))
+                        .build());
+    }
+
     private static PhoneAccountHandle makeQuickAccountHandle(String id) {
         return new PhoneAccountHandle(
                 new ComponentName(
                         "com.android.server.telecom.tests",
                         "com.android.server.telecom.tests.MockConnectionService"
                 ),
-                id
-        );
+                id,
+                new UserHandle(5));
     }
 
     private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) {
         return new PhoneAccount.Builder(
                 makeQuickAccountHandle(id),
-                "label" + idx
-        );
+                "label" + idx);
     }
 
     private PhoneAccount makeQuickAccount(String id, int idx) {
@@ -203,12 +242,26 @@
                 .setAddress(Uri.parse("http://foo.com/" + idx))
                 .setSubscriptionAddress(Uri.parse("tel:555-000" + idx))
                 .setCapabilities(idx)
-                .setIconResId(idx)
+                .setIcon("com.android.server.telecom.tests", R.drawable.stat_sys_phone_call)
                 .setShortDescription("desc" + idx)
                 .build();
     }
 
-    private static <T> T roundTrip(
+    private static void roundTripPhoneAccount(PhoneAccount original) throws Exception {
+        PhoneAccount copy = null;
+
+        {
+            Parcel parcel = Parcel.obtain();
+            parcel.writeParcelable(original, 0);
+            parcel.setDataPosition(0);
+            copy = parcel.readParcelable(PhoneAccountRegistrarTest.class.getClassLoader());
+            parcel.recycle();
+        }
+
+        assertPhoneAccountEquals(original, copy);
+    }
+
+    private static <T> T roundTripXml(
             Object self,
             T input,
             PhoneAccountRegistrar.XmlSerialization<T> xml,
@@ -221,7 +274,7 @@
             XmlSerializer serializer = new FastXmlSerializer();
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
             serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
-            xml.writeToXml(input, serializer);
+            xml.writeToXml(input, serializer, context);
             serializer.flush();
             data = baos.toByteArray();
         }
@@ -233,7 +286,7 @@
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(new BufferedInputStream(new ByteArrayInputStream(data)), null);
             parser.nextTag();
-            result = xml.readFromXml(parser, 0, context);
+            result = xml.readFromXml(parser, MAX_VERSION, context);
         }
 
         Log.d(self, "result = " + result);
@@ -260,13 +313,31 @@
             assertEquals(a.getSubscriptionAddress(), b.getSubscriptionAddress());
             assertEquals(a.getCapabilities(), b.getCapabilities());
             assertEquals(a.getIconResId(), b.getIconResId());
-            assertEquals(a.getColor(), b.getColor());
+            assertEquals(a.getIconPackageName(), b.getIconPackageName());
+            assertBitmapEquals(a.getIconBitmap(), b.getIconBitmap());
+            assertEquals(a.getIconTint(), b.getIconTint());
+            assertEquals(a.getHighlightColor(), b.getHighlightColor());
             assertEquals(a.getLabel(), b.getLabel());
             assertEquals(a.getShortDescription(), b.getShortDescription());
             assertEquals(a.getSupportedUriSchemes(), b.getSupportedUriSchemes());
         }
     }
 
+    private static void assertBitmapEquals(Bitmap a, Bitmap b) {
+        if (a == null || b == null) {
+            assertEquals(null, a);
+            assertEquals(null, b);
+        } else {
+            assertEquals(a.getWidth(), b.getWidth());
+            assertEquals(a.getHeight(), b.getHeight());
+            for (int x = 0; x < a.getWidth(); x++) {
+                for (int y = 0; y < a.getHeight(); y++) {
+                    assertEquals(a.getPixel(x, y), b.getPixel(x, y));
+                }
+            }
+        }
+    }
+
     private static void assertStateEquals(
             PhoneAccountRegistrar.State a, PhoneAccountRegistrar.State b) {
         assertPhoneAccountHandleEquals(a.defaultOutgoing, b.defaultOutgoing);