Merge "Add tests for ContactsHelperAsync"
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 0e0b5b0..c7eaf22 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Vinnige antwoord"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Boodskap gestuur na <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Oproeprekeninge"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Net noodoproepe word toegelaat."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Hierdie program kan nie uitgaande oproepe maak sonder die foon se toestemming nie."</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>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 853729d..d15621d 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"ፈጣን ምላሽ"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"ለ <xliff:g id="PHONE_NUMBER">%s</xliff:g> የተላከ መልዕክት"</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"የመደወያ መለያዎች"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"የድንገተኛ አደጋ ጥሪዎች ብቻ ናቸው የሚፈቀዱት።"</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"ይህ መተግበሪያ ያለስልኩ ፈቃድ ወጪ ጥሪዎችን ማድረግ አይችልም።"</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"አንድ ጥሪ ለማድረግ የሚሰራ ቁጥር ያስገቡ።"</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"ጥሪ በዚህ ጊዜ ላይ ሊታከል አይችልም።"</string>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..1c4ce56
--- /dev/null
+++ b/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="telecommAppLabel" product="default" msgid="9166784827254469057">"Upravljanje telefonskim pozivima"</string>
+    <string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"Telefon"</string>
+    <string name="unknown" msgid="6878797917991465859">"Nepoznato"</string>
+    <string name="notification_missedCallTitle" msgid="7554385905572364535">"Propušten poziv"</string>
+    <string name="notification_missedCallsTitle" msgid="1361677948941502522">"Propušteni pozivi"</string>
+    <string name="notification_missedCallsMsg" msgid="4575787816055205600">"Broj propuštenih poziva: <xliff:g id="NUM_MISSED_CALLS">%s</xliff:g>"</string>
+    <string name="notification_missedCallTicker" msgid="504686252427747209">"Propušten poziv od: <xliff:g id="MISSED_CALL_FROM">%s</xliff:g>"</string>
+    <string name="notification_missedCall_call_back" msgid="2684890353590890187">"Uzvrati poziv"</string>
+    <string name="notification_missedCall_message" msgid="3049928912736917988">"Poruka"</string>
+    <string name="accessibility_call_muted" msgid="2776111226185342220">"Zvuk poziva je isključen."</string>
+    <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"Spikerfon je omogućen."</string>
+    <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"U gužvi sam. O čemu se radi?"</string>
+    <string name="respond_via_sms_canned_response_2" msgid="4074450431532859214">"Pozvaću te uskoro."</string>
+    <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"Pozvaću te kasnije."</string>
+    <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"U gužvi sam. Da se čujemo kasnije?"</string>
+    <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"Brzi odgovori"</string>
+    <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"Izmena 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_confirmation_format" msgid="7229149977515784269">"Poruka je poslata na broj <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
+    <string name="enable_account_preference_title" msgid="2021848090086481720">"Nalozi za pozivanje"</string>
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Dozvoljeni su samo hitni pozivi."</string>
+    <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Ova aplikacija ne može da poziva bez dozvole za telefoniranje."</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Da biste uputili poziv, unesite važeći broj."</string>
+    <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Trenutno nije moguće dodati poziv."</string>
+    <string name="video_call_not_allowed_if_tty_enabled" msgid="7593649283571253283">"Onemogućite TTY režim da biste upućivali video pozive."</string>
+    <string name="no_vm_number" msgid="4164780423805688336">"Nedostaje broj za govornu poštu"</string>
+    <string name="no_vm_number_msg" msgid="1300729501030053828">"Nije uskladišten nijedan broj govorne pošte na SIM kartici."</string>
+    <string name="add_vm_number_str" msgid="4676479471644687453">"Dodaj broj"</string>
+    <string name="change_default_dialer_dialog_title" msgid="4430590714918044425">"Promeniti podrazumevanu aplikaciju Telefon?"</string>
+    <string name="change_default_dialer_with_previous_app_set_text" msgid="3213396537499337949">"Želite li da koristite aplikaciju <xliff:g id="NEW_APP">%1$s</xliff:g> umesto aplikacije <xliff:g id="CURRENT_APP">%2$s</xliff:g> kao podrazumevanu aplikaciju za pozivanje telefonskih brojeva?"</string>
+    <string name="change_default_dialer_no_previous_app_set_text" msgid="7608426684114545221">"Želite li da koristite aplikaciju <xliff:g id="NEW_APP">%s</xliff:g> kao podrazumevanu aplikaciju za pozivanje telefonskih brojeva?"</string>
+</resources>
diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml
index ff406db..384aa35 100644
--- a/res/values-bn-rBD/strings.xml
+++ b/res/values-bn-rBD/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"দ্রুত প্রতিক্রিয়া"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> এ বার্তা পাঠানো হয়েছে৷"</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"কলিং অ্যাকাউন্টগুলি"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"শুধুমাত্র জরুরি কলগুলিকে অনুমোদিত।"</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"এই অ্যাপ্লিকেশানটি ফোনের অনুমতি ছাড়া আউটগোয়িং কলগুলি করতে পারবে না।"</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"কোনো কল স্থাপন করতে, একটি বৈধ নম্বর লিখুন৷"</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"এই মুহূর্তে কল যোগ করা যাবে না৷"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index f297dab..f5a570f 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Resposta ràpida"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Missatge enviat a <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Comptes de trucades"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Només es permeten les trucades d\'emergència."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Aquesta aplicació no pot fer trucades sortints sense el permís del telèfon."</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>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 56c5c76..4a5c9e0 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Rychlá odpověď"</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="enable_account_preference_title" msgid="2021848090086481720">"Účty pro volání"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Jsou povolena pouze tísňová volání."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Tato aplikace nemůže provádět odchozí hovory bez oprávnění k použití telefonu."</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>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 5d8fa36..787cfe0 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Hurtigt svar"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Meddelelsen er sendt til <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Opkaldskonti"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Kun nødopkald er tilladt."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Denne app kan ikke foretage udgående opkald uden opkaldstilladelse."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"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>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index fc8e9ae..74c24fb 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Kurzantwort"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Nachricht an <xliff:g id="PHONE_NUMBER">%s</xliff:g> gesendet"</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Anrufkonten"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Es sind nur Notrufe erlaubt."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Diese App darf ohne die Berechtigung \"Standard-App für Telefonie\" keine ausgehenden Anrufe tätigen."</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>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 1d0d773..ec44361 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Γρήγορη απάντηση"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Το μήνυμα εστάλη στο <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Λογαριασμοί κλήσης"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Επιτρέπονται μόνο κλήσεις έκτακτης ανάγκης."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Αυτή η εφαρμογή δεν μπορεί να πραγματοποιήσει εξερχόμενες κλήσεις χωρίς την άδεια \"Τηλέφωνο\"."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Για να πραγματοποιήσετε μια κλήση, εισαγάγετε έναν έγκυρο αριθμό."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Δεν είναι δυνατή η προσθήκη κλήσης αυτήν τη στιγμή."</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 4285c28..0ad7c1b 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Respuesta rápida"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mensaje enviado a <xliff:g id="PHONE_NUMBER">%s</xliff:g>"</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Cuentas telefónicas"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Solo se permiten llamadas de emergencia."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Esta aplicación no puede realizar llamadas salientes sin permiso del teléfono."</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>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 071ddba..1fb18a6 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Respuestas rápidas"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mensaje enviado a <xliff:g id="PHONE_NUMBER">%s</xliff:g>"</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Cuentas de llamadas"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Solo se permiten llamadas de emergencia."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Esta aplicación no puede hacer llamadas sin permiso del teléfono."</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>
diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml
index b6090f3..04206c7 100644
--- a/res/values-et-rEE/strings.xml
+++ b/res/values-et-rEE/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Kiirvastus"</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="enable_account_preference_title" msgid="2021848090086481720">"Kõnekontod"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Lubatud on ainult hädaabikõned."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"See rakendus ei saa ilma telefoni kasutamise loata välja helistada."</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>
diff --git a/res/values-eu-rES/strings.xml b/res/values-eu-rES/strings.xml
index 654f115..88f8a8e 100644
--- a/res/values-eu-rES/strings.xml
+++ b/res/values-eu-rES/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Erantzun bizkorra"</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="enable_account_preference_title" msgid="2021848090086481720">"Deiak egiteko kontuak"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Larrialdi-deiak bakarrik egin daitezke."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Aplikazioak irteerako deiak egin ahal izan ditzan, telefonoaren eginbidea erabiltzeko baimena behar 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>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 25e380a..fa8028c 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"پاسخ سریع"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"پیام به <xliff:g id="PHONE_NUMBER">%s</xliff:g> ارسال شد."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"حساب‌های تماس"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"فقط تماس‌های اضطراری مجاز است."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"این برنامه نمی‌تواند بدون اجازه تلفن، تماس‌های خروجی برقرار کند."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"برای برقراری تماس، یک شماره معتبر وارد کنید."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"در این زمان نمی‌توان تماسی اضافه کرد."</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index f253000..2f73a26 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Pikavastaukset"</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="enable_account_preference_title" msgid="2021848090086481720">"Puhelutilit"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Vain hätäpuhelut sallittu"</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Tämä sovellus ei voi soittaa puheluita ilman Puhelin-lupaa."</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>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index bffa229..4bf6b52 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Réponse rapide"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Message envoyé à <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Comptes d\'appel"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Seuls les appels d\'urgence sont autorisés."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Cette application ne peut pas faire d\'appels sans l\'autorisation de l\'application Téléphone."</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>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index e8ee088..247b528 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Réponse rapide"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Message envoyé à <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Comptes téléphoniques"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Seuls les appels d\'urgence sont autorisés."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Cette application ne peut pas passer d\'appels sortants sans l\'autorisation de l\'application Téléphone."</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>
diff --git a/res/values-gl-rES/strings.xml b/res/values-gl-rES/strings.xml
index f64da11..fc726a6 100644
--- a/res/values-gl-rES/strings.xml
+++ b/res/values-gl-rES/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Resposta rápida"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mensaxe enviada ao <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Contas de chamadas"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Só se permiten chamadas de emerxencia."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Esta aplicación non pode facer chamadas saíntes sen permiso do teléfono."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Para realizar unha chamada, introduce un número válido."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Neste momento non se pode engadir a chamada."</string>
diff --git a/res/values-gu-rIN/strings.xml b/res/values-gu-rIN/strings.xml
index 12e163c..5c3078e 100644
--- a/res/values-gu-rIN/strings.xml
+++ b/res/values-gu-rIN/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"ઝડપી પ્રતિસાદ"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> પર સંદેશ મોકલ્યો."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"કૉલિંગ એકાઉન્ટ્સ"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"ફક્ત કટોકટીના કૉલ્સને મંજૂરી છે."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"ફોન પરવાનગી વિના આ એપ્લિકેશન આઉટગોઇંગ કૉલ્સ કરી શકતી નથી."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"કૉલ કરવા માટે, માન્ય નંબર દાખલ કરો."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"આ સમયે કૉલ ઉમેરી શકાતો નથી."</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index cf9a5e9..2a47df9 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Brzi odgovor"</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="enable_account_preference_title" msgid="2021848090086481720">"Računi za pozivanje"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Dopušteni su samo hitni pozivi."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Ova aplikacija ne može uspostavljati odlazne pozive bez dopuštenja za telefon."</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>
diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml
index 05a7746..6ff22a7 100644
--- a/res/values-hy-rAM/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Արագ պատասխան"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Հաղորդագրությունն ուղարկվել է <xliff:g id="PHONE_NUMBER">%s</xliff:g>-ին:"</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Հաշիվներ զանգերի համար"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Միայն արտակարգ իրավիճակների զանգերն են թույլատրվում:"</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Առանց Հեռախոսի թույլտվության այս ծրագիրը չի կարող ելքային զանգեր կատարել:"</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Զանգ կատարելու համար մուտքագրեք ճիշտ համար:"</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Հնարավոր չէ ևս մեկ զանգ ավելացնել այս պահին:"</string>
diff --git a/res/values-is-rIS/strings.xml b/res/values-is-rIS/strings.xml
index 59e37ac..f9516dc 100644
--- a/res/values-is-rIS/strings.xml
+++ b/res/values-is-rIS/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Snarsvar"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Skilaboð send til <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Símtalareikningar"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Aðeins neyðarsímöl eru leyfð."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Þetta forrit getur ekki hringt án heimildar í símanum."</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>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index aa42c41..3df48c1 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Risposta rapida"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Messaggio inviato a <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Account di chiamata"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Sono consentite soltanto le chiamate di emergenza."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Non è possibile effettuare chiamate tramite questa applicazione senza l\'autorizzazione sul telefono."</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>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 0a9506f..ae002ff 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"クイック返信"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g>にメッセージを送信しました。"</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"通話アカウント"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"許可されているのは緊急通報のみです。"</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"このアプリは、電話権限がないため発信できません。"</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"発信するには、有効な番号を入力してください。"</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"通話は現在追加できません。"</string>
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml
index 50d9375..66c7eb0 100644
--- a/res/values-ka-rGE/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"სწრაფი პასუხი"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"შეტყობინება გაიგზავნა <xliff:g id="PHONE_NUMBER">%s</xliff:g>-თან."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"დარეკვის ანგარიშები"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"შესაძლებელია მხოლოდ გადაუდებელი ზარების განხორციელება."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"ეს აპლიკაცია ტელეფონის ნებართვის გარეშე გამავალ ზარებს ვერ განახორციელებს."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"ზარის განხორციელებისათვის, შეიყვანეთ მოქმედი ნომერი."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"ამ ეტაპზე ზარის დამატება ვერ ხერხდება."</string>
diff --git a/res/values-kn-rIN/strings.xml b/res/values-kn-rIN/strings.xml
index 37da2d4..165dcf7 100644
--- a/res/values-kn-rIN/strings.xml
+++ b/res/values-kn-rIN/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"ತ್ವರಿತ ಪ್ರತಿಕ್ರಿಯೆ"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> ಗೆ ಸಂದೇಶ ಕಳುಹಿಸಲಾಗಿದೆ."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"ಕರೆ ಮಾಡುವ ಖಾತೆಗಳು"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"ತುರ್ತು ಕರೆಗಳನ್ನು ಮಾಡಲು ಮಾತ್ರ ಅವಕಾಶವಿದೆ."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಫೋನ್ ಅನುಮತಿಯಿಲ್ಲದೆ ಹೊರಹೋಗುವ ಕರೆಗಳನ್ನು ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"ಕರೆಯನ್ನು ಮಾಡಲು, ಮಾನ್ಯವಾದ ಸಂಖ್ಯೆಯನ್ನು ನಮೂದಿಸಿ."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"ಕರೆಯನ್ನು ಈ ಸಮಯದಲ್ಲಿ ಸೇರಿಸಲಾಗುವುದಿಲ್ಲ."</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 5080f15..ff26e46 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"빠른 응답"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g>(으)로 메시지를 보냈습니다."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"통화 계정"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"긴급 전화만 허용됩니다."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"전화 권한이 없으므로 애플리케이션에서 발신 전화를 걸 수 없습니다."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"전화를 걸려면 올바른 번호를 입력하세요."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"현재 통화를 추가할 수 없습니다."</string>
diff --git a/res/values-ky-rKG/strings.xml b/res/values-ky-rKG/strings.xml
index a65db25..c2d8260 100644
--- a/res/values-ky-rKG/strings.xml
+++ b/res/values-ky-rKG/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Тез жооп"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> номуруна билдирүү жөнөтүлдү."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Чалуу каттоо эсептери"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Шашылыш чалууларга гана уруксат берилген."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Бул колдонмо тийиштүү уруксатсыз чалууларды жасай албайт."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Чалуу үчүн, жарактуу номер киргизиңиз."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Бул жолу чалууну кошуу мүмкүн эмес."</string>
diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml
index 6c41d65..effc21f 100644
--- a/res/values-lo-rLA/strings.xml
+++ b/res/values-lo-rLA/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"ຕອບກັບດ່ວນ"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"ສົ່ງຂໍ້ຄວາມຫາ <xliff:g id="PHONE_NUMBER">%s</xliff:g> ແລ້ວ."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"ບັນ​ຊີ​ໂທ"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"ອະນຸຍາດໃຫ້ໂທສຸກເສີນເທົ່ານັ້ນ."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"ແອັບ​ພ​ລິ​ເຄ​ຊັນ​ນີ້​ບໍ່​ສາ​ມາດ​ໂທ​ອອກ​ໄດ້ ໂດຍ​ບໍ່​ມີ​ການ​ອະ​ນຸ​ຍາດ​ຂອງ​ໂທ​ລະ​ສັບ."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"ເພື່ອ​ທີ່​ຈະ​ໂທ, ປ້ອນ​ເບີ​ໂທ​ທີ່​ໃຊ້​ໄດ້​ເຂົ້າ​ໄປ."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"​ບໍ່​ສາ​ມາດ​ເພີ່ມ​ການ​ໂທ​ໄດ້​ໃນ​ເວ​ລາ​ນີ້."</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index bac3368..ccc7270 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Ātrā atbilde"</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="enable_account_preference_title" msgid="2021848090086481720">"Zvanu konti"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Ir atļauti tikai ārkārtas zvani."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Šajā lietojumprogrammā nevar veikt izejošos zvanus bez tālruņa atļaujas."</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>
diff --git a/res/values-mk-rMK/strings.xml b/res/values-mk-rMK/strings.xml
index 3c87169..8d7ebce 100644
--- a/res/values-mk-rMK/strings.xml
+++ b/res/values-mk-rMK/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Брз одговор"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Порака е испратена на <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Сметки за повици"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Дозволени се само итни повици."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Оваа апликација не може да прави појдовни повици без дозволата Телефон."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"За да повикате, внесете важечки број."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Повикот не може да се додаде во моментов."</string>
diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn-rMN/strings.xml
index 1ecabc4..f722b92 100644
--- a/res/values-mn-rMN/strings.xml
+++ b/res/values-mn-rMN/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Шуурхай хариу"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Зурвасыг <xliff:g id="PHONE_NUMBER">%s</xliff:g> руу илгээв."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Дуудлагын эрхтэй бүртгэлүүд"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Зөвхөн яаралтай тусламжийн дуудлага хийх боломжтой."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Энэ апп нь утасны зөвшөөрөлгүйгээр дуудлага хийх боломжгүй."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Дуудлага хийхийн тулд хүчин төгөлдөр дугаар оруулна уу."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Одоо дуудлага нэмэх боломжгүй."</string>
diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml
index d75cf36..2d31e88 100644
--- a/res/values-ms-rMY/strings.xml
+++ b/res/values-ms-rMY/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Respons pantas"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mesej dihantar ke <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Akaun panggilan"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Panggilan kecemasan sahaja dibenarkan."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Aplikasi ini tidak boleh membuat panggilan keluar tanpa kebenaran Telefon."</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>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 7f37bf0..e37f856 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Hurtigsvar"</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="enable_account_preference_title" msgid="2021848090086481720">"Ringekontoer"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Kun nødanrop er mulig."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Denne appen kan ikke ringe uten tillatelse fra telefonen."</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>
diff --git a/res/values-pa-rIN/strings.xml b/res/values-pa-rIN/strings.xml
index 6e49d64..ce7c88c 100644
--- a/res/values-pa-rIN/strings.xml
+++ b/res/values-pa-rIN/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"ਤਤਕਾਲ ਜਵਾਬ"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"ਸੁਨੇਹਾ <xliff:g id="PHONE_NUMBER">%s</xliff:g> ਨੂੰ ਭੇਜਿਆ ਗਿਆ।"</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"ਕਾਲਿੰਗ ਖਾਤੇ"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"ਸਿਰਫ਼ ਸੰਕਟ ਕਾਲਾਂ ਨੂੰ ਮਨਜ਼ੂਰੀ ਹੈ।"</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"ਇਹ ਐਪਲੀਕੇਸ਼ਨ ਫੋਨ ਅਨੁਮਤੀ ਦੇ ਬਿਨਾਂ ਆਉਟਗੋਇੰਗ ਕਾਲਾਂ ਨਹੀਂ ਕਰ ਸਕਦੀ।"</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"ਇੱਕ ਕਾਲ ਕਰਨ ਲਈ, ਇੱਕ ਪ੍ਰਮਾਣਿਕ ਨੰਬਰ ਦਰਜ ਕਰੋ।"</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"ਇਸ ਵੇਲੇ ਕਾਲ ਨਹੀਂ ਜੋੜੀ ਸਕਦੀ।"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 4d44cb1..a2243bc 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Szybka odpowiedź"</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="enable_account_preference_title" msgid="2021848090086481720">"Konta telefoniczne"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Dozwolone są tylko połączenia alarmowe."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Ta aplikacja nie może wykonywać połączeń bez uprawnienia Telefon."</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>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index d167aff..1727b2a 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Resposta rápida"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mensagem enviada para <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Contas de chamadas"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Somente chamadas de emergência são permitidas."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Este aplicativo não pode fazer chamadas sem a permissão do smartphone."</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>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index c4464b8..79cc111 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Răspuns rapid"</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="enable_account_preference_title" msgid="2021848090086481720">"Conturi pentru apelare"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Sunt permise doar apelurile de urgență."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Această aplicație nu poate efectua apeluri fără permisiunea Telefon."</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>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 8d43a8c..4d53bc0 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Быстрый ответ"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Сообщение отправлено на номер <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Аккаунты для звонков"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Только экстренные вызовы"</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Приложение не может совершать звонки без соответствующего разрешения."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Недействительный номер."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Невозможно позвонить в данный момент"</string>
diff --git a/res/values-si-rLK/strings.xml b/res/values-si-rLK/strings.xml
index 9c21e26..39d2298 100644
--- a/res/values-si-rLK/strings.xml
+++ b/res/values-si-rLK/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"ක්ෂණික ප්‍රතිචාරය"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> හට පණිවිඩය යවන්න."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"ඇමතීමේ ගිණුම්"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"හදිසි ඇමතුම්වලට පමණක් ඉඩ දේ."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"දුරකථන අවසරයෙන් තොරව මෙම යෙදුමට පිටතට යන ඇමතුම් සිදු කළ නොහැකිය."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"ඇමතුමක් ලබාගැනීමට, වලංගු අංකයක් ලබාගන්න."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"මේ වේලාවේ ඇමතුම එකතු කළ නොහැක."</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index c8036ee..fcaaea1 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Hiter odgovor"</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="enable_account_preference_title" msgid="2021848090086481720">"Računi za klicanje"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Dovoljeno je samo opravljanje klicev v sili."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Ta aplikacija lahko opravlja odhodne klice brez dovoljenja za telefon."</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>
diff --git a/res/values-sq-rAL/strings.xml b/res/values-sq-rAL/strings.xml
index aa6b3c4..e684eff 100644
--- a/res/values-sq-rAL/strings.xml
+++ b/res/values-sq-rAL/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Përgjigje e shpejtë"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Mesazhi u dërgua te <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Llogaritë e telefonatave"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Lejohen vetëm telefonatat e urgjencës."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Ky aplikacion nuk mund të kryejë telefonata dalëse pa lejen e Telefonit."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Për të kryer një telefonatë, fut një numër të vlefshëm."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Telefonata nuk mund të shtohet këtë herë."</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index ad9e9e3..07b1327 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Брзи одговор"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Порука је послата на број <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Налози за позивање"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Дозвољени су само хитни позиви."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Ова апликација не може да позива без дозволе за телефонирање."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Да бисте упутили позив, унесите важећи број."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Тренутно није могуће додати позив."</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 6298b4f..4d5cff7 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Majibu ya haraka"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Ujumbe uliotumwa kwa <xliff:g id="PHONE_NUMBER">%s</xliff:g> ."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Akaunti za simu"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Piga simu za dharura pekee."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Programu hii haiwezi kupiga simu bila ruhusa ya Simu."</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>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 106a1b5..117d656 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"คำตอบด่วน"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"ส่งข้อความไปยัง <xliff:g id="PHONE_NUMBER">%s</xliff:g> แล้ว"</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"บัญชีการโทร"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"อนุญาตเฉพาะหมายเลขฉุกเฉิน"</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"แอปพลิเคชันนี้ไม่สามารถโทรออกโดยไม่มีสิทธิ์ใช้โทรศัพท์"</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"หากต้องการโทรออก โปรดป้อนหมายเลขที่ถูกต้อง"</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"ไม่สามารถเพิ่มสายได้ในขณะนี้"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index ea350ab..728ad6b 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Mabilisang tugon"</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="enable_account_preference_title" msgid="2021848090086481720">"Account sa pagtawag"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Ang mga pang-emergency na tawag lang ang pinapayagan."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Hindi makakapagsagawa ng mga papalabas na tawag ang application na ito nang wala ang pahintulot ng Telepono."</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>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 0ef8a03..dd5c6bd 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Hızlı yanıt"</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="enable_account_preference_title" msgid="2021848090086481720">"Çağrı hesapları"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Yalnızca acil durum çağrılarına izin veriliyor."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Bu uygulama, Telefonun izni olmadan giden çağrılar yapamaz."</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>
diff --git a/res/values-ur-rPK/strings.xml b/res/values-ur-rPK/strings.xml
index 6144a70..9774c7e 100644
--- a/res/values-ur-rPK/strings.xml
+++ b/res/values-ur-rPK/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"فوری جواب"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"پیغام <xliff:g id="PHONE_NUMBER">%s</xliff:g> کو بھیج دیا گیا۔"</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"کالنگ اکاؤنٹس"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"صرف ہنگامی کالز کی اجازت ہے۔"</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"یہ ایپلی کیشن فون کی اجازت کے بغیر باہر جانے والی کالیں نہیں کر سکتی۔"</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"کال کرنے کیلئے، ایک درست نمبر درج کریں۔"</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"اس وقت کال شامل نہیں کی جا سکتی ہے۔"</string>
diff --git a/res/values-uz-rUZ/strings.xml b/res/values-uz-rUZ/strings.xml
index 3ad9cf5..1a84603 100644
--- a/res/values-uz-rUZ/strings.xml
+++ b/res/values-uz-rUZ/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Tezkor javob"</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="enable_account_preference_title" msgid="2021848090086481720">"Qo‘ng‘iroq hisoblari"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Faqat favqulodda qo‘ng‘iroqlarga ruxsat berilgan."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Bu ilova Telefon ruxsatnomasisiz chiquvchi qo‘ng‘iroqlarni amalga oshira olmaydi."</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>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index c6752ad..4c30166 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"快速回复"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"讯息已发送至 <xliff:g id="PHONE_NUMBER">%s</xliff:g>。"</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"通话帐号"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"只能拨打紧急呼救电话。"</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"此应用没有电话权限,无法拨出电话。"</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"要拨打电话,请输入有效的电话号码。"</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"目前无法添加通话。"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index a06b76f..6468859 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"快速回應"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"訊息已傳送至 <xliff:g id="PHONE_NUMBER">%s</xliff:g>。"</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"通話帳戶"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"只能撥打緊急電話。"</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"這個應用程式不具備電話應用程式存取權限,無法撥出電話。"</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"如要撥打電話,請輸入有效的號碼。"</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"目前無法新增通話。"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 70188be..d8e5757 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -37,8 +37,7 @@
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"Izimpendulo ezisheshayo"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"Umlayezo othunyelwe ku <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Ama-akhawunti wokushaya"</string>
-    <!-- no translation found for outgoing_call_not_allowed_user_restriction (6872406278300131364) -->
-    <skip />
+    <string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"Amakholi aphuthumayo kuphela avunyelwe."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Lolu hlelo lokusebenza alikwazi ukwenza amakhli aphumayo ngaphandle kwemvume yefoni."</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>
diff --git a/scripts/telecom_testing.sh b/scripts/telecom_testing.sh
index d7e21d6..efae9fc 100644
--- a/scripts/telecom_testing.sh
+++ b/scripts/telecom_testing.sh
@@ -1,23 +1,30 @@
 lite_test_telecom() {
   usage="
-  Usage: lite_test_telecom [-c CLASSNAME] [-d] [-i] [-e], where
+  Usage: lite_test_telecom [-c CLASSNAME] [-d] [-a | -i] [-e], where
 
   -c CLASSNAME          Run tests only for the specified class/method. CLASSNAME
                           should be of the form SomeClassTest or SomeClassTest#testMethod.
   -d                    Waits for a debugger to attach before starting to run tests.
-  -i                    Rebuild and reinstall the test apk before running tests
+  -i                    Rebuild and reinstall the test apk before running tests (mmm).
+  -a                    Rebuild all dependencies and reinstall the test apk before/
+                          running tests (mmma).
   -e                    Run code coverage. Coverage will be output into the coverage/
                           directory in the repo root.
+  -h                    This help message.
   "
 
   OPTIND=1
   class=
   install=false
+  installwdep=false
   debug=false
   coverage=false
 
-  while getopts "c:die" opt; do
+  while getopts "c:hadie" opt; do
     case "$opt" in
+      h)
+        echo "$usage"
+        return 0;;
       \?)
         echo "$usage"
         return 0;;
@@ -27,6 +34,9 @@
         debug=true;;
       i)
         install=true;;
+      a)
+        install=true
+        installwdep=true;;
       e)
         coverage=true;;
     esac
@@ -42,7 +52,17 @@
     else
       emma_opt="EMMA_INSTRUMENT_STATIC=false"
     fi
-    ANDROID_COMPILE_WITH_JACK=false mmm "packages/services/Telecomm/tests" ${emma_opt}
+    # Build and exit script early if build fails
+    if [ $installwdep = true ] ; then
+      ANDROID_COMPILE_WITH_JACK=false mmma "packages/services/Telecomm/tests" ${emma_opt}
+    else
+      ANDROID_COMPILE_WITH_JACK=false mmm "packages/services/Telecomm/tests" ${emma_opt}
+    fi
+    if [ $? -ne 0 ] ; then
+      echo "Make failed! try using -a instead of -i if building with coverage"
+      return
+    fi
+
     adb install -r -t "out/target/product/$TARGET_PRODUCT/data/app/TelecomUnitTests/TelecomUnitTests.apk"
     if [ $? -ne 0 ] ; then
       cd "$olddir"
@@ -64,6 +84,8 @@
   adb shell am instrument ${e_options} -w com.android.server.telecom.tests/android.test.InstrumentationTestRunner
 
   if [ $coverage = true ] ; then
+    adb root
+    adb wait-for-device
     adb pull /data/user/0/com.android.server.telecom.tests/files/coverage.ec /tmp/
     java -cp external/emma/lib/emma.jar emma report -r html -sp packages/services/Telecomm/src -in out/target/common/obj/APPS/TelecomUnitTests_intermediates/coverage.em -in /tmp/coverage.ec
   fi
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index c2d4aa5..5971f7b 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -1141,7 +1141,8 @@
         }
     }
 
-    void disconnect() {
+    @VisibleForTesting
+    public void disconnect() {
         disconnect(false);
     }
 
@@ -1210,7 +1211,8 @@
      *
      * @param videoState The video state in which to answer the call.
      */
-    void answer(int videoState) {
+    @VisibleForTesting
+    public void answer(int videoState) {
         Preconditions.checkNotNull(mConnectionService);
 
         // Check to verify that the call is still in the ringing state. A call can change states
@@ -1231,7 +1233,8 @@
      * @param rejectWithMessage Whether to send a text message as part of the call rejection.
      * @param textMessage An optional text message to send as part of the rejection.
      */
-    void reject(boolean rejectWithMessage, String textMessage) {
+    @VisibleForTesting
+    public void reject(boolean rejectWithMessage, String textMessage) {
         Preconditions.checkNotNull(mConnectionService);
 
         // Check to verify that the call is still in the ringing state. A call can change states
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index a774130..05586ee 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -90,6 +90,9 @@
 
     public static final int SWITCH_FOCUS = 4001;
 
+    // Used in testing to execute verifications. Not compatible with subsessions.
+    public static final int RUN_RUNNABLE = 9001;
+
     /** Valid values for mAudioFocusType */
     public static final int NO_FOCUS = 1;
     public static final int HAS_FOCUS = 2;
@@ -923,7 +926,6 @@
         mRouteCodeToQuiescentState.put(ROUTE_BLUETOOTH, mQuiescentBluetoothRoute);
         mRouteCodeToQuiescentState.put(ROUTE_SPEAKER, mQuiescentSpeakerRoute);
         mRouteCodeToQuiescentState.put(ROUTE_WIRED_HEADSET, mQuiescentHeadsetRoute);
-        initialize();
     }
 
     /**
@@ -964,7 +966,7 @@
     }
 
     /**
-     * This is for state-independent changes in audio route (i.e. muting)
+     * This is for state-independent changes in audio route (i.e. muting or runnables)
      * @param msg that couldn't be handled.
      */
     @Override
@@ -994,12 +996,20 @@
                     sendInternalMessage(MUTE_ON);
                 }
                 return;
+            case RUN_RUNNABLE:
+                Runnable r = (Runnable) msg.obj;
+                r.run();
+                return;
             default:
                 Log.e(this, new IllegalStateException(),
                         "Unexpected message code");
         }
     }
 
+    public void quitStateMachine() {
+        quitNow();
+    }
+
     private void setSpeakerphoneOn(boolean on) {
         if (mAudioManager.isSpeakerphoneOn() != on) {
             Log.i(this, "turning speaker phone %s", on);
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index c885181..1a80cfa 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -208,6 +208,8 @@
                 statusBarNotifier,
                 audioServiceFactory
         );
+        callAudioRouteStateMachine.initialize();
+
         CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter =
                 new CallAudioRoutePeripheralAdapter(
                         callAudioRouteStateMachine,
@@ -802,23 +804,26 @@
 
         call.setHandle(uriHandle);
         call.setGatewayInfo(gatewayInfo);
-        // Auto-enable speakerphone if the originating intent specified to do so, or if the call
-        // is a video call.
-        call.setStartWithSpeakerphoneOn(speakerphoneOn || isSpeakerphoneAutoEnabled(videoState));
+
+        final boolean useSpeakerWhenDocked = mContext.getResources().getBoolean(
+                R.bool.use_speaker_when_docked);
+        final boolean isDocked = mDockManager.isDocked();
+        final boolean useSpeakerForVideoCall = isSpeakerphoneAutoEnabled(videoState);
+
+        // Auto-enable speakerphone if the originating intent specified to do so, if the call
+        // is a video call, of if using speaker when docked
+        call.setStartWithSpeakerphoneOn(speakerphoneOn || useSpeakerForVideoCall
+                || (useSpeakerWhenDocked && isDocked));
         call.setVideoState(videoState);
 
         if (speakerphoneOn) {
             Log.i(this, "%s Starting with speakerphone as requested", call);
-        } else {
+        } else if (useSpeakerWhenDocked && useSpeakerWhenDocked) {
             Log.i(this, "%s Starting with speakerphone because car is docked.", call);
+        } else if (useSpeakerForVideoCall) {
+            Log.i(this, "%s Starting with speakerphone because its a video call.", call);
         }
 
-        final boolean useSpeakerWhenDocked = mContext.getResources().getBoolean(
-                R.bool.use_speaker_when_docked);
-
-        call.setStartWithSpeakerphoneOn(speakerphoneOn
-                || (useSpeakerWhenDocked && mDockManager.isDocked()));
-
         if (call.isEmergencyCall()) {
             // Emergency -- CreateConnectionProcessor will choose accounts automatically
             call.setTargetPhoneAccount(null);
@@ -1302,7 +1307,8 @@
         return getFirstCallWithState(OUTGOING_CALL_STATES);
     }
 
-    Call getFirstCallWithState(int... states) {
+    @VisibleForTesting
+    public Call getFirstCallWithState(int... states) {
         return getFirstCallWithState(null, states);
     }
 
@@ -1581,9 +1587,7 @@
      * MMI codes which can be dialed when one or more calls are in progress.
      * <P>
      * Checks for numbers formatted similar to the MMI codes defined in:
-     * {@link com.android.internal.telephony.GsmCdmaPhone#handleInCallMmiCommands(String)}
-     * and
-     * {@link com.android.internal.telephony.imsphone.ImsPhone#handleInCallMmiCommands(String)}
+     * {@link com.android.internal.telephony.Phone#handleInCallMmiCommands(String)}
      *
      * @param handle The URI to call.
      * @return {@code True} if the URI represents a number which could be an in-call MMI code.
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 10e2844..d6fffcc 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -81,8 +81,19 @@
         public boolean isDefaultOrSystemDialer(Context context, String packageName) {
             return DefaultDialerManager.isDefaultOrSystemDialer(context, packageName);
         }
-
     }
+
+    public interface SubscriptionManagerAdapter {
+        int getDefaultVoiceSubId();
+    }
+
+    static class SubscriptionManagerAdapterImpl implements SubscriptionManagerAdapter {
+        @Override
+        public int getDefaultVoiceSubId() {
+            return SubscriptionManager.getDefaultVoiceSubId();
+        }
+    }
+
     private static final String PERMISSION_PROCESS_PHONE_ACCOUNT_REGISTRATION =
             "android.permission.PROCESS_PHONE_ACCOUNT_REGISTRATION";
     private static final int DEFAULT_VIDEO_STATE = -1;
@@ -489,7 +500,7 @@
                                     accountHandle);
                             return null;
                         }
-                        int subId = SubscriptionManager.getDefaultVoiceSubId();
+                        int subId = mSubscriptionManagerAdapter.getDefaultVoiceSubId();
                         if (accountHandle != null) {
                             subId = mPhoneAccountRegistrar
                                     .getSubscriptionIdForPhoneAccount(accountHandle);
@@ -1159,6 +1170,7 @@
     private final CallIntentProcessor.Adapter mCallIntentProcessorAdapter;
     private final UserCallIntentProcessorFactory mUserCallIntentProcessorFactory;
     private final DefaultDialerManagerAdapter mDefaultDialerManagerAdapter;
+    private final SubscriptionManagerAdapter mSubscriptionManagerAdapter;
     private final TelecomSystem.SyncRoot mLock;
 
     public TelecomServiceImpl(
@@ -1168,6 +1180,7 @@
             CallIntentProcessor.Adapter callIntentProcessorAdapter,
             UserCallIntentProcessorFactory userCallIntentProcessorFactory,
             DefaultDialerManagerAdapter defaultDialerManagerAdapter,
+            SubscriptionManagerAdapter subscriptionManagerAdapter,
             TelecomSystem.SyncRoot lock) {
         mContext = context;
         mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
@@ -1181,6 +1194,7 @@
         mUserCallIntentProcessorFactory = userCallIntentProcessorFactory;
         mDefaultDialerManagerAdapter = defaultDialerManagerAdapter;
         mCallIntentProcessorAdapter = callIntentProcessorAdapter;
+        mSubscriptionManagerAdapter = subscriptionManagerAdapter;
     }
 
     public ITelecomService.Stub getBinder() {
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index 6b9a7d7..5b4604d 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -181,6 +181,7 @@
                     }
                 },
                 new TelecomServiceImpl.DefaultDialerManagerAdapterImpl(),
+                new TelecomServiceImpl.SubscriptionManagerAdapterImpl(),
                 mLock);
     }
 
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
new file mode 100644
index 0000000..9565cbd
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.telecom.tests;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.telecom.Analytics;
+import com.android.server.telecom.Log;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.os.Process;
+import android.telecom.Call;
+import android.telecom.CallAudioState;
+import android.telecom.Connection;
+import android.telecom.DisconnectCause;
+import android.telecom.ParcelableCall;
+import android.telecom.TelecomManager;
+import android.telecom.VideoProfile;
+
+import com.android.internal.telecom.IInCallAdapter;
+
+import java.io.StringWriter;
+import java.util.Map;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Performs various basic call tests in Telecom.
+ */
+public class BasicCallTests extends TelecomSystemTest {
+    public void testSingleOutgoingCallLocalDisconnect() throws Exception {
+        IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+
+        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
+        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+
+        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
+        assertEquals(Call.STATE_DISCONNECTED,
+                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+        assertEquals(Call.STATE_DISCONNECTED,
+                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+    }
+
+    public void testSingleOutgoingCallRemoteDisconnect() throws Exception {
+        IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+
+        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
+        assertEquals(Call.STATE_DISCONNECTED,
+                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+        assertEquals(Call.STATE_DISCONNECTED,
+                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+    }
+
+    /**
+     * Tests the {@link TelecomManager#acceptRingingCall()} API.  Tests simple case of an incoming
+     * audio-only call.
+     *
+     * @throws Exception
+     */
+    public void testTelecomManagerAcceptRingingCall() throws Exception {
+        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
+                mConnectionServiceFixtureA);
+
+        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+
+        // Use TelecomManager API to answer the ringing call.
+        TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
+                .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
+        telecomManager.acceptRingingCall();
+
+        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
+                .answer(ids.mCallId);
+        mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
+
+        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
+    }
+
+    /**
+     * Tests the {@link TelecomManager#acceptRingingCall()} API.  Tests simple case of an incoming
+     * video call, which should be answered as video.
+     *
+     * @throws Exception
+     */
+    public void testTelecomManagerAcceptRingingVideoCall() throws Exception {
+        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
+                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+
+        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+
+        // Use TelecomManager API to answer the ringing call; the default expected behavior is to
+        // answer using whatever video state the ringing call requests.
+        TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
+                .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
+        telecomManager.acceptRingingCall();
+
+        // Answer video API should be called
+        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
+                .answerVideo(eq(ids.mCallId), eq(VideoProfile.STATE_BIDIRECTIONAL));
+        mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
+
+        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
+    }
+
+    /**
+     * Tests the {@link TelecomManager#acceptRingingCall(int)} API.  Tests answering a video call
+     * as an audio call.
+     *
+     * @throws Exception
+     */
+    public void testTelecomManagerAcceptRingingVideoCallAsAudio() throws Exception {
+        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
+                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+
+        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+
+        // Use TelecomManager API to answer the ringing call.
+        TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
+                .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
+        telecomManager.acceptRingingCall(VideoProfile.STATE_AUDIO_ONLY);
+
+        // The generic answer method on the ConnectionService is used to answer audio-only calls.
+        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
+                .answer(eq(ids.mCallId));
+        mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
+
+        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
+    }
+
+    /**
+     * Tests the {@link TelecomManager#acceptRingingCall()} API.  Tests simple case of an incoming
+     * video call, where an attempt is made to answer with an invalid video state.
+     *
+     * @throws Exception
+     */
+    public void testTelecomManagerAcceptRingingInvalidVideoState() throws Exception {
+        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
+                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+
+        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+
+        // Use TelecomManager API to answer the ringing call; the default expected behavior is to
+        // answer using whatever video state the ringing call requests.
+        TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
+                .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
+        telecomManager.acceptRingingCall(999 /* invalid videostate */);
+
+        // Answer video API should be called
+        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
+                .answerVideo(eq(ids.mCallId), eq(VideoProfile.STATE_BIDIRECTIONAL));
+        mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
+        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
+    }
+
+    public void testSingleIncomingCallLocalDisconnect() throws Exception {
+        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
+        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+
+        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
+        assertEquals(Call.STATE_DISCONNECTED,
+                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+        assertEquals(Call.STATE_DISCONNECTED,
+                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+    }
+
+    public void testSingleIncomingCallRemoteDisconnect() throws Exception {
+        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+
+        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
+        assertEquals(Call.STATE_DISCONNECTED,
+                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
+        assertEquals(Call.STATE_DISCONNECTED,
+                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+    }
+
+    public void do_testDeadlockOnOutgoingCall() throws Exception {
+        final IdPair ids = startOutgoingPhoneCall("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
+                Process.myUserHandle());
+        rapidFire(
+                new Runnable() {
+                    @Override
+                    public void run() {
+                        while (mCallerInfoAsyncQueryFactoryFixture.mRequests.size() > 0) {
+                            mCallerInfoAsyncQueryFactoryFixture.mRequests.remove(0).reply();
+                        }
+                    }
+                },
+                new Runnable() {
+                    @Override
+                    public void run() {
+                        try {
+                            mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
+                        } catch (Exception e) {
+                            Log.e(this, e, "");
+                        }
+                    }
+                });
+    }
+
+    public void testDeadlockOnOutgoingCall() throws Exception {
+        for (int i = 0; i < 100; i++) {
+            BasicCallTests test = new BasicCallTests();
+            test.setContext(getContext());
+            test.setTestContext(getTestContext());
+            test.setName(getName());
+            test.setUp();
+            test.do_testDeadlockOnOutgoingCall();
+            test.tearDown();
+        }
+    }
+
+    public void testIncomingThenOutgoingCalls() throws Exception {
+        // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
+        IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+        IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(),                mConnectionServiceFixtureA);
+
+        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId);
+        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId);
+    }
+
+    public void testOutgoingThenIncomingCalls() throws Exception {
+        // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
+        IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+        IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+        verify(mConnectionServiceFixtureA.getTestDouble())
+                .hold(outgoing.mConnectionId);
+        mConnectionServiceFixtureA.mConnectionById.get(outgoing.mConnectionId).state =
+                Connection.STATE_HOLDING;
+        mConnectionServiceFixtureA.sendSetOnHold(outgoing.mConnectionId);
+        assertEquals(Call.STATE_HOLDING,
+                mInCallServiceFixtureX.getCall(outgoing.mCallId).getState());
+        assertEquals(Call.STATE_HOLDING,
+                mInCallServiceFixtureY.getCall(outgoing.mCallId).getState());
+
+        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId);
+        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId);
+    }
+
+    public void testAudioManagerOperations() throws Exception {
+        AudioManager audioManager = (AudioManager) mComponentContextFixture.getTestDouble()
+                .getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
+
+        IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+
+        verify(audioManager, timeout(TEST_TIMEOUT)).requestAudioFocusForCall(anyInt(), anyInt());
+        verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce())
+                .setMode(AudioManager.MODE_IN_CALL);
+
+        mInCallServiceFixtureX.mInCallAdapter.mute(true);
+        verify(mAudioService, timeout(TEST_TIMEOUT))
+                .setMicrophoneMute(eq(true), any(String.class), any(Integer.class));
+        mInCallServiceFixtureX.mInCallAdapter.mute(false);
+        verify(mAudioService, timeout(TEST_TIMEOUT))
+                .setMicrophoneMute(eq(false), any(String.class), any(Integer.class));
+
+        mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER);
+        verify(audioManager, timeout(TEST_TIMEOUT))
+                .setSpeakerphoneOn(true);
+        mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_EARPIECE);
+        verify(audioManager, timeout(TEST_TIMEOUT))
+                .setSpeakerphoneOn(false);
+
+        mConnectionServiceFixtureA.
+                sendSetDisconnected(outgoing.mConnectionId, DisconnectCause.REMOTE);
+
+        verify(audioManager, timeout(TEST_TIMEOUT))
+                .abandonAudioFocusForCall();
+        verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce())
+                .setMode(AudioManager.MODE_NORMAL);
+    }
+
+    private void rapidFire(Runnable... tasks) {
+        final CyclicBarrier barrier = new CyclicBarrier(tasks.length);
+        final CountDownLatch latch = new CountDownLatch(tasks.length);
+        for (int i = 0; i < tasks.length; i++) {
+            final Runnable task = tasks[i];
+            new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        barrier.await();
+                        task.run();
+                    } catch (InterruptedException | BrokenBarrierException e){
+                        Log.e(BasicCallTests.this, e, "Unexpectedly interrupted");
+                    } finally {
+                        latch.countDown();
+                    }
+                }
+            }).start();
+        }
+        try {
+            latch.await();
+        } catch (InterruptedException e) {
+            Log.e(BasicCallTests.this, e, "Unexpectedly interrupted");
+        }
+    }
+
+        public void testBasicConferenceCall() throws Exception {
+        makeConferenceCall();
+    }
+
+    public void testAddCallToConference1() throws Exception {
+        ParcelableCall conferenceCall = makeConferenceCall();
+        IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+        // testAddCallToConference{1,2} differ in the order of arguments to InCallAdapter#conference
+        mInCallServiceFixtureX.getInCallAdapter().conference(
+                conferenceCall.getId(), callId3.mCallId);
+        Thread.sleep(200);
+
+        ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId);
+        ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId());
+        assertEquals(conferenceCall.getId(), call3.getParentCallId());
+        assertEquals(3, updatedConference.getChildCallIds().size());
+        assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId));
+    }
+
+    public void testAddCallToConference2() throws Exception {
+        ParcelableCall conferenceCall = makeConferenceCall();
+        IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+        mInCallServiceFixtureX.getInCallAdapter()
+                .conference(callId3.mCallId, conferenceCall.getId());
+        Thread.sleep(200);
+
+        ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId);
+        ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId());
+        assertEquals(conferenceCall.getId(), call3.getParentCallId());
+        assertEquals(3, updatedConference.getChildCallIds().size());
+        assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId));
+    }
+
+    private ParcelableCall makeConferenceCall() throws Exception {
+        IdPair callId1 = startAndMakeActiveOutgoingCall("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+
+        IdPair callId2 = startAndMakeActiveOutgoingCall("650-555-1213",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+
+        IInCallAdapter inCallAdapter = mInCallServiceFixtureX.getInCallAdapter();
+        inCallAdapter.conference(callId1.mCallId, callId2.mCallId);
+        // Wait for wacky non-deterministic behavior
+        Thread.sleep(200);
+        ParcelableCall call1 = mInCallServiceFixtureX.getCall(callId1.mCallId);
+        ParcelableCall call2 = mInCallServiceFixtureX.getCall(callId2.mCallId);
+        // Check that the two calls end up with a parent in the end
+        assertNotNull(call1.getParentCallId());
+        assertNotNull(call2.getParentCallId());
+        assertEquals(call1.getParentCallId(), call2.getParentCallId());
+
+        // Check to make sure that the parent call made it to the in-call service
+        String parentCallId = call1.getParentCallId();
+        ParcelableCall conferenceCall = mInCallServiceFixtureX.getCall(parentCallId);
+        assertEquals(2, conferenceCall.getChildCallIds().size());
+        assertTrue(conferenceCall.getChildCallIds().contains(callId1.mCallId));
+        assertTrue(conferenceCall.getChildCallIds().contains(callId2.mCallId));
+        return conferenceCall;
+    }
+
+    public void testAnalyticsSingleCall() throws Exception {
+        IdPair testCall = startAndMakeActiveIncomingCall(
+                "650-555-1212",
+                mPhoneAccountA0.getAccountHandle(),
+                mConnectionServiceFixtureA);
+        Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
+
+        assertTrue(analyticsMap.containsKey(testCall.mCallId));
+
+        Analytics.CallInfoImpl callAnalytics = analyticsMap.get(testCall.mCallId);
+        assertTrue(callAnalytics.startTime > 0);
+        assertEquals(0, callAnalytics.endTime);
+        assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics.callDirection);
+        assertFalse(callAnalytics.isInterrupted);
+        assertNull(callAnalytics.callTerminationReason);
+        assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
+                callAnalytics.connectionService);
+
+        mConnectionServiceFixtureA.
+                sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR);
+
+        analyticsMap = Analytics.cloneData();
+        callAnalytics = analyticsMap.get(testCall.mCallId);
+        assertTrue(callAnalytics.endTime > 0);
+        assertNotNull(callAnalytics.callTerminationReason);
+        assertEquals(DisconnectCause.ERROR, callAnalytics.callTerminationReason.getCode());
+
+        StringWriter sr = new StringWriter();
+        IndentingPrintWriter ip = new IndentingPrintWriter(sr, "    ");
+        Analytics.dump(ip);
+        String dumpResult = sr.toString();
+        String[] expectedFields = {"startTime", "endTime", "direction", "isAdditionalCall",
+                "isInterrupted", "callTechnologies", "callTerminationReason", "connectionServices"};
+        for (String field : expectedFields) {
+            assertTrue(dumpResult.contains(field));
+        }
+    }
+
+    public void testAnalyticsTwoCalls() throws Exception {
+        IdPair testCall1 = startAndMakeActiveIncomingCall(
+                "650-555-1212",
+                mPhoneAccountA0.getAccountHandle(),
+                mConnectionServiceFixtureA);
+        IdPair testCall2 = startAndMakeActiveOutgoingCall(
+                "650-555-1213",
+                mPhoneAccountA0.getAccountHandle(),
+                mConnectionServiceFixtureA);
+
+        Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
+        assertTrue(analyticsMap.containsKey(testCall1.mCallId));
+        assertTrue(analyticsMap.containsKey(testCall2.mCallId));
+
+        Analytics.CallInfoImpl callAnalytics1 = analyticsMap.get(testCall1.mCallId);
+        Analytics.CallInfoImpl callAnalytics2 = analyticsMap.get(testCall2.mCallId);
+        assertTrue(callAnalytics1.startTime > 0);
+        assertTrue(callAnalytics2.startTime > 0);
+        assertEquals(0, callAnalytics1.endTime);
+        assertEquals(0, callAnalytics2.endTime);
+
+        assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics1.callDirection);
+        assertEquals(Analytics.OUTGOING_DIRECTION, callAnalytics2.callDirection);
+
+        assertTrue(callAnalytics1.isInterrupted);
+        assertTrue(callAnalytics2.isAdditionalCall);
+
+        assertNull(callAnalytics1.callTerminationReason);
+        assertNull(callAnalytics2.callTerminationReason);
+
+        assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
+                callAnalytics1.connectionService);
+        assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
+                callAnalytics1.connectionService);
+
+        mConnectionServiceFixtureA.
+                sendSetDisconnected(testCall2.mConnectionId, DisconnectCause.REMOTE);
+        mConnectionServiceFixtureA.
+                sendSetDisconnected(testCall1.mConnectionId, DisconnectCause.ERROR);
+
+        analyticsMap = Analytics.cloneData();
+        callAnalytics1 = analyticsMap.get(testCall1.mCallId);
+        callAnalytics2 = analyticsMap.get(testCall2.mCallId);
+        assertTrue(callAnalytics1.endTime > 0);
+        assertTrue(callAnalytics2.endTime > 0);
+        assertNotNull(callAnalytics1.callTerminationReason);
+        assertNotNull(callAnalytics2.callTerminationReason);
+        assertEquals(DisconnectCause.ERROR, callAnalytics1.callTerminationReason.getCode());
+        assertEquals(DisconnectCause.REMOTE, callAnalytics2.callTerminationReason.getCode());
+    }
+}
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
index b12ef8d..e91a45b 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
@@ -38,9 +38,11 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.same;
+import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.never;
@@ -55,6 +57,19 @@
     private static final int ON = 1;
     private static final int OFF = 2;
 
+    private class StateMachineWaiter {
+        private boolean mAreStateMachineActionsComplete = false;
+
+        public void setStateMachineActionsComplete() {
+            mAreStateMachineActionsComplete = true;
+            super.notify();
+        }
+
+        public boolean areStateMachineActionsComplete() {
+            return mAreStateMachineActionsComplete;
+        }
+    }
+
     private class TestParameters {
         public String name;
         public int initialRoute;
@@ -104,6 +119,7 @@
     private CallAudioManager.AudioServiceFactory mAudioServiceFactory;
     private static final int TEST_TIMEOUT = 500;
     private AudioManager mockAudioManager;
+
     @Override
     public void setUp() throws Exception {
         super.setUp();
@@ -133,7 +149,9 @@
             } catch (Throwable e) {
                 String newMessage = "Failed at parameters: \n" + params.toString() + '\n'
                         + e.getMessage();
-                throw(new Throwable(newMessage, e));
+                Throwable t = new Throwable(newMessage, e);
+                t.setStackTrace(e.getStackTrace());
+                throw t;
             }
         }
     }
@@ -146,7 +164,9 @@
             } catch (Throwable e) {
                 String newMessage = "Failed at parameters: \n" + params.toString() + '\n'
                         + e.getMessage();
-                throw(new Throwable(newMessage, e));
+                Throwable t = new Throwable(newMessage, e);
+                t.setStackTrace(e.getStackTrace());
+                throw t;
             }
         }
     }
@@ -184,7 +204,8 @@
         verifyNewSystemCallAudioState(initState, expectedMiddleState);
         resetMocks();
 
-        stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET);
+        stateMachine.sendMessageWithSessionInfo(
+                CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET);
         verifyNewSystemCallAudioState(expectedMiddleState, initState);
     }
 
@@ -417,7 +438,7 @@
         params.add(new TestParameters(
                 "Disconnect bluetooth during earpiece", // name
                 CallAudioState.ROUTE_EARPIECE, // initialRoute
-                CallAudioState.ROUTE_EARPIECE| CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
+                CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
                 NONE, // speakerInteraction
                 NONE, // bluetoothInteraction
                 CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action
@@ -516,11 +537,11 @@
         return params;
     }
 
-    private void runParametrizedTestCaseWithFocus(TestParameters params) {
+    private void runParametrizedTestCaseWithFocus(final TestParameters params) throws Throwable {
         resetMocks();
 
         // Construct a fresh state machine on every case
-        CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine(
+        final CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine(
                 mContext,
                 mockCallsManager,
                 mockBluetoothManager,
@@ -538,7 +559,7 @@
                 params.initialRoute == CallAudioState.ROUTE_SPEAKER);
 
         // Set the initial CallAudioState object
-        CallAudioState initState = new CallAudioState(false,
+        final CallAudioState initState = new CallAudioState(false,
                 params.initialRoute, (params.availableRoutes | CallAudioState.ROUTE_SPEAKER));
         stateMachine.initialize(initState);
         // Make the state machine have focus so that we actually do something
@@ -546,19 +567,24 @@
                 CallAudioRouteStateMachine.HAS_FOCUS);
         stateMachine.sendMessageWithSessionInfo(params.action);
 
+        waitForStateMachineActionCompletion(stateMachine);
+
+        stateMachine.quitStateMachine();
+
         // Verify interactions with the speakerphone and bluetooth systems
-        switch(params.bluetoothInteraction) {
+        switch (params.bluetoothInteraction) {
             case NONE:
                 verify(mockBluetoothManager, never()).disconnectBluetoothAudio();
                 verify(mockBluetoothManager, never()).connectBluetoothAudio();
                 break;
             case ON:
-                verify(mockBluetoothManager, timeout(TEST_TIMEOUT)).connectBluetoothAudio();
+                verify(mockBluetoothManager).connectBluetoothAudio();
+
                 verify(mockBluetoothManager, never()).disconnectBluetoothAudio();
                 break;
             case OFF:
                 verify(mockBluetoothManager, never()).connectBluetoothAudio();
-                verify(mockBluetoothManager, timeout(TEST_TIMEOUT)).disconnectBluetoothAudio();
+                verify(mockBluetoothManager).disconnectBluetoothAudio();
         }
 
         switch (params.speakerInteraction) {
@@ -567,8 +593,7 @@
                 break;
             case ON: // fall through
             case OFF:
-                verify(mockAudioManager, timeout(TEST_TIMEOUT)).setSpeakerphoneOn(
-                        params.speakerInteraction == ON);
+                verify(mockAudioManager).setSpeakerphoneOn(params.speakerInteraction == ON);
         }
 
         // Verify the end state
@@ -577,11 +602,11 @@
         verifyNewSystemCallAudioState(initState, expectedState);
     }
 
-    private void runParametrizedTestCaseWithoutFocus(TestParameters params) {
+    private void runParametrizedTestCaseWithoutFocus(final TestParameters params) throws Throwable {
         resetMocks();
 
         // Construct a fresh state machine on every case
-        CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine(
+        final CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine(
                 mContext,
                 mockCallsManager,
                 mockBluetoothManager,
@@ -602,14 +627,13 @@
         stateMachine.initialize(initState);
         // Omit the focus-getting statement
         stateMachine.sendMessageWithSessionInfo(params.action);
-        try {
-            Thread.sleep(100L);
-        } catch (InterruptedException e) {
-            // Just a pause to make sure the state machine handler thread has a chance to update
-            // its state. Do nothing.
-        }
 
-        // Verify that no substantive interactions have taken place with the rest of the system
+        waitForStateMachineActionCompletion(stateMachine);
+
+        stateMachine.quitStateMachine();
+
+        // Verify that no substantive interactions have taken place with the
+        // rest of the system
         verify(mockBluetoothManager, never()).disconnectBluetoothAudio();
         verify(mockBluetoothManager, never()).connectBluetoothAudio();
         verify(mockAudioManager, never()).setSpeakerphoneOn(any(Boolean.class));
@@ -624,6 +648,24 @@
         assertEquals(expectedState, stateMachine.getCurrentCallAudioState());
     }
 
+    private void waitForStateMachineActionCompletion(CallAudioRouteStateMachine stateMachine) {
+        final CountDownLatch lock = new CountDownLatch(1);
+        Runnable actionComplete = new Runnable() {
+            @Override
+            public void run() {
+                lock.countDown();
+            }
+        };
+        stateMachine.sendMessage(CallAudioRouteStateMachine.RUN_RUNNABLE, actionComplete);
+        while (lock.getCount() > 0) {
+            try {
+                lock.await();
+            } catch (InterruptedException e) {
+                // do nothing
+            }
+        }
+   }
+
     private void verifyNewSystemCallAudioState(CallAudioState expectedOldState,
             CallAudioState expectedNewState) {
         ArgumentCaptor<CallAudioState> oldStateCaptor = ArgumentCaptor.forClass(
diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
index 0e16986..8ea3fbe 100644
--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
@@ -64,19 +64,19 @@
         @Override
         public Connection onCreateUnknownConnection(
                 PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) {
-            return new FakeConnection();
+            return new FakeConnection(request.getVideoState());
         }
 
         @Override
         public Connection onCreateIncomingConnection(
                 PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) {
-            return new FakeConnection();
+            return new FakeConnection(request.getVideoState());
         }
 
         @Override
         public Connection onCreateOutgoingConnection(
                 PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) {
-            return new FakeConnection();
+            return new FakeConnection(request.getVideoState());
         }
 
         @Override
@@ -92,12 +92,13 @@
     }
 
     public class FakeConnection extends Connection {
-        public FakeConnection() {
+        public FakeConnection(int videoState) {
             super();
             int capabilities = getConnectionCapabilities();
             capabilities |= CAPABILITY_MUTE;
             capabilities |= CAPABILITY_SUPPORT_HOLD;
             capabilities |= CAPABILITY_HOLD;
+            setVideoState(videoState);
             setConnectionCapabilities(capabilities);
             setActive();
         }
@@ -158,6 +159,9 @@
             c.isIncoming = isIncoming;
             c.isUnknown = isUnknown;
             c.capabilities |= Connection.CAPABILITY_HOLD | Connection.CAPABILITY_SUPPORT_HOLD;
+            c.videoState = request.getVideoState();
+            c.mockVideoProvider = new MockVideoProvider();
+            c.videoProvider = c.mockVideoProvider.getInterface();
             mConnectionById.put(id, c);
             mConnectionServiceDelegateAdapter.createConnection(connectionManagerPhoneAccount,
                     id, request, isIncoming, isUnknown);
@@ -253,6 +257,8 @@
         int callerDisplayNamePresentation;
         final List<String> conferenceableConnectionIds = new ArrayList<>();
         IVideoProvider videoProvider;
+        Connection.VideoProvider videoProviderImpl;
+        MockVideoProvider mockVideoProvider;
         int videoState;
         boolean isVoipAudioMode;
         Bundle extras;
diff --git a/tests/src/com/android/server/telecom/tests/MockVideoProvider.java b/tests/src/com/android/server/telecom/tests/MockVideoProvider.java
new file mode 100644
index 0000000..147d232
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/MockVideoProvider.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.telecom.tests;
+
+import org.mockito.Mockito;
+
+import android.net.Uri;
+import android.telecom.Connection;
+import android.telecom.Connection.VideoProvider;
+import android.telecom.InCallService;
+import android.telecom.InCallService.VideoCall;
+import android.telecom.Log;
+import android.telecom.VideoProfile;
+import android.view.Surface;
+
+/**
+ * Provides a mock implementation of a video provider.
+ */
+public class MockVideoProvider extends VideoProvider {
+    public static final String CAMERA_NONE = "none";
+    public static final String CAMERA_FRONT = "front";
+    public static final String CAMERA_BACK = "back";
+    public static final int CAMERA_FRONT_DIMENSIONS = 1024;
+    public static final int CAMERA_BACK_DIMENSIONS = 2048;
+    public static final long DATA_USAGE = 1024;
+    public static final int PEER_DIMENSIONS = 4096;
+    public static final int DEVICE_ORIENTATION_UNDEFINED = -1;
+    public static final float ZOOM_UNDEFINED = -1.0f;
+
+    private Surface mPreviewSurface = null;
+    private Surface mDisplaySurface = null;
+    private int mDeviceOrientation = DEVICE_ORIENTATION_UNDEFINED;
+    private float mZoom = ZOOM_UNDEFINED;
+    private VideoProfile mSessionModifyResponse = null;
+    private Uri mPauseImage = null;
+
+    /**
+     * Responds to a request to set the camera by reporting the new camera information via the
+     * {@link #changeCameraCapabilities(VideoProfile.CameraCapabilities)} API.
+     *
+     * @param cameraId The id of the camera (use ids as reported by
+     */
+    @Override
+    public void onSetCamera(String cameraId) {
+        handleCameraChange(cameraId);
+    }
+
+    /**
+     * Stores the preview surface set via the {@link VideoCall#setPreviewSurface(Surface)} API for
+     * retrieval using {@link #getPreviewSurface()}.
+     *
+     * @param surface The {@link Surface}.
+     */
+    @Override
+    public void onSetPreviewSurface(Surface surface) {
+        mPreviewSurface = surface;
+    }
+
+    /**
+     * Stores the display surface set via the {@link VideoCall#setDisplaySurface(Surface)} API for
+     * retrieval using {@link #getDisplaySurface()}.
+     *
+     * @param surface The {@link Surface}.
+     */
+    @Override
+    public void onSetDisplaySurface(Surface surface) {
+        mDisplaySurface = surface;
+    }
+
+    /**
+     * Stores the device orientation set via the {@link VideoCall#setDeviceOrientation(int)} API for
+     * retrieval using {@link #getDeviceOrientation()}.
+     *
+     * @param rotation The device orientation, in degrees.
+     */
+    @Override
+    public void onSetDeviceOrientation(int rotation) {
+        mDeviceOrientation = rotation;
+    }
+
+    /**
+     * Stores the zoom level set via the {@link VideoCall#setZoom(float)} API for retrieval using
+     * {@link #getZoom()}.
+     *
+     * @param value The camera zoom.
+     */
+    @Override
+    public void onSetZoom(float value) {
+        mZoom = value;
+    }
+
+    /**
+     * Responds to any incoming session modify request by accepting the requested profile.
+     *
+     * @param fromProfile The video profile prior to the request.
+     * @param toProfile The video profile with the requested changes made.
+     */
+    @Override
+    public void onSendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
+        super.receiveSessionModifyResponse(VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS,
+                fromProfile, toProfile);
+    }
+
+    /**
+     * Stores session modify responses received via the
+     * {@link VideoCall#sendSessionModifyResponse(VideoProfile)} API for retrieval via
+     * {@link #getSessionModifyResponse()}.
+     *
+     * @param responseProfile The response video profile.
+     */
+    @Override
+    public void onSendSessionModifyResponse(VideoProfile responseProfile) {
+        mSessionModifyResponse = responseProfile;
+    }
+
+    /**
+     * Responds to requests for camera capabilities by reporting the front camera capabilities.
+     */
+    @Override
+    public void onRequestCameraCapabilities() {
+        handleCameraChange(CAMERA_FRONT);
+    }
+
+    /**
+     * Responds to all requests for data usage by reporting {@link #DATA_USAGE}.
+     */
+    @Override
+    public void onRequestConnectionDataUsage() {
+        super.setCallDataUsage(DATA_USAGE);
+    }
+
+    /**
+     * Stores pause image URIs received via the {@link VideoCall#setPauseImage(Uri)} API for
+     * retrieval via {@link #getPauseImage()}.
+     *
+     * @param uri URI of image to display.
+     */
+    @Override
+    public void onSetPauseImage(Uri uri) {
+        mPauseImage = uri;
+    }
+
+    /**
+     * Handles a change to the current camera selection.  Responds by reporting the capabilities of
+     * the camera.
+     */
+    private void handleCameraChange(String cameraId) {
+        if (CAMERA_FRONT.equals(cameraId)) {
+            super.changeCameraCapabilities(new VideoProfile.CameraCapabilities(
+                    CAMERA_FRONT_DIMENSIONS, CAMERA_FRONT_DIMENSIONS));
+        } else if (CAMERA_BACK.equals(cameraId)) {
+            super.changeCameraCapabilities(new VideoProfile.CameraCapabilities(
+                    CAMERA_BACK_DIMENSIONS, CAMERA_BACK_DIMENSIONS));
+        }
+    }
+
+    /**
+     * Retrieves the last preview surface sent to the provider.
+     *
+     * @return the surface.
+     */
+    public Surface getPreviewSurface() {
+        return mPreviewSurface;
+    }
+
+    /**
+     * Retrieves the last display surface sent to the provider.
+     *
+     * @return the surface.
+     */
+    public Surface getDisplaySurface() {
+        return mDisplaySurface;
+    }
+
+    /**
+     * Retrieves the last device orientation sent to the provider.
+     *
+     * @return the orientation.
+     */
+    public int getDeviceOrientation() {
+        return mDeviceOrientation;
+    }
+
+    /**
+     * Retrieves the last zoom sent to the provider.
+     *
+     * @return the zoom.
+     */
+    public float getZoom() {
+        return mZoom;
+    }
+
+    /**
+     * Retrieves the last session modify response sent to the provider.
+     *
+     * @return the session modify response.
+     */
+    public VideoProfile getSessionModifyResponse() {
+        return mSessionModifyResponse;
+    }
+
+    /**
+     * Retrieves the last pause image sent to the provider.
+     *
+     * @return the pause image URI.
+     */
+    public Uri getPauseImage() {
+        return mPauseImage;
+    }
+
+    /**
+     * Sends a mock session modify request via the provider.
+     */
+    public void sendMockSessionModifyRequest() {
+        super.receiveSessionModifyRequest(new VideoProfile(VideoProfile.STATE_BIDIRECTIONAL));
+    }
+
+    /**
+     * Sends a mock session event via the provider.
+     *
+     * @param event the event.
+     */
+    public void sendMockSessionEvent(int event) {
+        super.handleCallSessionEvent(event);
+    }
+
+    /**
+     * Sends a mock peer dimension change via the provider.
+     *
+     * @param width The new width.
+     * @param height The new height.
+     */
+    public void sendMockPeerDimensions(int width, int height) {
+        super.changePeerDimensions(width, height);
+    }
+
+    /**
+     * Sends a mock video quality change via the provider.
+     *
+     * @param videoQuality the video quality.
+     */
+    public void sendMockVideoQuality(int videoQuality) {
+        super.changeVideoQuality(videoQuality);
+    }
+}
diff --git a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
index faeb34f..d725b1d 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
@@ -36,9 +36,13 @@
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
+import android.telecom.VideoProfile;
+import android.telephony.TelephonyManager;
 
 import com.android.internal.telecom.ITelecomService;
+import com.android.server.telecom.Call;
 import com.android.server.telecom.CallIntentProcessor;
+import com.android.server.telecom.CallState;
 import com.android.server.telecom.CallsManager;
 import com.android.server.telecom.PhoneAccountRegistrar;
 import com.android.server.telecom.TelecomServiceImpl;
@@ -62,9 +66,11 @@
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.argThat;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -107,6 +113,14 @@
         }
     }
 
+    public static class SubscriptionManagerAdapterFake
+            implements TelecomServiceImpl.SubscriptionManagerAdapter {
+        @Override
+        public int getDefaultVoiceSubId() {
+            return 0;
+        }
+    }
+
     private static class AnyStringIn extends ArgumentMatcher<String> {
         private Collection<String> mStrings;
         public AnyStringIn(Collection<String> strings) {
@@ -130,6 +144,8 @@
             spy(new CallIntentProcessAdapterFake());
     private TelecomServiceImpl.DefaultDialerManagerAdapter mDefaultDialerManagerAdapter =
             spy(new DefaultDialerManagerAdapterFake());
+    private TelecomServiceImpl.SubscriptionManagerAdapter mSubscriptionManagerAdapter =
+            spy(new SubscriptionManagerAdapterFake());
     @Mock private UserCallIntentProcessor mUserCallIntentProcessor;
 
     private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };
@@ -168,6 +184,7 @@
                     }
                 },
                 mDefaultDialerManagerAdapter,
+                mSubscriptionManagerAdapter,
                 mLock);
         mTSIBinder = telecomServiceImpl.getBinder();
         mComponentContextFixture.setTelecomManager(mTelecomManager);
@@ -685,7 +702,7 @@
         setDefaultDialerFailureTestHelper();
     }
 
-    public void testSetDefaultDialerNoWriteSecureSetingsPermission() throws Exception {
+    public void testSetDefaultDialerNoWriteSecureSettingsPermission() throws Exception {
         doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
                 eq(WRITE_SECURE_SETTINGS), anyString());
         setDefaultDialerFailureTestHelper();
@@ -704,6 +721,128 @@
         verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class));
     }
 
+    public void testIsVoicemailNumber() throws Exception {
+        String vmNumber = "010";
+        makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_CURRENT);
+
+        doReturn(true).when(mFakePhoneAccountRegistrar).isVoiceMailNumber(TEL_PA_HANDLE_CURRENT,
+                vmNumber);
+        assertTrue(mTSIBinder.isVoiceMailNumber(TEL_PA_HANDLE_CURRENT,
+                vmNumber, DEFAULT_DIALER_PACKAGE));
+    }
+
+    public void testIsVoicemailNumberAccountNotVisibleFailure() throws Exception {
+        String vmNumber = "010";
+
+        doReturn(true).when(mFakePhoneAccountRegistrar).isVoiceMailNumber(TEL_PA_HANDLE_CURRENT,
+                vmNumber);
+
+        when(mFakePhoneAccountRegistrar.getPhoneAccount(TEL_PA_HANDLE_CURRENT,
+                Binder.getCallingUserHandle())).thenReturn(null);
+        assertFalse(mTSIBinder
+                .isVoiceMailNumber(TEL_PA_HANDLE_CURRENT, vmNumber, DEFAULT_DIALER_PACKAGE));
+    }
+
+    public void testGetVoicemailNumberWithNullAccountHandle() throws Exception {
+        when(mFakePhoneAccountRegistrar.getPhoneAccount(isNull(PhoneAccountHandle.class),
+                eq(Binder.getCallingUserHandle())))
+                .thenReturn(makePhoneAccount(TEL_PA_HANDLE_CURRENT).build());
+        int subId = 58374;
+        String vmNumber = "543";
+        doReturn(subId).when(mSubscriptionManagerAdapter).getDefaultVoiceSubId();
+
+        TelephonyManager mockTelephonyManager =
+                (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+        when(mockTelephonyManager.getVoiceMailNumber(subId)).thenReturn(vmNumber);
+
+        assertEquals(vmNumber, mTSIBinder.getVoiceMailNumber(null, DEFAULT_DIALER_PACKAGE));
+    }
+
+    public void testGetVoicemailNumberWithNonNullAccountHandle() throws Exception {
+        when(mFakePhoneAccountRegistrar.getPhoneAccount(eq(TEL_PA_HANDLE_CURRENT),
+                eq(Binder.getCallingUserHandle())))
+                .thenReturn(makePhoneAccount(TEL_PA_HANDLE_CURRENT).build());
+        int subId = 58374;
+        String vmNumber = "543";
+
+        TelephonyManager mockTelephonyManager =
+                (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+        when(mockTelephonyManager.getVoiceMailNumber(subId)).thenReturn(vmNumber);
+        when(mFakePhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(TEL_PA_HANDLE_CURRENT))
+                .thenReturn(subId);
+
+        assertEquals(vmNumber,
+                mTSIBinder.getVoiceMailNumber(TEL_PA_HANDLE_CURRENT, DEFAULT_DIALER_PACKAGE));
+    }
+
+    public void testGetLine1Number() throws Exception {
+        int subId = 58374;
+        String line1Number = "9482752023479";
+        makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_CURRENT);
+        when(mFakePhoneAccountRegistrar.getSubscriptionIdForPhoneAccount(TEL_PA_HANDLE_CURRENT))
+                .thenReturn(subId);
+        TelephonyManager mockTelephonyManager =
+                (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+        when(mockTelephonyManager.getLine1NumberForSubscriber(subId)).thenReturn(line1Number);
+
+        assertEquals(line1Number,
+                mTSIBinder.getLine1Number(TEL_PA_HANDLE_CURRENT, DEFAULT_DIALER_PACKAGE));
+    }
+
+    public void testEndCallWithRingingForegroundCall() throws Exception {
+        Call call = mock(Call.class);
+        when(call.getState()).thenReturn(CallState.RINGING);
+        when(mFakeCallsManager.getForegroundCall()).thenReturn(call);
+        assertTrue(mTSIBinder.endCall());
+        verify(call).reject(false, null);
+    }
+
+    public void testEndCallWithNonRingingForegroundCall() throws Exception {
+        Call call = mock(Call.class);
+        when(call.getState()).thenReturn(CallState.ACTIVE);
+        when(mFakeCallsManager.getForegroundCall()).thenReturn(call);
+        assertTrue(mTSIBinder.endCall());
+        verify(call).disconnect();
+    }
+
+    public void testEndCallWithNoForegroundCall() throws Exception {
+        Call call = mock(Call.class);
+        when(call.getState()).thenReturn(CallState.ACTIVE);
+        when(mFakeCallsManager.getFirstCallWithState(anyInt(), anyInt(), anyInt(), anyInt()))
+                .thenReturn(call);
+        assertTrue(mTSIBinder.endCall());
+        verify(call).disconnect();
+    }
+
+    public void testEndCallWithNoCalls() throws Exception {
+        assertFalse(mTSIBinder.endCall());
+    }
+
+    public void testAcceptRingingCall() throws Exception {
+        Call call = mock(Call.class);
+        when(mFakeCallsManager.getFirstCallWithState(any(int[].class)))
+                .thenReturn(call);
+        // Not intended to be a real video state. Here to ensure that the call will be answered
+        // with whatever video state it's currently in.
+        int fakeVideoState = 29578215;
+        when(call.getVideoState()).thenReturn(fakeVideoState);
+        mTSIBinder.acceptRingingCall();
+        verify(call).answer(fakeVideoState);
+    }
+
+    public void testAcceptRingingCallWithValidVideoState() throws Exception {
+        Call call = mock(Call.class);
+        when(mFakeCallsManager.getFirstCallWithState(any(int[].class)))
+                .thenReturn(call);
+        // Not intended to be a real video state. Here to ensure that the call will be answered
+        // with the video state passed in to acceptRingingCallWithVideoState
+        int fakeVideoState = 29578215;
+        int realVideoState = VideoProfile.STATE_RX_ENABLED | VideoProfile.STATE_TX_ENABLED;
+        when(call.getVideoState()).thenReturn(fakeVideoState);
+        mTSIBinder.acceptRingingCallWithVideoState(realVideoState);
+        verify(call).answer(realVideoState);
+    }
+
     /**
      * Register phone accounts for the supplied PhoneAccountHandles to make them
      * visible to all users (via the isVisibleToCaller method in TelecomServiceImpl.
@@ -716,6 +855,9 @@
             when(mFakePhoneAccountRegistrar
                     .getPhoneAccount(eq(ph), any(UserHandle.class), anyBoolean()))
                     .thenReturn(makeMultiUserPhoneAccount(ph).build());
+            when(mFakePhoneAccountRegistrar
+                    .getPhoneAccount(eq(ph), any(UserHandle.class)))
+                    .thenReturn(makeMultiUserPhoneAccount(ph).build());
         }
     }
 
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index 7ebbb63..a4a8397 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -49,6 +49,7 @@
 import android.telecom.Connection;
 import android.telecom.ConnectionRequest;
 import android.telecom.DisconnectCause;
+import android.telecom.InCallService;
 import android.telecom.ParcelableCall;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
@@ -56,8 +57,8 @@
 import android.telecom.VideoProfile;
 
 import com.android.internal.telecom.IInCallAdapter;
+import com.android.internal.telecom.IVideoProvider;
 import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.telecom.Analytics;
 import com.android.server.telecom.BluetoothPhoneServiceImpl;
 import com.android.server.telecom.CallAudioManager;
 import com.android.server.telecom.CallIntentProcessor;
@@ -82,6 +83,7 @@
 
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
@@ -91,6 +93,9 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.CyclicBarrier;
 
+/**
+ * Implements mocks and functionality required to implement telecom system tests.
+ */
 public class TelecomSystemTest extends TelecomTestCase {
 
     static final int TEST_POLL_INTERVAL = 10;  // milliseconds
@@ -302,11 +307,9 @@
         mConnectionServiceFixtureA = new ConnectionServiceFixture();
         mConnectionServiceFixtureB = new ConnectionServiceFixture();
 
-        mComponentContextFixture.addConnectionService(
-                mConnectionServiceComponentNameA,
+        mComponentContextFixture.addConnectionService(mConnectionServiceComponentNameA,
                 mConnectionServiceFixtureA.getTestDouble());
-        mComponentContextFixture.addConnectionService(
-                mConnectionServiceComponentNameB,
+        mComponentContextFixture.addConnectionService(mConnectionServiceComponentNameB,
                 mConnectionServiceFixtureB.getTestDouble());
 
         mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA0);
@@ -330,11 +333,9 @@
         mInCallServiceFixtureX = new InCallServiceFixture();
         mInCallServiceFixtureY = new InCallServiceFixture();
 
-        mComponentContextFixture.addInCallService(
-                mInCallServiceComponentNameX,
+        mComponentContextFixture.addInCallService(mInCallServiceComponentNameX,
                 mInCallServiceFixtureX.getTestDouble());
-        mComponentContextFixture.addInCallService(
-                mInCallServiceComponentNameY,
+        mComponentContextFixture.addInCallService(mInCallServiceComponentNameY,
                 mInCallServiceFixtureY.getTestDouble());
     }
 
@@ -368,21 +369,22 @@
         return audioService;
     }
 
-    private IdPair startOutgoingPhoneCall(
-            String number,
-            PhoneAccountHandle phoneAccountHandle,
-            ConnectionServiceFixture connectionServiceFixture,
-            UserHandle initiatingUser) throws Exception {
-        reset(
-                connectionServiceFixture.getTestDouble(),
-                mInCallServiceFixtureX.getTestDouble(),
+    protected IdPair startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle,
+            ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser)
+            throws Exception {
+        return startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture,
+                initiatingUser, VideoProfile.STATE_AUDIO_ONLY);
+    }
+
+    protected IdPair startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle,
+            ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
+            int videoState) throws Exception {
+        reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(),
                 mInCallServiceFixtureY.getTestDouble());
 
-        assertEquals(
-                mInCallServiceFixtureX.mCallById.size(),
+        assertEquals(mInCallServiceFixtureX.mCallById.size(),
                 mInCallServiceFixtureY.mCallById.size());
-        assertEquals(
-                (mInCallServiceFixtureX.mInCallAdapter != null),
+        assertEquals((mInCallServiceFixtureX.mInCallAdapter != null),
                 (mInCallServiceFixtureY.mInCallAdapter != null));
 
         mNumOutgoingCallsMade++;
@@ -399,6 +401,9 @@
                     TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
                     phoneAccountHandle);
         }
+        if (videoState != VideoProfile.STATE_AUDIO_ONLY) {
+            actionCallIntent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState);
+        }
 
         final UserHandle userHandle = initiatingUser;
         Context localAppContext = mComponentContextFixture.getTestDouble().getApplicationContext();
@@ -443,35 +448,27 @@
                 new BroadcastReceiver.PendingResult(0, "", null, 0, true, false, null, 0, 0));
         newOutgoingCallReceiver.getValue().setResultData(
                 newOutgoingCallIntent.getValue().getStringExtra(Intent.EXTRA_PHONE_NUMBER));
-        newOutgoingCallReceiver.getValue().onReceive(
-                mComponentContextFixture.getTestDouble(),
+        newOutgoingCallReceiver.getValue().onReceive(mComponentContextFixture.getTestDouble(),
                 newOutgoingCallIntent.getValue());
 
         assertEquals(startingNumConnections + 1, connectionServiceFixture.mConnectionById.size());
 
-        verify(connectionServiceFixture.getTestDouble()).createConnection(
-                eq(phoneAccountHandle),
-                anyString(),
-                any(ConnectionRequest.class),
-                anyBoolean(),
-                anyBoolean());
-
+        verify(connectionServiceFixture.getTestDouble())
+                .createConnection(eq(phoneAccountHandle), anyString(), any(ConnectionRequest.class),
+                        anyBoolean(), anyBoolean());
         connectionServiceFixture.sendHandleCreateConnectionComplete(
                 connectionServiceFixture.mLatestConnectionId);
 
         assertEquals(startingNumCalls + 1, mInCallServiceFixtureX.mCallById.size());
         assertEquals(startingNumCalls + 1, mInCallServiceFixtureY.mCallById.size());
 
-        assertEquals(
-                mInCallServiceFixtureX.mLatestCallId,
-                mInCallServiceFixtureY.mLatestCallId);
+        assertEquals(mInCallServiceFixtureX.mLatestCallId, mInCallServiceFixtureY.mLatestCallId);
 
-        return new IdPair(
-                connectionServiceFixture.mLatestConnectionId,
+        return new IdPair(connectionServiceFixture.mLatestConnectionId,
                 mInCallServiceFixtureX.mLatestCallId);
     }
 
-    private IdPair startIncomingPhoneCall(
+    protected IdPair startIncomingPhoneCall(
             String number,
             PhoneAccountHandle phoneAccountHandle,
             final ConnectionServiceFixture connectionServiceFixture) throws Exception {
@@ -479,23 +476,18 @@
                 connectionServiceFixture);
     }
 
-    private IdPair startIncomingPhoneCall(
+    protected IdPair startIncomingPhoneCall(
             String number,
             PhoneAccountHandle phoneAccountHandle,
             int videoState,
             final ConnectionServiceFixture connectionServiceFixture) throws Exception {
-        reset(
-                connectionServiceFixture.getTestDouble(),
-                mInCallServiceFixtureX.getTestDouble(),
+        reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(),
                 mInCallServiceFixtureY.getTestDouble());
 
-        assertEquals(
-                mInCallServiceFixtureX.mCallById.size(),
+        assertEquals(mInCallServiceFixtureX.mCallById.size(),
                 mInCallServiceFixtureY.mCallById.size());
-        assertEquals(
-                (mInCallServiceFixtureX.mInCallAdapter != null),
+        assertEquals((mInCallServiceFixtureX.mInCallAdapter != null),
                 (mInCallServiceFixtureY.mInCallAdapter != null));
-
         final int startingNumConnections = connectionServiceFixture.mConnectionById.size();
         final int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
         boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null;
@@ -507,22 +499,17 @@
         mTelecomSystem.getTelecomServiceImpl().getBinder()
                 .addNewIncomingCall(phoneAccountHandle, extras);
 
-        verify(connectionServiceFixture.getTestDouble()).createConnection(
-                any(PhoneAccountHandle.class),
-                anyString(),
-                any(ConnectionRequest.class),
-                eq(true),
-                eq(false));
+        verify(connectionServiceFixture.getTestDouble())
+                .createConnection(any(PhoneAccountHandle.class), anyString(),
+                        any(ConnectionRequest.class), eq(true), eq(false));
 
         mConnectionServiceFixtureA.mConnectionById.get(
                 connectionServiceFixture.mLatestConnectionId).videoState = videoState;
 
         connectionServiceFixture.sendHandleCreateConnectionComplete(
                 connectionServiceFixture.mLatestConnectionId);
-        connectionServiceFixture.sendSetRinging(
-                connectionServiceFixture.mLatestConnectionId);
-        connectionServiceFixture.sendSetVideoState(
-                connectionServiceFixture.mLatestConnectionId);
+        connectionServiceFixture.sendSetRinging(connectionServiceFixture.mLatestConnectionId);
+        connectionServiceFixture.sendSetVideoState(connectionServiceFixture.mLatestConnectionId);
 
         // For the case of incoming calls, Telecom connecting the InCall services and adding the
         // Call is triggered by the async completion of the CallerInfoAsyncQuery. Once the Call
@@ -530,16 +517,10 @@
         // test fixtures, will be synchronous.
 
         if (!hasInCallAdapter) {
-            verify(
-                    mInCallServiceFixtureX.getTestDouble(),
-                    timeout(TEST_TIMEOUT))
-                    .setInCallAdapter(
-                            any(IInCallAdapter.class));
-            verify(
-                    mInCallServiceFixtureY.getTestDouble(),
-                    timeout(TEST_TIMEOUT))
-                    .setInCallAdapter(
-                            any(IInCallAdapter.class));
+            verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
+                    .setInCallAdapter(any(IInCallAdapter.class));
+            verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT))
+                    .setInCallAdapter(any(IInCallAdapter.class));
         }
 
         // Give the InCallService time to respond
@@ -558,16 +539,10 @@
             }
         });
 
-        verify(
-                mInCallServiceFixtureX.getTestDouble(),
-                timeout(TEST_TIMEOUT))
-                .addCall(
-                        any(ParcelableCall.class));
-        verify(
-                mInCallServiceFixtureY.getTestDouble(),
-                timeout(TEST_TIMEOUT))
-                .addCall(
-                        any(ParcelableCall.class));
+        verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
+                .addCall(any(ParcelableCall.class));
+        verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT))
+                .addCall(any(ParcelableCall.class));
 
         // Give the InCallService time to respond
 
@@ -591,54 +566,35 @@
             }
         });
 
-        assertEquals(
-                mInCallServiceFixtureX.mLatestCallId,
-                mInCallServiceFixtureY.mLatestCallId);
+        assertEquals(mInCallServiceFixtureX.mLatestCallId, mInCallServiceFixtureY.mLatestCallId);
 
-        return new IdPair(
-                connectionServiceFixture.mLatestConnectionId,
+        return new IdPair(connectionServiceFixture.mLatestConnectionId,
                 mInCallServiceFixtureX.mLatestCallId);
     }
 
-    private void rapidFire(Runnable... tasks) {
-        final CyclicBarrier barrier = new CyclicBarrier(tasks.length);
-        final CountDownLatch latch = new CountDownLatch(tasks.length);
-        for (int i = 0; i < tasks.length; i++) {
-            final Runnable task = tasks[i];
-            new Thread(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        barrier.await();
-                        task.run();
-                    } catch (InterruptedException | BrokenBarrierException e){
-                        Log.e(TelecomSystemTest.this, e, "Unexpectedly interrupted");
-                    } finally {
-                        latch.countDown();
-                    }
-                }
-            }).start();
-        }
-        try {
-            latch.await();
-        } catch (InterruptedException e) {
-            Log.e(TelecomSystemTest.this, e, "Unexpectedly interrupted");
-        }
+    protected IdPair startAndMakeActiveOutgoingCall(
+            String number,
+            PhoneAccountHandle phoneAccountHandle,
+            ConnectionServiceFixture connectionServiceFixture) throws Exception {
+        return startAndMakeActiveOutgoingCall(number, phoneAccountHandle, connectionServiceFixture,
+                VideoProfile.STATE_AUDIO_ONLY);
     }
 
     // A simple outgoing call, verifying that the appropriate connection service is contacted,
     // the proper lifecycle is followed, and both In-Call Services are updated correctly.
-    private IdPair startAndMakeActiveOutgoingCall(
+    protected IdPair startAndMakeActiveOutgoingCall(
             String number,
             PhoneAccountHandle phoneAccountHandle,
-            ConnectionServiceFixture connectionServiceFixture) throws Exception {
+            ConnectionServiceFixture connectionServiceFixture, int videoState) throws Exception {
         IdPair ids = startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture,
-                Process.myUserHandle());
+                Process.myUserHandle(), videoState);
 
         connectionServiceFixture.sendSetDialing(ids.mConnectionId);
         assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
         assertEquals(Call.STATE_DIALING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
 
+        connectionServiceFixture.sendSetVideoState(ids.mConnectionId);
+
         connectionServiceFixture.sendSetActive(ids.mConnectionId);
         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
@@ -646,214 +602,35 @@
         return ids;
     }
 
-    public void testBasicConferenceCall() throws Exception {
-        makeConferenceCall();
-    }
-
-    public void testAddCallToConference1() throws Exception {
-        ParcelableCall conferenceCall = makeConferenceCall();
-        IdPair callId3 = startAndMakeActiveOutgoingCall(
-                "650-555-1214",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-        // testAddCallToConference{1,2} differ in the order of arguments to InCallAdapter#conference
-        mInCallServiceFixtureX.getInCallAdapter().conference(
-                conferenceCall.getId(), callId3.mCallId);
-        Thread.sleep(200);
-
-        ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId);
-        ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId());
-        assertEquals(conferenceCall.getId(), call3.getParentCallId());
-        assertEquals(3, updatedConference.getChildCallIds().size());
-        assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId));
-    }
-
-    public void testAddCallToConference2() throws Exception {
-        ParcelableCall conferenceCall = makeConferenceCall();
-        IdPair callId3 = startAndMakeActiveOutgoingCall(
-                "650-555-1214",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-        mInCallServiceFixtureX.getInCallAdapter().conference(
-                callId3.mCallId, conferenceCall.getId());
-        Thread.sleep(200);
-
-        ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId);
-        ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId());
-        assertEquals(conferenceCall.getId(), call3.getParentCallId());
-        assertEquals(3, updatedConference.getChildCallIds().size());
-        assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId));
-    }
-
-    private ParcelableCall makeConferenceCall() throws Exception {
-        IdPair callId1 = startAndMakeActiveOutgoingCall(
-                "650-555-1212",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-
-        IdPair callId2 = startAndMakeActiveOutgoingCall(
-                "650-555-1213",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-
-        IInCallAdapter inCallAdapter = mInCallServiceFixtureX.getInCallAdapter();
-        inCallAdapter.conference(callId1.mCallId, callId2.mCallId);
-        // Wait for wacky non-deterministic behavior
-        Thread.sleep(200);
-        ParcelableCall call1 = mInCallServiceFixtureX.getCall(callId1.mCallId);
-        ParcelableCall call2 = mInCallServiceFixtureX.getCall(callId2.mCallId);
-        // Check that the two calls end up with a parent in the end
-        assertNotNull(call1.getParentCallId());
-        assertNotNull(call2.getParentCallId());
-        assertEquals(call1.getParentCallId(), call2.getParentCallId());
-
-        // Check to make sure that the parent call made it to the in-call service
-        String parentCallId = call1.getParentCallId();
-        ParcelableCall conferenceCall = mInCallServiceFixtureX.getCall(parentCallId);
-        assertEquals(2, conferenceCall.getChildCallIds().size());
-        assertTrue(conferenceCall.getChildCallIds().contains(callId1.mCallId));
-        assertTrue(conferenceCall.getChildCallIds().contains(callId2.mCallId));
-        return conferenceCall;
-    }
-
-    public void testSingleOutgoingCallLocalDisconnect() throws Exception {
-        IdPair ids = startAndMakeActiveOutgoingCall(
-                "650-555-1212",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-
-        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
-        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
-        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
-
-        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
-        assertEquals(Call.STATE_DISCONNECTED,
-                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
-        assertEquals(Call.STATE_DISCONNECTED,
-                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
-    }
-
-    public void testSingleOutgoingCallRemoteDisconnect() throws Exception {
-        IdPair ids = startAndMakeActiveOutgoingCall(
-                "650-555-1212",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-
-        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
-        assertEquals(Call.STATE_DISCONNECTED,
-                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
-        assertEquals(Call.STATE_DISCONNECTED,
-                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
-    }
-
-    /**
-     * Tests the {@link TelecomManager#acceptRingingCall()} API.  Tests simple case of an incoming
-     * audio-only call.
-     *
-     * @throws Exception
-     */
-    public void testTelecomManagerAcceptRingingCall() throws Exception {
-        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-
-        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
-        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
-
-        // Use TelecomManager API to answer the ringing call.
-        TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
-                .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
-        telecomManager.acceptRingingCall();
-
-        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
-                .answer(ids.mCallId);
-    }
-
-    /**
-     * Tests the {@link TelecomManager#acceptRingingCall()} API.  Tests simple case of an incoming
-     * video call, which should be answered as video.
-     *
-     * @throws Exception
-     */
-    public void testTelecomManagerAcceptRingingVideoCall() throws Exception {
-        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
-                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
-
-        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
-        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
-
-        // Use TelecomManager API to answer the ringing call; the default expected behavior is to
-        // answer using whatever video state the ringing call requests.
-        TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
-                .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
-        telecomManager.acceptRingingCall();
-
-        // Answer video API should be called
-        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
-                .answerVideo(eq(ids.mCallId), eq(VideoProfile.STATE_BIDIRECTIONAL));
-    }
-
-    /**
-     * Tests the {@link TelecomManager#acceptRingingCall(int)} API.  Tests answering a video call
-     * as an audio call.
-     *
-     * @throws Exception
-     */
-    public void testTelecomManagerAcceptRingingVideoCallAsAudio() throws Exception {
-        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
-                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
-
-        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
-        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
-
-        // Use TelecomManager API to answer the ringing call.
-        TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
-                .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
-        telecomManager.acceptRingingCall(VideoProfile.STATE_AUDIO_ONLY);
-
-        // The generic answer method on the ConnectionService is used to answer audio-only calls.
-        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
-                .answer(eq(ids.mCallId));
-    }
-
-    /**
-     * Tests the {@link TelecomManager#acceptRingingCall()} API.  Tests simple case of an incoming
-     * video call, where an attempt is made to answer with an invalid video state.
-     *
-     * @throws Exception
-     */
-    public void testTelecomManagerAcceptRingingInvalidVideoState() throws Exception {
-        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
-                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
-
-        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
-        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
-
-        // Use TelecomManager API to answer the ringing call; the default expected behavior is to
-        // answer using whatever video state the ringing call requests.
-        TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
-                .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
-        telecomManager.acceptRingingCall(999 /* invalid videostate */);
-
-        // Answer video API should be called
-        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
-                .answerVideo(eq(ids.mCallId), eq(VideoProfile.STATE_BIDIRECTIONAL));
-    }
-
-    // A simple incoming call, similar in scope to the previous test
-    private IdPair startAndMakeActiveIncomingCall(
+    protected IdPair startAndMakeActiveIncomingCall(
             String number,
             PhoneAccountHandle phoneAccountHandle,
             ConnectionServiceFixture connectionServiceFixture) throws Exception {
+        return startAndMakeActiveIncomingCall(number, phoneAccountHandle, connectionServiceFixture,
+                VideoProfile.STATE_AUDIO_ONLY);
+    }
+
+    // A simple incoming call, similar in scope to the previous test
+    protected IdPair startAndMakeActiveIncomingCall(
+            String number,
+            PhoneAccountHandle phoneAccountHandle,
+            ConnectionServiceFixture connectionServiceFixture,
+            int videoState) throws Exception {
         IdPair ids = startIncomingPhoneCall(number, phoneAccountHandle, connectionServiceFixture);
 
         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
         assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
 
         mInCallServiceFixtureX.mInCallAdapter
-                .answerCall(ids.mCallId, VideoProfile.STATE_AUDIO_ONLY);
+                .answerCall(ids.mCallId, videoState);
 
-        verify(connectionServiceFixture.getTestDouble())
-                .answer(ids.mConnectionId);
+        if (!VideoProfile.isVideo(videoState)) {
+            verify(connectionServiceFixture.getTestDouble())
+                    .answer(ids.mConnectionId);
+        } else {
+            verify(connectionServiceFixture.getTestDouble())
+                    .answerVideo(ids.mConnectionId, videoState);
+        }
 
         connectionServiceFixture.sendSetActive(ids.mConnectionId);
         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
@@ -862,236 +639,6 @@
         return ids;
     }
 
-    public void testSingleIncomingCallLocalDisconnect() throws Exception {
-        IdPair ids = startAndMakeActiveIncomingCall(
-                "650-555-1212",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-
-        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
-        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
-        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
-
-        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
-        assertEquals(Call.STATE_DISCONNECTED,
-                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
-        assertEquals(Call.STATE_DISCONNECTED,
-                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
-    }
-
-    public void testSingleIncomingCallRemoteDisconnect() throws Exception {
-        IdPair ids = startAndMakeActiveIncomingCall(
-                "650-555-1212",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-
-        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
-        assertEquals(Call.STATE_DISCONNECTED,
-                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
-        assertEquals(Call.STATE_DISCONNECTED,
-                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
-    }
-
-    public void do_testDeadlockOnOutgoingCall() throws Exception {
-        final IdPair ids = startOutgoingPhoneCall(
-                "650-555-1212",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA,
-                Process.myUserHandle());
-        rapidFire(
-                new Runnable() {
-                    @Override
-                    public void run() {
-                        while (mCallerInfoAsyncQueryFactoryFixture.mRequests.size() > 0) {
-                            mCallerInfoAsyncQueryFactoryFixture.mRequests.remove(0).reply();
-                        }
-                    }
-                },
-                new Runnable() {
-                    @Override
-                    public void run() {
-                        try {
-                            mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
-                        } catch (Exception e) {
-                            Log.e(this, e, "");
-                        }
-                    }
-                });
-    }
-
-    public void testDeadlockOnOutgoingCall() throws Exception {
-        for (int i = 0; i < 100; i++) {
-            TelecomSystemTest test = new TelecomSystemTest();
-            test.setContext(getContext());
-            test.setTestContext(getTestContext());
-            test.setName(getName());
-            test.setUp();
-            test.do_testDeadlockOnOutgoingCall();
-            test.tearDown();
-        }
-    }
-
-    public void testIncomingThenOutgoingCalls() throws Exception {
-        // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
-        IdPair incoming = startAndMakeActiveIncomingCall(
-                "650-555-2323",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-        IdPair outgoing = startAndMakeActiveOutgoingCall(
-                "650-555-1212",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-    }
-
-    public void testOutgoingThenIncomingCalls() throws Exception {
-        // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
-        IdPair outgoing = startAndMakeActiveOutgoingCall(
-                "650-555-1212",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-        IdPair incoming = startAndMakeActiveIncomingCall(
-                "650-555-2323",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-        verify(mConnectionServiceFixtureA.getTestDouble())
-                .hold(outgoing.mConnectionId);
-        mConnectionServiceFixtureA.mConnectionById.get(outgoing.mConnectionId).state =
-                Connection.STATE_HOLDING;
-        mConnectionServiceFixtureA.sendSetOnHold(outgoing.mConnectionId);
-        assertEquals(
-                Call.STATE_HOLDING,
-                mInCallServiceFixtureX.getCall(outgoing.mCallId).getState());
-        assertEquals(
-                Call.STATE_HOLDING,
-                mInCallServiceFixtureY.getCall(outgoing.mCallId).getState());
-    }
-
-    public void testAnalyticsSingleCall() throws Exception {
-        IdPair testCall = startAndMakeActiveIncomingCall(
-                "650-555-1212",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-                Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
-
-        assertTrue(analyticsMap.containsKey(testCall.mCallId));
-
-        Analytics.CallInfoImpl callAnalytics = analyticsMap.get(testCall.mCallId);
-        assertTrue(callAnalytics.startTime > 0);
-        assertEquals(0, callAnalytics.endTime);
-        assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics.callDirection);
-        assertFalse(callAnalytics.isInterrupted);
-        assertNull(callAnalytics.callTerminationReason);
-        assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
-                callAnalytics.connectionService);
-
-        mConnectionServiceFixtureA.
-                sendSetDisconnected(testCall.mConnectionId, DisconnectCause.ERROR);
-
-        analyticsMap = Analytics.cloneData();
-        callAnalytics = analyticsMap.get(testCall.mCallId);
-        assertTrue(callAnalytics.endTime > 0);
-        assertNotNull(callAnalytics.callTerminationReason);
-        assertEquals(DisconnectCause.ERROR, callAnalytics.callTerminationReason.getCode());
-
-        StringWriter sr = new StringWriter();
-        IndentingPrintWriter ip = new IndentingPrintWriter(sr, "    ");
-        Analytics.dump(ip);
-        String dumpResult = sr.toString();
-        String[] expectedFields = {"startTime", "endTime", "direction", "isAdditionalCall",
-                "isInterrupted", "callTechnologies", "callTerminationReason", "connectionServices"};
-        for (String field : expectedFields) {
-            assertTrue(dumpResult.contains(field));
-        }
-    }
-
-    public void testAnalyticsTwoCalls() throws Exception {
-        IdPair testCall1 = startAndMakeActiveIncomingCall(
-                "650-555-1212",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-        IdPair testCall2 = startAndMakeActiveOutgoingCall(
-                "650-555-1213",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-
-        Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
-        assertTrue(analyticsMap.containsKey(testCall1.mCallId));
-        assertTrue(analyticsMap.containsKey(testCall2.mCallId));
-
-        Analytics.CallInfoImpl callAnalytics1 = analyticsMap.get(testCall1.mCallId);
-        Analytics.CallInfoImpl callAnalytics2 = analyticsMap.get(testCall2.mCallId);
-        assertTrue(callAnalytics1.startTime > 0);
-        assertTrue(callAnalytics2.startTime > 0);
-        assertEquals(0, callAnalytics1.endTime);
-        assertEquals(0, callAnalytics2.endTime);
-
-        assertEquals(Analytics.INCOMING_DIRECTION, callAnalytics1.callDirection);
-        assertEquals(Analytics.OUTGOING_DIRECTION, callAnalytics2.callDirection);
-
-        assertTrue(callAnalytics1.isInterrupted);
-        assertTrue(callAnalytics2.isAdditionalCall);
-
-        assertNull(callAnalytics1.callTerminationReason);
-        assertNull(callAnalytics2.callTerminationReason);
-
-        assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
-                callAnalytics1.connectionService);
-        assertEquals(mConnectionServiceComponentNameA.flattenToShortString(),
-                callAnalytics1.connectionService);
-
-        mConnectionServiceFixtureA.
-                sendSetDisconnected(testCall2.mConnectionId, DisconnectCause.REMOTE);
-        mConnectionServiceFixtureA.
-                sendSetDisconnected(testCall1.mConnectionId, DisconnectCause.ERROR);
-
-        analyticsMap = Analytics.cloneData();
-        callAnalytics1 = analyticsMap.get(testCall1.mCallId);
-        callAnalytics2 = analyticsMap.get(testCall2.mCallId);
-        assertTrue(callAnalytics1.endTime > 0);
-        assertTrue(callAnalytics2.endTime > 0);
-        assertNotNull(callAnalytics1.callTerminationReason);
-        assertNotNull(callAnalytics2.callTerminationReason);
-        assertEquals(DisconnectCause.ERROR, callAnalytics1.callTerminationReason.getCode());
-        assertEquals(DisconnectCause.REMOTE, callAnalytics2.callTerminationReason.getCode());
-    }
-
-    public void testAudioManagerOperations() throws Exception {
-        AudioManager audioManager = (AudioManager) mComponentContextFixture.getTestDouble()
-                .getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
-
-        IdPair outgoing = startAndMakeActiveOutgoingCall(
-                "650-555-1212",
-                mPhoneAccountA0.getAccountHandle(),
-                mConnectionServiceFixtureA);
-
-        verify(audioManager, timeout(TEST_TIMEOUT))
-                .requestAudioFocusForCall(anyInt(), anyInt());
-        verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce())
-                .setMode(AudioManager.MODE_IN_CALL);
-
-        mInCallServiceFixtureX.mInCallAdapter.mute(true);
-        verify(mAudioService, timeout(TEST_TIMEOUT))
-                .setMicrophoneMute(eq(true), any(String.class), any(Integer.class));
-        mInCallServiceFixtureX.mInCallAdapter.mute(false);
-        verify(mAudioService, timeout(TEST_TIMEOUT))
-                .setMicrophoneMute(eq(false), any(String.class), any(Integer.class));
-
-        mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER);
-        verify(audioManager, timeout(TEST_TIMEOUT))
-                .setSpeakerphoneOn(true);
-        mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_EARPIECE);
-        verify(audioManager, timeout(TEST_TIMEOUT))
-                .setSpeakerphoneOn(false);
-
-        mConnectionServiceFixtureA.
-                sendSetDisconnected(outgoing.mConnectionId, DisconnectCause.REMOTE);
-
-        verify(audioManager, timeout(TEST_TIMEOUT))
-                .abandonAudioFocusForCall();
-        verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce())
-                .setMode(AudioManager.MODE_NORMAL);
-    }
-
     protected static void assertTrueWithTimeout(Predicate<Void> predicate) {
         int elapsed = 0;
         while (elapsed < TEST_TIMEOUT) {
diff --git a/tests/src/com/android/server/telecom/tests/VideoCallTests.java b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
new file mode 100644
index 0000000..ab29c5b
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.telecom.tests;
+
+import org.mockito.ArgumentCaptor;
+
+import android.telecom.CallAudioState;
+import android.telecom.VideoProfile;
+
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+/**
+ * System tests for video-specific behavior in telecom.
+ * TODO: Add unit tests which ensure that auto-speakerphone does not occur when using a wired
+ * headset or a bluetooth headset.
+ */
+public class VideoCallTests extends TelecomSystemTest {
+
+    /**
+     * Tests to ensure an incoming video-call is automatically routed to the speakerphone when
+     * the call is answered and neither a wired headset nor bluetooth headset are connected.
+     */
+    public void testAutoSpeakerphoneIncomingBidirectional() throws Exception {
+        // Start an incoming video call.
+        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
+                VideoProfile.STATE_BIDIRECTIONAL);
+
+        verifyAudioRoute(CallAudioState.ROUTE_SPEAKER, 3);
+    }
+
+    /**
+     * Tests to ensure an incoming receive-only video-call is answered in speakerphone mode.  Note
+     * that this is not a scenario we would expect normally with the default dialer as it will
+     * always answer incoming video calls as bi-directional.  It is, however, possible for a third
+     * party dialer to answer an incoming video call a a one-way video call.
+     */
+    public void testAutoSpeakerphoneIncomingReceiveOnly() throws Exception {
+        // Start an incoming video call.
+        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
+                VideoProfile.STATE_RX_ENABLED);
+
+        verifyAudioRoute(CallAudioState.ROUTE_SPEAKER, 3);
+    }
+
+    /**
+     * Tests audio routing for an outgoing video call made with bidirectional video.  Expect to be
+     * in speaker mode.
+     */
+    public void testAutoSpeakerphoneOutgoingBidirectional() throws Exception {
+        // Start an incoming video call.
+        IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
+                VideoProfile.STATE_BIDIRECTIONAL);
+
+        verifyAudioRoute(CallAudioState.ROUTE_SPEAKER, 3);
+    }
+
+    /**
+     * Tests audio routing for an outgoing video call made with transmit only video.  Expect to be
+     * in speaker mode.  Note: The default UI does not support making one-way video calls, but the
+     * APIs do and a third party incall UI could choose to support that.
+     */
+    public void testAutoSpeakerphoneOutgoingTransmitOnly() throws Exception {
+        // Start an incoming video call.
+        IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
+                VideoProfile.STATE_TX_ENABLED);
+
+        verifyAudioRoute(CallAudioState.ROUTE_SPEAKER, 3);
+    }
+
+    /**
+     * Tests audio routing for an outgoing video call made with transmit only video.  Expect to be
+     * in speaker mode.  Note: The default UI does not support making one-way video calls, but the
+     * APIs do and a third party incall UI could choose to support that.
+     */
+    public void testNoAutoSpeakerphoneOnOutgoing() throws Exception {
+        // Start an incoming video call.
+        IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
+                VideoProfile.STATE_AUDIO_ONLY);
+
+        verifyAudioRoute(CallAudioState.ROUTE_EARPIECE, 2);
+    }
+
+    /**
+     * Tests to ensure an incoming audio-only call is routed to the earpiece.
+     */
+    public void testNoAutoSpeakerphoneOnIncoming() throws Exception {
+
+        // Start an incoming video call.
+        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
+                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
+                VideoProfile.STATE_AUDIO_ONLY);
+
+        verifyAudioRoute(CallAudioState.ROUTE_EARPIECE, 2);
+    }
+
+    /**
+     * Verifies that the
+     * {@link android.telecom.InCallService#onCallAudioStateChanged(CallAudioState)} change is
+     * called with an expected route and number of changes.
+     *
+     * @param expectedRoute The expected audio route on the latest change.
+     * @param audioStateChangeCount The number of audio state changes expected.  This is set based
+     *                              on how many times we expect the audio route to change when
+     *                              setting up a call.  For an audio-only call, we normally expect
+     *                              2 route changes, and for a video call we expect an extra change.
+     */
+    private void verifyAudioRoute(int expectedRoute, int audioStateChangeCount) throws Exception {
+        // Capture all onCallAudioStateChanged callbacks to InCall.
+        ArgumentCaptor<CallAudioState> callAudioStateArgumentCaptor = ArgumentCaptor.forClass(
+                CallAudioState.class);
+        verify(mInCallServiceFixtureX.getTestDouble(),
+                timeout(TEST_TIMEOUT).times(audioStateChangeCount)).
+                onCallAudioStateChanged(callAudioStateArgumentCaptor.capture());
+        assertEquals(expectedRoute,
+                callAudioStateArgumentCaptor.getAllValues().get(audioStateChangeCount - 1)
+                        .getRoute());
+    }
+}
diff --git a/tests/src/com/android/server/telecom/tests/VideoProviderTest.java b/tests/src/com/android/server/telecom/tests/VideoProviderTest.java
new file mode 100644
index 0000000..d6585d9
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/VideoProviderTest.java
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.telecom.tests;
+
+import com.android.server.telecom.CallAudioManager;
+import com.android.server.telecom.Log;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.internal.exceptions.ExceptionIncludingMockitoWarnings;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Camera;
+import android.graphics.SurfaceTexture;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.telecom.Call;
+import android.telecom.CallAudioState;
+import android.telecom.Connection;
+import android.telecom.Connection.VideoProvider;
+import android.telecom.InCallService;
+import android.telecom.InCallService.VideoCall;
+import android.telecom.ParcelableCall;
+import android.telecom.TelecomManager;
+import android.telecom.VideoCallImpl;
+import android.telecom.VideoProfile;
+import android.telecom.VideoProfile.CameraCapabilities;
+import android.view.Surface;
+
+import com.google.common.base.Predicate;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.RunnableFuture;
+import java.util.concurrent.TimeUnit;
+
+import static android.test.MoreAsserts.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Performs tests of the {@link VideoProvider} and {@link VideoCall} APIs.  Ensures that requests
+ * sent from an InCallService are routed through Telecom to a VideoProvider, and that callbacks are
+ * correctly routed.
+ */
+public class VideoProviderTest extends TelecomSystemTest {
+    private static final int ORIENTATION_0 = 0;
+    private static final int ORIENTATION_90 = 90;
+    private static final float ZOOM_LEVEL = 3.0f;
+
+    @Mock private VideoCall.Callback mVideoCallCallback;
+    private IdPair mCallIds;
+    private InCallService.VideoCall mVideoCall;
+    private VideoCallImpl mVideoCallImpl;
+    private ConnectionServiceFixture.ConnectionInfo mConnectionInfo;
+    private CountDownLatch mVerificationLock;
+
+    private Answer mVerification = new Answer() {
+        @Override
+        public Object answer(InvocationOnMock i) {
+            mVerificationLock.countDown();
+            return null;
+        }
+    };
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        mCallIds = startAndMakeActiveOutgoingCall(
+                "650-555-1212",
+                mPhoneAccountA0.getAccountHandle(),
+                mConnectionServiceFixtureA);
+
+        // Set the video provider on the connection.
+        mConnectionServiceFixtureA.sendSetVideoProvider(
+                mConnectionServiceFixtureA.mLatestConnectionId);
+
+        // Provide a mocked VideoCall.Callback to receive callbacks via.
+        mVideoCallCallback = mock(InCallService.VideoCall.Callback.class);
+
+        mVideoCall = mInCallServiceFixtureX.getCall(mCallIds.mCallId).getVideoCallImpl();
+        mVideoCallImpl = (VideoCallImpl) mVideoCall;
+        mVideoCall.registerCallback(mVideoCallCallback);
+
+        mConnectionInfo = mConnectionServiceFixtureA.mConnectionById.get(mCallIds.mConnectionId);
+        mVerificationLock = new CountDownLatch(1);
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Tests the {@link VideoCall#setCamera(String)}, {@link VideoProvider#onSetCamera(String)},
+     * and {@link VideoCall.Callback#onCameraCapabilitiesChanged(CameraCapabilities)}
+     * APIS.
+     */
+    public void testCameraChange() throws Exception {
+        // Wait until the callback has been received before performing verification.
+        doAnswer(mVerification).when(mVideoCallCallback)
+                .onCameraCapabilitiesChanged(any(CameraCapabilities.class));
+
+        // Make 2 setCamera requests.
+        mVideoCall.setCamera(MockVideoProvider.CAMERA_FRONT);
+        mVideoCall.setCamera(MockVideoProvider.CAMERA_BACK);
+
+        mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+        // Capture the video profile reported via the callback.
+        ArgumentCaptor<CameraCapabilities> cameraCapabilitiesCaptor =
+                ArgumentCaptor.forClass(CameraCapabilities.class);
+
+        // Verify that the callback was called twice and capture the callback arguments.
+        verify(mVideoCallCallback, timeout(TEST_TIMEOUT).times(2))
+                .onCameraCapabilitiesChanged(cameraCapabilitiesCaptor.capture());
+
+        assertEquals(2, cameraCapabilitiesCaptor.getAllValues().size());
+
+        List<CameraCapabilities> cameraCapabilities = cameraCapabilitiesCaptor.getAllValues();
+        // Ensure dimensions are as expected.
+        assertEquals(MockVideoProvider.CAMERA_FRONT_DIMENSIONS,
+                cameraCapabilities.get(0).getHeight());
+        assertEquals(MockVideoProvider.CAMERA_BACK_DIMENSIONS,
+                cameraCapabilities.get(1).getHeight());
+    }
+
+    /**
+     * Tests the {@link VideoCall#setPreviewSurface(Surface)} and
+     * {@link VideoProvider#onSetPreviewSurface(Surface)} APIs.
+     */
+    public void testSetPreviewSurface() throws Exception {
+        final Surface surface = new Surface(new SurfaceTexture(1));
+        mVideoCall.setPreviewSurface(surface);
+
+        assertTrueWithTimeout(new Predicate<Void>() {
+            @Override
+            public boolean apply(Void v) {
+                return mConnectionInfo.mockVideoProvider.getPreviewSurface() == surface;
+            }
+        });
+
+        mVideoCall.setPreviewSurface(null);
+
+        assertTrueWithTimeout(new Predicate<Void>() {
+            @Override
+            public boolean apply(Void v) {
+                return mConnectionInfo.mockVideoProvider.getPreviewSurface() == null;
+            }
+        });
+    }
+
+    /**
+     * Tests the {@link VideoCall#setDisplaySurface(Surface)} and
+     * {@link VideoProvider#onSetDisplaySurface(Surface)} APIs.
+     */
+    public void testSetDisplaySurface() throws Exception {
+        final Surface surface = new Surface(new SurfaceTexture(1));
+        mVideoCall.setDisplaySurface(surface);
+
+        assertTrueWithTimeout(new Predicate<Void>() {
+            @Override
+            public boolean apply(Void v) {
+                return mConnectionInfo.mockVideoProvider.getDisplaySurface() == surface;
+            }
+        });
+
+        mVideoCall.setDisplaySurface(null);
+
+        assertTrueWithTimeout(new Predicate<Void>() {
+            @Override
+            public boolean apply(Void v) {
+                return mConnectionInfo.mockVideoProvider.getDisplaySurface() == null;
+            }
+        });
+    }
+
+    /**
+     * Tests the {@link VideoCall#setDeviceOrientation(int)} and
+     * {@link VideoProvider#onSetDeviceOrientation(int)} APIs.
+     */
+    public void testSetDeviceOrientation() throws Exception {
+        mVideoCall.setDeviceOrientation(ORIENTATION_0);
+
+        assertTrueWithTimeout(new Predicate<Void>() {
+            @Override
+            public boolean apply(Void v) {
+                return mConnectionInfo.mockVideoProvider.getDeviceOrientation() == ORIENTATION_0;
+            }
+        });
+
+        mVideoCall.setDeviceOrientation(ORIENTATION_90);
+
+        assertTrueWithTimeout(new Predicate<Void>() {
+            @Override
+            public boolean apply(Void v) {
+                return mConnectionInfo.mockVideoProvider.getDeviceOrientation() == ORIENTATION_90;
+            }
+        });
+    }
+
+    /**
+     * Tests the {@link VideoCall#setZoom(float)} and {@link VideoProvider#onSetZoom(float)} APIs.
+     */
+    public void testSetZoom() throws Exception {
+        mVideoCall.setZoom(ZOOM_LEVEL);
+
+        assertTrueWithTimeout(new Predicate<Void>() {
+            @Override
+            public boolean apply(Void v) {
+                return mConnectionInfo.mockVideoProvider.getZoom() == ZOOM_LEVEL;
+            }
+        });
+    }
+
+    /**
+     * Tests the {@link VideoCall#sendSessionModifyRequest(VideoProfile)},
+     * {@link VideoProvider#onSendSessionModifyRequest(VideoProfile, VideoProfile)},
+     * {@link VideoProvider#receiveSessionModifyResponse(int, VideoProfile, VideoProfile)}, and
+     * {@link VideoCall.Callback#onSessionModifyResponseReceived(int, VideoProfile, VideoProfile)}
+     * APIs.
+     *
+     * Emulates a scenario where an InCallService sends a request to upgrade to video, which the
+     * peer accepts as-is.
+     */
+    public void testSessionModifyRequest() throws Exception {
+        VideoProfile requestProfile = new VideoProfile(VideoProfile.STATE_BIDIRECTIONAL);
+
+        // Set the starting video state on the video call impl; normally this would be set based on
+        // the original android.telecom.Call instance.
+        mVideoCallImpl.setVideoState(VideoProfile.STATE_RX_ENABLED);
+
+        doAnswer(mVerification).when(mVideoCallCallback)
+                .onSessionModifyResponseReceived(anyInt(), any(VideoProfile.class),
+                        any(VideoProfile.class));
+
+        // Send the request.
+        mVideoCall.sendSessionModifyRequest(requestProfile);
+
+        mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+        // Capture the video profiles from the callback.
+        ArgumentCaptor<VideoProfile> fromVideoProfileCaptor =
+                ArgumentCaptor.forClass(VideoProfile.class);
+        ArgumentCaptor<VideoProfile> toVideoProfileCaptor =
+                ArgumentCaptor.forClass(VideoProfile.class);
+
+        // Verify we got a response and capture the profiles.
+        verify(mVideoCallCallback, timeout(TEST_TIMEOUT))
+                .onSessionModifyResponseReceived(eq(VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS),
+                        fromVideoProfileCaptor.capture(), toVideoProfileCaptor.capture());
+
+        assertEquals(VideoProfile.STATE_RX_ENABLED,
+                fromVideoProfileCaptor.getValue().getVideoState());
+        assertEquals(VideoProfile.STATE_BIDIRECTIONAL,
+                toVideoProfileCaptor.getValue().getVideoState());
+    }
+
+    /**
+     * Tests the {@link VideoCall#sendSessionModifyResponse(VideoProfile)},
+     * and {@link VideoProvider#onSendSessionModifyResponse(VideoProfile)} APIs.
+     */
+    public void testSessionModifyResponse() throws Exception {
+        VideoProfile sessionModifyResponse = new VideoProfile(VideoProfile.STATE_TX_ENABLED);
+
+        mVideoCall.sendSessionModifyResponse(sessionModifyResponse);
+
+        assertTrueWithTimeout(new Predicate<Void>() {
+            @Override
+            public boolean apply(Void v) {
+                VideoProfile response = mConnectionInfo.mockVideoProvider
+                        .getSessionModifyResponse();
+                return response != null && response.getVideoState() == VideoProfile.STATE_TX_ENABLED;
+            }
+        });
+    }
+
+    /**
+     * Tests the {@link VideoCall#requestCameraCapabilities()} ()},
+     * {@link VideoProvider#onRequestCameraCapabilities()} ()}, and
+     * {@link VideoCall.Callback#onCameraCapabilitiesChanged(CameraCapabilities)} APIs.
+     */
+    public void testRequestCameraCapabilities() throws Exception {
+        // Wait until the callback has been received before performing verification.
+        doAnswer(mVerification).when(mVideoCallCallback)
+                .onCameraCapabilitiesChanged(any(CameraCapabilities.class));
+
+        mVideoCall.requestCameraCapabilities();
+
+        mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+        verify(mVideoCallCallback, timeout(TEST_TIMEOUT))
+                .onCameraCapabilitiesChanged(any(CameraCapabilities.class));
+    }
+
+    /**
+     * Tests the {@link VideoCall#setPauseImage(Uri)}, and
+     * {@link VideoProvider#onSetPauseImage(Uri)} APIs.
+     */
+    public void testSetPauseImage() throws Exception {
+        final Uri testUri = Uri.fromParts("file", "test.jpg", null);
+        mVideoCall.setPauseImage(testUri);
+
+        assertTrueWithTimeout(new Predicate<Void>() {
+            @Override
+            public boolean apply(Void v) {
+                Uri pauseImage = mConnectionInfo.mockVideoProvider.getPauseImage();
+                return pauseImage != null && pauseImage.equals(testUri);
+            }
+        });
+    }
+
+    /**
+     * Tests the {@link VideoCall#requestCallDataUsage()},
+     * {@link VideoProvider#onRequestConnectionDataUsage()}, and
+     * {@link VideoCall.Callback#onCallDataUsageChanged(long)} APIs.
+     */
+    public void testRequestDataUsage() throws Exception {
+        // Wait until the callback has been received before performing verification.
+        doAnswer(mVerification).when(mVideoCallCallback)
+                .onCallDataUsageChanged(anyLong());
+
+        mVideoCall.requestCallDataUsage();
+
+        mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+        verify(mVideoCallCallback, timeout(TEST_TIMEOUT))
+                .onCallDataUsageChanged(eq(MockVideoProvider.DATA_USAGE));
+    }
+
+    /**
+     * Tests the {@link VideoProvider#receiveSessionModifyRequest(VideoProfile)},
+     * {@link VideoCall.Callback#onSessionModifyRequestReceived(VideoProfile)} APIs.
+     */
+    public void testReceiveSessionModifyRequest() throws Exception {
+        // Wait until the callback has been received before performing verification.
+        doAnswer(mVerification).when(mVideoCallCallback)
+                .onSessionModifyRequestReceived(any(VideoProfile.class));
+
+        mConnectionInfo.mockVideoProvider.sendMockSessionModifyRequest();
+
+        mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+        ArgumentCaptor<VideoProfile> requestProfileCaptor =
+                ArgumentCaptor.forClass(VideoProfile.class);
+        verify(mVideoCallCallback, timeout(TEST_TIMEOUT))
+                .onSessionModifyRequestReceived(requestProfileCaptor.capture());
+        assertEquals(VideoProfile.STATE_BIDIRECTIONAL,
+                requestProfileCaptor.getValue().getVideoState());
+    }
+
+
+    /**
+     * Tests the {@link VideoProvider#handleCallSessionEvent(int)}, and
+     * {@link VideoCall.Callback#onCallSessionEvent(int)} APIs.
+     */
+    public void testSessionEvent() throws Exception {
+        // Wait until the callback has been received before performing verification.
+        doAnswer(mVerification).when(mVideoCallCallback)
+                .onCallSessionEvent(anyInt());
+
+        mConnectionInfo.mockVideoProvider.sendMockSessionEvent(
+                VideoProvider.SESSION_EVENT_CAMERA_READY);
+
+        mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+        verify(mVideoCallCallback, timeout(TEST_TIMEOUT))
+                .onCallSessionEvent(eq(VideoProvider.SESSION_EVENT_CAMERA_READY));
+    }
+
+    /**
+     * Tests the {@link VideoProvider#changePeerDimensions(int, int)} and
+     * {@link VideoCall.Callback#onPeerDimensionsChanged(int, int)} APIs.
+     */
+    public void testPeerDimensionChange() throws Exception {
+        // Wait until the callback has been received before performing verification.
+        doAnswer(mVerification).when(mVideoCallCallback)
+                .onPeerDimensionsChanged(anyInt(), anyInt());
+
+        mConnectionInfo.mockVideoProvider.sendMockPeerDimensions(MockVideoProvider.PEER_DIMENSIONS,
+                MockVideoProvider.PEER_DIMENSIONS);
+
+        mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+        verify(mVideoCallCallback, timeout(TEST_TIMEOUT))
+                .onPeerDimensionsChanged(eq(MockVideoProvider.PEER_DIMENSIONS),
+                        eq(MockVideoProvider.PEER_DIMENSIONS));
+    }
+
+    /**
+     * Tests the {@link VideoProvider#changeVideoQuality(int)} and
+     * {@link VideoCall.Callback#onVideoQualityChanged(int)} APIs.
+     */
+    public void testVideoQualityChange() throws Exception {
+        // Wait until the callback has been received before performing verification.
+        doAnswer(mVerification).when(mVideoCallCallback)
+                .onVideoQualityChanged(anyInt());
+
+        mConnectionInfo.mockVideoProvider.sendMockVideoQuality(VideoProfile.QUALITY_HIGH);
+
+        mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+
+        verify(mVideoCallCallback, timeout(TEST_TIMEOUT))
+                .onVideoQualityChanged(eq(VideoProfile.QUALITY_HIGH));
+    }
+}