Merge "Rename PhoneNumberUtils APIs" into mnc-dev
diff --git a/Android.mk b/Android.mk
index 0a93c32..1440fcc 100644
--- a/Android.mk
+++ b/Android.mk
@@ -32,7 +32,6 @@
 LOCAL_JAVA_LIBRARIES := telephony-common
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-common \
-    android-ex-variablespeed \
     android-support-v13 \
     android-support-v4 \
     android-support-v7-cardview \
@@ -42,8 +41,6 @@
     guava \
     libphonenumber
 
-LOCAL_REQUIRED_MODULES := libvariablespeed
-
 LOCAL_PACKAGE_NAME := Dialer
 LOCAL_CERTIFICATE := shared
 LOCAL_PRIVILEGED_MODULE := true
diff --git a/res/layout/call_detail.xml b/res/layout/call_detail.xml
index c077851..5d1607e 100644
--- a/res/layout/call_detail.xml
+++ b/res/layout/call_detail.xml
@@ -87,6 +87,12 @@
             </LinearLayout>
         </LinearLayout>
 
+        <com.android.dialer.voicemail.VoicemailPlaybackLayout
+            android:id="@+id/voicemail_playback_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:visibility="gone" />
+
         <!--
           The list view is under everything.
           It contains a first header element which is hidden under the controls UI.
diff --git a/res/mipmap-xxxhdpi/ic_launcher_phone.png b/res/mipmap-xxxhdpi/ic_launcher_phone.png
index 26f51f1..8c92ac1 100644
--- a/res/mipmap-xxxhdpi/ic_launcher_phone.png
+++ b/res/mipmap-xxxhdpi/ic_launcher_phone.png
Binary files differ
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 49a6bd9..cd2bc26 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Spoedbel"</string>
     <string name="tab_recents" msgid="929949073851377206">"Onlangse kontakte"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kontakte"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Stemboodskap"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Verwyder uit gunstelinge"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Ontdoen"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Bel <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 35c474d..ec86001 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"ፈጣን ደውል"</string>
     <string name="tab_recents" msgid="929949073851377206">"የቅርብ ጊዜዎቹ"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"ዕውቂያዎች"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"የድምፅ መልዕክት"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"ከተወዳጆች ውስጥ ተወግዷል።"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"ቀልብስ"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"ለ<xliff:g id="NUMBER">%s</xliff:g> ደውል"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 0f7fc02..86fd385 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -135,6 +135,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"اتصال سريع"</string>
     <string name="tab_recents" msgid="929949073851377206">"الحديثة"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"جهات الاتصال"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"البريد الصوتي"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"تمت إزالة جهة الاتصال من المفضلة"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"تراجع"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"الاتصال بالرقم <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-az-rAZ/strings.xml b/res/values-az-rAZ/strings.xml
index 4b5ef9b..e53efce 100644
--- a/res/values-az-rAZ/strings.xml
+++ b/res/values-az-rAZ/strings.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!--
+<!-- 
   ~ Copyright (C) 2012 The Android Open Source Project
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,54 +18,53 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="applicationLabel" msgid="8490255569343340580">"Nömrə yığan"</string>
+    <string name="launcherActivityLabel" msgid="1129729740601172692">"Telefon"</string>
     <string name="dialerIconLabel" msgid="6500826552823403796">"Telefon"</string>
-    <string name="recentCallsIconLabel" msgid="1419116422359067949">"Zəng jurnalı"</string>
+    <string name="recentCallsIconLabel" msgid="2639489159797075507">"Zəng tarixçəsi"</string>
     <string name="recentCalls_callNumber" msgid="1756372533999226126">"Zəng <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="recentCalls_editNumberBeforeCall" msgid="7756171675833267857">"Zəng etmədən öncə nömrəyə düzəliş edin"</string>
     <string name="recentCalls_addToContact" msgid="1429899535546487008">"Kontaktlara əlavə edin"</string>
-    <string name="recentCalls_removeFromRecentList" msgid="401662244636511330">"Zəng jurnalından silin"</string>
-    <string name="recentCalls_deleteAll" msgid="6352364392762163704">"Zəng jurnalını təmizləyin"</string>
+    <string name="recentCalls_removeFromRecentList" msgid="5551148439199439404">"Zəng tarixçəsindən sil"</string>
+    <string name="recentCalls_deleteAll" msgid="5157887960461979812">"Zəng tarixçəsini təmizlə"</string>
     <string name="recentCalls_trashVoicemail" msgid="7604696960787435655">"Səsli məktubu silin"</string>
     <string name="recentCalls_shareVoicemail" msgid="1416112847592942840">"Səsli məktubu paylaşın"</string>
-    <string name="recentCalls_empty" msgid="247053222448663107">"Zəng jurnalı boşdur."</string>
-    <string name="clearCallLogConfirmation_title" msgid="6427524640461816332">"Zəng jurnalı silinsin?"</string>
-    <string name="clearCallLogConfirmation" msgid="5043563133171583152">"Bütün zəng qeydləriniz silinəcək."</string>
-    <string name="clearCallLogProgress_title" msgid="8365943000154295771">"Zəng jurnalı silinir..."</string>
-  <plurals name="notification_voicemail_title">
-    <item quantity="one" msgid="1746619685488504230">"Səsli məktub"</item>
-    <item quantity="other" msgid="5513481419205061254">"<xliff:g id="COUNT">%1$d</xliff:g> Səsli məktub"</item>
-  </plurals>
+    <string name="recentCalls_empty" msgid="8555115547405030734">"Zəng yoxdur"</string>
+    <string name="clearCallLogConfirmation_title" msgid="801753155679372984">"Zəng tarixçəsi təmizlənsin?"</string>
+    <string name="clearCallLogConfirmation" msgid="7899552396101432827">"Bu, tarixçənizdən bütün zəngləri siləcəkdir"</string>
+    <string name="clearCallLogProgress_title" msgid="3372471156216306132">"Zəng tarixçəsi silinir…"</string>
+    <plurals name="notification_voicemail_title" formatted="false" msgid="9088953961148324851">
+      <item quantity="other"> <xliff:g id="COUNT">%1$d</xliff:g> Səsli poçt </item>
+      <item quantity="one">Səsli poçt</item>
+    </plurals>
     <string name="notification_action_voicemail_play" msgid="6113133136977996863">"Oxudun"</string>
     <string name="notification_voicemail_callers_list" msgid="1153954809339404149">"<xliff:g id="NEWER_CALLERS">%1$s</xliff:g>, <xliff:g id="OLDER_CALLER">%2$s</xliff:g>"</string>
     <string name="notification_new_voicemail_ticker" msgid="895342132049452081">"<xliff:g id="CALLER">%1$s</xliff:g> adlı şəxsdən yeni səsli məktub"</string>
-    <string name="voicemail_playback_error" msgid="1811242131549854624">"Səsli məktub oxudula bilmədi."</string>
+    <string name="voicemail_playback_error" msgid="3356071912353297599">"Səsli poçtu səsləndirmək mümkün deyil"</string>
     <string name="voicemail_buffering" msgid="738287747618697097">"Buferlənir..."</string>
-    <string name="voicemail_fetching_content" msgid="877911315738258780">"Səsli məktub əldə edilir..."</string>
-    <string name="voicemail_fetching_timout" msgid="6691792377574905201">"Səsli məktub əldə edilə bilmədi."</string>
+    <string name="voicemail_fetching_content" msgid="1287895365599580842">"Səsli poçt yüklənir…"</string>
+    <string name="voicemail_fetching_timout" msgid="3959428065511972176">"Səsli poçtu yükləmək mümkün olmadı"</string>
     <string name="call_log_voicemail_header" msgid="3945407886667089173">"Yalnız səsli məktublu zənglər"</string>
     <string name="call_log_incoming_header" msgid="2787722299753674684">"Yalnız daxil olan zənglər"</string>
     <string name="call_log_outgoing_header" msgid="761009180766735769">"Yalnız gedən zənglər"</string>
     <string name="call_log_missed_header" msgid="8017148056610855956">"Yalnız buraxılmış zənglər"</string>
-    <string name="voicemail_status_voicemail_not_available" msgid="3021980206152528883">"Səsli poçt serverinə birləşmək olmur."</string>
-    <string name="voicemail_status_messages_waiting" msgid="7113421459602803605">"Səsli poçt serveri ilə bağlantı yaratmaq olmur. Yeni səsli poçtlar gözlənilir."</string>
-    <string name="voicemail_status_configure_voicemail" msgid="3738537770636895689">"Səsli poçtunuzu quraşdırın."</string>
-    <string name="voicemail_status_audio_not_available" msgid="3369618334553341626">"Audio əlçatımlı deyil."</string>
+    <string name="voicemail_status_voicemail_not_available" msgid="5222480147701456390">"Səsli poçt yeniləmələri mövcud deyil"</string>
+    <string name="voicemail_status_messages_waiting" msgid="6329544650250068650">"Yeni səsli poçt gözləyir. İndi yükləmək mümkün deyil."</string>
+    <string name="voicemail_status_configure_voicemail" msgid="8300808991932816153">"Səsli poçtunuzu qurun"</string>
+    <string name="voicemail_status_audio_not_available" msgid="2449801102560158082">"Audio mövcud deyil"</string>
     <string name="voicemail_status_action_configure" msgid="8671796489912239589">"Quraşdırın"</string>
     <string name="voicemail_status_action_call_server" msgid="1824816252288551794">"Səsli poçta zəng edin"</string>
-    <string name="voicemail_speed_slowest" msgid="1733460666177707312">"Ən alçaq sürət"</string>
-    <string name="voicemail_speed_slower" msgid="1508601287347216244">"Zəif sürət"</string>
-    <string name="voicemail_speed_normal" msgid="9033988544627228892">"Normal sürət"</string>
-    <string name="voicemail_speed_faster" msgid="2019965121475935488">"Yüksək sürət"</string>
-    <string name="voicemail_speed_fastest" msgid="5758712343491183292">"Ən yüksək sürət"</string>
     <string name="call_log_item_count_and_date" msgid="7641933305703520787">"(<xliff:g id="COUNT">%1$d</xliff:g>) <xliff:g id="DATE">%2$s</xliff:g>"</string>
     <string name="sms_disambig_title" msgid="5846266399240630846">"Nömrə seçin"</string>
     <string name="call_disambig_title" msgid="4392886850104795739">"Nömrə seçin"</string>
     <string name="make_primary" msgid="5829291915305113983">"Bu seçimi yadda saxla"</string>
-    <string name="description_voicemail_button" msgid="3402506823655455591">"Səsli məktub"</string>
     <string name="description_search_button" msgid="3660807558587384889">"axtarış"</string>
     <string name="description_dial_button" msgid="1274091017188142646">"nömrə yığın"</string>
-    <string name="description_delete_button" msgid="6263102114033407382">"backspace"</string>
     <string name="description_digits_edittext" msgid="8760207516497016437">"yığmaq üçün nömrə"</string>
+    <string name="description_playback_start_stop" msgid="5060732345522492292">"Oxudun və ya dayandırın"</string>
+    <string name="description_playback_speakerphone" msgid="6008323900245707504">"Spikerfonu aktiv və ya deaktiv edin"</string>
+    <string name="description_playback_seek" msgid="4509404274968530055">"Oxutma pozisiyası axtarın"</string>
+    <string name="description_rate_decrease" msgid="3161652589401708284">"Oxutma reytinqini azaldın"</string>
+    <string name="description_rate_increase" msgid="6324606574127052385">"Oxutma reytinqini artırın"</string>
     <string name="action_menu_call_history_description" msgid="9018442816219748968">"Çağrı Tarixçəsi"</string>
     <string name="action_menu_overflow_description" msgid="2303272250613084574">"Daha çox seçim"</string>
     <string name="action_menu_dialpad_button" msgid="1425910318049008136">"nömrə yığımı paneli"</string>
@@ -77,32 +76,39 @@
     <string name="menu_show_all_calls" msgid="7560347482073345885">"Bütün zəngləri göstərin"</string>
     <string name="add_2sec_pause" msgid="9214012315201040129">"2 saniyəlik pauza əlavə edin"</string>
     <string name="add_wait" msgid="3360818652790319634">"Gözləmə əlavə edin"</string>
+    <string name="dialer_settings_label" msgid="4305043242594150479">"Ayarlar"</string>
     <string name="menu_newContact" msgid="1209922412763274638">"Yeni kontakt"</string>
     <string name="menu_allContacts" msgid="6948308384034051670">"Bütün kontaktlar"</string>
     <string name="callDetailTitle" msgid="5340227785196217938">"Zəng detalları"</string>
-    <string name="toast_call_detail_error" msgid="7200975244804730096">"Sorğu göndərilmiş zəng üçün detallar oxuna bilmədi."</string>
+    <string name="toast_call_detail_error" msgid="6947041258280380832">"Təfərrüatlar mövcud deyil"</string>
     <string name="dialer_useDtmfDialpad" msgid="1707548397435075040">"Toxunma ton klaviaturasını istifadə edin"</string>
     <string name="dialer_returnToInCallScreen" msgid="3719386377550913067">"Davam edən zəngə qayıdın"</string>
     <string name="dialer_addAnotherCall" msgid="4205688819890074468">"Zəng əlavə edin"</string>
     <string name="type_incoming" msgid="6502076603836088532">"Gələn zəng"</string>
     <string name="type_outgoing" msgid="343108709599392641">"Gedən zəng"</string>
     <string name="type_missed" msgid="2720502601640509542">"Buraxılmış zəng"</string>
+    <string name="type_incoming_video" msgid="82323391702796181">"Gələn video zəng"</string>
+    <string name="type_outgoing_video" msgid="2858140021680755266">"Gedən video zəng"</string>
+    <string name="type_missed_video" msgid="954396897034220545">"Buraxılmış video zəng"</string>
     <string name="type_voicemail" msgid="5153139450668549908">"Səsli poçt"</string>
     <string name="actionIncomingCall" msgid="6028930669817038600">"Gələn zənglər"</string>
     <string name="description_call_log_play_button" msgid="651182125650429846">"Səsli məktubu oxudun"</string>
     <string name="description_view_contact" msgid="5205669345700598415">"<xliff:g id="NAME">%1$s</xliff:g> adlı kontakta baxın"</string>
     <string name="description_call" msgid="3443678121983852666">"Zəng edin: <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="description_send_text_message" msgid="7803126439934046891">"<xliff:g id="NAME">%1$s</xliff:g> mesaj göndər"</string>
+    <string name="description_contact_details" msgid="51229793651342809">"<xliff:g id="NAMEORNUMBER">%1$s</xliff:g> üçün kontakt detalları"</string>
+    <string name="description_new_voicemail" msgid="2133792360865517746">"Yeni səsli poçt."</string>
+    <string name="description_num_calls" msgid="1601505153694540074">"<xliff:g id="NUMBEROFCALLS">%1$s</xliff:g> zəng."</string>
+    <string name="description_video_call" msgid="2933838090743214204">"Video çağrı."</string>
+    <string name="description_send_text_message" msgid="3118485319691414221">"<xliff:g id="NAME">%1$s</xliff:g> adlı şəxsə SMS göndər"</string>
     <string name="description_call_log_unheard_voicemail" msgid="118101684236996786">"Eşidilməmiş səsli mesaj"</string>
     <string name="description_start_voice_search" msgid="520539488194946012">"Səs axtarışına başlayın"</string>
     <string name="menu_callNumber" msgid="997146291983360266">"<xliff:g id="NUMBER">%s</xliff:g> zəng edin"</string>
     <string name="unknown" msgid="740067747858270469">"Naməlum"</string>
     <string name="voicemail" msgid="3851469869202611441">"Səsli poçt"</string>
     <string name="private_num" msgid="6374339738119166953">"Şəxsi nömrə"</string>
-    <string name="payphone" msgid="4864313342828942922">"Telefon ödənişi"</string>
-    <string name="dialerKeyboardHintText" msgid="5401660096579787344">"Nömrə yığmaq üçün klaviaturadan istifadə ediin"</string>
-    <string name="callDetailsDurationFormat" msgid="8157706382818184268">"<xliff:g id="MINUTES">%s</xliff:g> dəqiqə <xliff:g id="SECONDS">%s</xliff:g> saniyə"</string>
-    <string name="dialog_phone_call_prohibited_message" msgid="6554711866586660441">"Zəng edilmədi"</string>
+    <string name="payphone" msgid="7726415831153618726">"Taksofon"</string>
+    <string name="callDetailsDurationFormat" msgid="6061406028764382234">"<xliff:g id="MINUTES">%s</xliff:g> dəq <xliff:g id="SECONDS">%s</xliff:g> san"</string>
+    <string name="dialog_phone_call_prohibited_message" msgid="5730565540182492608">"Bu nömrəyə zəng etmək mümkün deyil"</string>
     <string name="dialog_voicemail_not_ready_message" msgid="4384716252789515378">"Səsli poçtu ayarlamaq üçün Menyu, sonra isə &gt; Ayarlara daxil olun."</string>
     <string name="dialog_voicemail_airplane_mode_message" msgid="530922773669546093">"Səsli poçta zəng etmək üçün Təyyarə rejimini söndürün."</string>
     <string name="contact_list_loading" msgid="5488620820563977329">"Yüklənir…"</string>
@@ -110,17 +116,76 @@
     <string name="meid" msgid="6210568493746275750">"MEID"</string>
     <string name="simContacts_emptyLoading" msgid="6700035985448642408">"SIM kartdan yüklənir..."</string>
     <string name="simContacts_title" msgid="27341688347689769">"SIM kart kontaktları"</string>
-    <string name="add_contact_not_available" msgid="1419207765446461366">"Bu özəlliyi istifadə etmək üçün Adamlar tətbiqinə yenidən icazə verin."</string>
-    <!-- no translation found for dialer_hint_find_contact (8798845521253672403) -->
-    <skip />
-    <string name="call_log_all_title" msgid="3566738938889333307">"Bütün"</string>
-    <string name="call_log_missed_title" msgid="4541142293870638971">"Buraxılmış"</string>
-    <string name="recentMissed_empty" msgid="5427113551557296665">"Buraxılmış zəng yoxdur"</string>
-    <string name="recentVoicemails_empty" msgid="5163114119598014048">"Səsli məktub yoxdur."</string>
+    <string name="add_contact_not_available" msgid="5547311613368004859">"Əlaqələr proqramı mövcud deyil"</string>
+    <string name="voice_search_not_available" msgid="2977719040254285301">"Səsli axtarış mövcud deyil"</string>
+    <string name="call_not_available" msgid="8941576511946492225">"Telefon tətbiqi deaktiv edildiyinə görə telefon zəngi etmək mümkün deyil."</string>
+    <string name="activity_not_available" msgid="2287665636817987623">"Bu cihazda onun üçün heç bir proqram yoxdur"</string>
+    <string name="dialer_hint_find_contact" msgid="1012544667033887519">"Ad və ya tel. nömrəsi daxil et"</string>
+    <string name="recentMissed_empty" msgid="4901789420356796156">"Zəng yoxdur"</string>
+    <string name="recentVoicemails_empty" msgid="8582424947259156664">"Son səsli poçt yoxdur"</string>
     <string name="show_favorites_only" msgid="5520072531022614595">"Yalnız seçilmişləri göstər"</string>
     <string name="call_log_activity_title" msgid="4612824396355272023">"Tarixçə"</string>
-    <!-- no translation found for favorite_hidden (5011234945140912047) -->
-    <skip />
+    <string name="call_log_all_title" msgid="3566738938889333307">"Bütün"</string>
+    <string name="call_log_missed_title" msgid="4541142293870638971">"Buraxılmış"</string>
+    <string name="call_log_voicemail_title" msgid="940422274047025948">"Səsli poçt"</string>
+    <string name="tab_speed_dial" msgid="7552166276545648893">"Sürətli nömrə yığımı"</string>
+    <string name="tab_recents" msgid="929949073851377206">"Sonuncular"</string>
+    <string name="tab_all_contacts" msgid="1410922767166533690">"Kontaktlar"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Səsli poçt"</string>
+    <string name="favorite_hidden" msgid="5011234945140912047">"Seçilmişlərdən silindi"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Geri qaytar"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g> nömrəsinə zəng edin"</string>
+    <string name="search_shortcut_create_new_contact" msgid="1679917465521554093">"Yeni kontakt yaradın"</string>
+    <string name="search_shortcut_add_to_existing_contact" msgid="4403132207405813444">"Mövcud kontakta əlavə edin"</string>
+    <string name="search_shortcut_send_sms_message" msgid="2569304043345025525">"SMS göndərin"</string>
+    <string name="search_shortcut_make_video_call" msgid="1265971685034465166">"Video zəng edin"</string>
+    <string name="show_call_history" msgid="1141502332266697170">"Tam çağrı tarixçəsinə baxın"</string>
+    <string name="num_missed_calls" msgid="8081736535604293886">"<xliff:g id="NUMBER">%s</xliff:g> yeni buraxılmış zəng"</string>
+    <string name="speed_dial_empty" msgid="1931474498966072849">"Sürətli nömrə yığımı seçilmişlər və tez-tez zəng etdiyiniz nömrələr üçün bir toxunuşla zəng deməkdir"</string>
+    <string name="all_contacts_empty" msgid="2299508125100209367">"Əlaqə yoxdur"</string>
+    <string name="contact_tooltip" msgid="2019777545923635266">"Bütün nömrələri görmək üçün təsvirə toxunun və ya yenidən qaydaya salmaq üçün toxunun və saxlayın"</string>
+    <string name="remove_contact" msgid="1080555335283662961">"Yığışdır"</string>
+    <string name="favorites_menu_all_contacts" msgid="992506284449891186">"BÜTÜN KONTAKTLAR"</string>
+    <string name="call_log_action_video_call" msgid="7724301709041128296">"Video zəng"</string>
+    <string name="call_log_action_voicemail" msgid="4978620572562925654">"DİNLƏYİN"</string>
+    <string name="call_log_action_send_message" msgid="2826466379787846163">"Mesaj Göndərin"</string>
+    <string name="call_log_action_details" msgid="7957138590190911171">"Detallara baxın"</string>
+    <string name="description_incoming_missed_call" msgid="2381085098795943627">"Buraxılmış zənglər: <xliff:g id="NAMEORNUMBER">^1</xliff:g>, <xliff:g id="TYPEORLOCATION">^2</xliff:g>, <xliff:g id="TIMEOFCALL">^3</xliff:g>, <xliff:g id="PHONEACCOUNT">^4</xliff:g>."</string>
+    <string name="description_incoming_answered_call" msgid="7117665748428816544">"Zəngləri cavablandırıb: <xliff:g id="NAMEORNUMBER">^1</xliff:g>, <xliff:g id="TYPEORLOCATION">^2</xliff:g>, <xliff:g id="TIMEOFCALL">^3</xliff:g>, <xliff:g id="PHONEACCOUNT">^4</xliff:g>."</string>
+    <string name="description_outgoing_call" msgid="6386364390619734734">"Zəng et: <xliff:g id="NAMEORNUMBER">^1</xliff:g>, <xliff:g id="TYPEORLOCATION">^2</xliff:g>, <xliff:g id="TIMEOFCALL">^3</xliff:g>, <xliff:g id="PHONEACCOUNT">^4</xliff:g>."</string>
+    <string name="description_phone_account" msgid="1767072759541443861">"Zəngdədir: <xliff:g id="PHONEACCOUNT">^1</xliff:g>"</string>
+    <string name="description_call_log_call_action" msgid="3682561657090693134">"Çağrı"</string>
+    <string name="description_call_action" msgid="4000549004089776147">"Çağrı <xliff:g id="NAMEORNUMBER">^1</xliff:g>"</string>
+    <string name="description_video_call_action" msgid="7386922428155062213">"<xliff:g id="NAMEORNUMBER">^1</xliff:g> video zəng edin."</string>
+    <string name="description_voicemail_action" msgid="8054891873788903063">"<xliff:g id="NAMEORNUMBER">^1</xliff:g> tərəfdən səsli mesajı dinləyin"</string>
+    <string name="description_create_new_contact_action" msgid="818755978791008167">"<xliff:g id="NAMEORNUMBER">^1</xliff:g> üçün kontakt yaradın"</string>
+    <string name="description_add_to_existing_contact_action" msgid="6081200053494414351">"Mövcud kontakta <xliff:g id="NAMEORNUMBER">^1</xliff:g> əlavə edin"</string>
+    <string name="description_details_action" msgid="2433827152749491785">"<xliff:g id="NAMEORNUMBER">^1</xliff:g> üçün detalları çağırın"</string>
+    <string name="description_report_action" msgid="5011961125980353172">"<xliff:g id="NAMEORNUMBER">^1</xliff:g> haqqında bildirin"</string>
+    <string name="toast_entry_removed" msgid="8010830299576311534">"Zəng tarixçəsindən silindi"</string>
+    <string name="call_log_action_report" msgid="4327809827087468864">"Şikayət edin"</string>
+    <string name="call_log_header_today" msgid="3225248682434212981">"Bu gün"</string>
+    <string name="call_log_header_yesterday" msgid="9139172458834033092">"Dünən"</string>
+    <string name="call_log_header_other" msgid="5769921959940709084">"Keçmi"</string>
+    <string name="call_detail_list_header" msgid="3752717059699600861">"Zənglər siyahısı"</string>
+    <string name="voicemail_speaker_on" msgid="209154030283487068">"Dinamiki aktiv et."</string>
+    <string name="voicemail_speaker_off" msgid="7390530056413093958">"Dinamiki deaktiv et."</string>
+    <string name="voicemail_play_faster" msgid="3444751008615323006">"Daha sürətlə oxut."</string>
+    <string name="voicemail_play_slower" msgid="4544796503902818832">"Daha yavaş oxut."</string>
+    <string name="voicemail_play_start_pause" msgid="3687447935787768983">"Oxunuşu başlat və ya durdur"</string>
+    <string name="list_delimeter" msgid="4571593167738725100">", "</string>
+    <string name="display_options_title" msgid="7812852361055667468">"Ekran seçimləri"</string>
+    <string name="sounds_and_vibration_title" msgid="1692290115642160845">"Səslər və vibrasiya"</string>
+    <string name="accessibility_settings_title" msgid="6068141142874046249">"Giriş imkanı"</string>
+    <string name="ringtone_title" msgid="760362035635084653">"Telefon zəng səsi"</string>
+    <string name="vibrate_on_ring_title" msgid="3362916460327555241">"Həmçinin zənglər üçün vibrasiya olsun"</string>
+    <string name="dtmf_tone_enable_title" msgid="6571449695997521615">"Yığım tonları"</string>
+    <string name="dtmf_tone_length_title" msgid="8581125689808919460">"Yığım paneli ton uzunluğu"</string>
+  <string-array name="dtmf_tone_length_entries">
+    <item msgid="1036113889050195575">"Normal"</item>
+    <item msgid="6177579030803486015">"Uzun"</item>
+  </string-array>
+    <string name="respond_via_sms_setting_title" msgid="1318281521087951580">"Qısa cavablar"</string>
+    <string name="call_settings_label" msgid="313434211353070209">"Zənglər"</string>
+    <string name="phone_account_settings_label" msgid="5864322009841175294">"Hesabların çağrılması"</string>
 </resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 42e3d9b..3416bc6 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Бързо набиране"</string>
     <string name="tab_recents" msgid="929949073851377206">"Скорошни"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Контакти"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Гласова поща"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Премахнато от любимите"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Отмяна"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Обаждане на <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml
index 4daa6c1..1fb13f1 100644
--- a/res/values-bn-rBD/strings.xml
+++ b/res/values-bn-rBD/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"দ্রুত ডায়াল"</string>
     <string name="tab_recents" msgid="929949073851377206">"সাম্প্রতিকগুলি"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"পরিচিতিগুলি"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"ভয়েস মেল"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"পছন্দসই থেকে সরানো হয়েছে"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"পূর্বাবস্থায় ফিরুন"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g> কে কল করুন"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 610e4f1..8d9fba4 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Marcatge ràpid"</string>
     <string name="tab_recents" msgid="929949073851377206">"Recents"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Contactes"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Bústia de veu"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Eliminat dels preferits"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Desfés"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Truca al <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index f586cd8..c061879 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -133,6 +133,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Rychlá volba"</string>
     <string name="tab_recents" msgid="929949073851377206">"Poslední"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kontakty"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Hlasová schránka"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Odebráno z oblíbených"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Vrátit zpět"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Zavolat na číslo <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 7cf5d8e..6552e1d 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Hurtigopkald"</string>
     <string name="tab_recents" msgid="929949073851377206">"Seneste"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kontaktpersoner"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Telefonsvarer"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Fjernet fra foretrukne"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Fortryd"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Ring til <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 3718744..0a80009 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Schnellauswahl"</string>
     <string name="tab_recents" msgid="929949073851377206">"Neueste"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kontakte"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Mailbox"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Aus Favoriten entfernt"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Rückgängig machen"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g> wählen"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 87e3492..fcc0f3b 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Γρήγορη κλήση"</string>
     <string name="tab_recents" msgid="929949073851377206">"Πρόσφατα"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Επαφές"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Αυτόματος τηλεφωνητής"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Καταργήθηκε από τα αγαπημένα"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Αναίρεση"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Κλήση του αριθμού <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index b802e62..7bcb658 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Speed dial"</string>
     <string name="tab_recents" msgid="929949073851377206">"Recents"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Contacts"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Voicemail"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Removed from favourites"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Undo"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Call <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index b802e62..7bcb658 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Speed dial"</string>
     <string name="tab_recents" msgid="929949073851377206">"Recents"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Contacts"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Voicemail"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Removed from favourites"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Undo"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Call <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index b802e62..7bcb658 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Speed dial"</string>
     <string name="tab_recents" msgid="929949073851377206">"Recents"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Contacts"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Voicemail"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Removed from favourites"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Undo"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Call <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 88ca1ab..74ad6b9 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Marcado rápido"</string>
     <string name="tab_recents" msgid="929949073851377206">"Recientes"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Contactos"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Buzón de voz"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Eliminado de favoritos"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Deshacer"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Llamar al <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 4af50f9..b04848a 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Marcación rápida"</string>
     <string name="tab_recents" msgid="929949073851377206">"Recientes"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Contactos"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Buzón de voz"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Eliminado de favoritos"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Deshacer"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Llamar a <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml
index da1b3d8..b2e7523 100644
--- a/res/values-et-rEE/strings.xml
+++ b/res/values-et-rEE/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Kiirvalimine"</string>
     <string name="tab_recents" msgid="929949073851377206">"Hiljutised"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kontaktid"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Kõnepost"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Eemaldatud lemmikute hulgast"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Võta tagasi"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Helista <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-eu-rES/strings.xml b/res/values-eu-rES/strings.xml
index 47e1472..b5e57a7 100644
--- a/res/values-eu-rES/strings.xml
+++ b/res/values-eu-rES/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Markatze bizkorra"</string>
     <string name="tab_recents" msgid="929949073851377206">"Azkenak"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kontaktuak"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Erantzungailua"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Gogokoetatik kendu da"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Desegin"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Deitu <xliff:g id="NUMBER">%s</xliff:g> zenbakira"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index a60302a..6ec5a7f 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"شماره‌گیری سریع"</string>
     <string name="tab_recents" msgid="929949073851377206">"موارد اخیر"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"مخاطبین"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"پست صوتی"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"از موارد دلخواه حذف شد"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"لغو"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"تماس با <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index af90c99..7260441 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Pikavalinta"</string>
     <string name="tab_recents" msgid="929949073851377206">"Viimeisimmät"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Yhteystiedot"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Puhelinvastaaja"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Poistettu suosikeista"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Kumoa"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Soita <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index d149440..5b2935d 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Composition abrégée"</string>
     <string name="tab_recents" msgid="929949073851377206">"Récents"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Contacts"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Messagerie vocale"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Supprimé des favoris"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Annuler"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Appeler le <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 611c74c..abac9f9 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Numérotation abrégée"</string>
     <string name="tab_recents" msgid="929949073851377206">"Récents"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Contacts"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Messagerie vocale"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Supprimé des favoris."</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Annuler"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Appeler le <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-gl-rES/strings.xml b/res/values-gl-rES/strings.xml
index 529ee5a..8658b7f 100644
--- a/res/values-gl-rES/strings.xml
+++ b/res/values-gl-rES/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Marcación rápida"</string>
     <string name="tab_recents" msgid="929949073851377206">"Recentes"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Contactos"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Correo de voz"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Eliminado dos favoritos"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Desfacer"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Chamar a <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-gu-rIN/strings.xml b/res/values-gu-rIN/strings.xml
index 1097faf..dbabef6 100644
--- a/res/values-gu-rIN/strings.xml
+++ b/res/values-gu-rIN/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"સ્પીડ ડાયલ"</string>
     <string name="tab_recents" msgid="929949073851377206">"તાજેતરના"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"સંપર્કો"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"વૉઇસમેઇલ"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"મનપસંદમાંથી દૂર કર્યું"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"પૂર્વવત્ કરો"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g> ને કૉલ કરો"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 30be2be..fcb199f 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"स्पीड डायल"</string>
     <string name="tab_recents" msgid="929949073851377206">"हाल ही के"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"संपर्क"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"वॉइसमेल"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"पसंदीदा से निकाल दिया गया"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"वापस लाएं"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g> पर कॉल करें"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 29b0ca1..46eebf1 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -132,6 +132,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Brzo biranje"</string>
     <string name="tab_recents" msgid="929949073851377206">"Najnoviji"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kontakti"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Govorna pošta"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Uklonjeno iz favorita"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Poništi"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Nazovi <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 03653bb..e175faa 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Gyorshívó"</string>
     <string name="tab_recents" msgid="929949073851377206">"Legutóbbiak"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Címtár"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Hangposta"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Eltávolítva a kedvencek közül"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Visszavonás"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Hívás: <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml
index 632adc4..ff8738e 100644
--- a/res/values-hy-rAM/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Արագ համարարկում"</string>
     <string name="tab_recents" msgid="929949073851377206">"Վերջինները"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Կոնտակտներ"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Ձայնային փոստ"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Հեռացված է ընտրյալներից"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Հետարկել"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Զանգել <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 2d64b62..2f4907e 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Panggilan cepat"</string>
     <string name="tab_recents" msgid="929949073851377206">"Terbaru"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kontak"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Pesan suara"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Dihapus dari favorit"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Batalkan"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Telepon <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-is-rIS/strings.xml b/res/values-is-rIS/strings.xml
index 28816b6..020ef3e 100644
--- a/res/values-is-rIS/strings.xml
+++ b/res/values-is-rIS/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Hraðval"</string>
     <string name="tab_recents" msgid="929949073851377206">"Nýlegt"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Tengiliðir"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Talhólf"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Fjarlægður úr uppáhaldi"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Afturkalla"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Hringja í <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 64ec2b1..7fefd60 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Composizione rapida"</string>
     <string name="tab_recents" msgid="929949073851377206">"Recenti"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Contatti"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Segreteria"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Rimosso dai preferiti"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Annulla"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Chiama <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 2d53b9f..4ae0710 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -133,6 +133,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"חיוג מהיר"</string>
     <string name="tab_recents" msgid="929949073851377206">"אחרונים"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"אנשי קשר"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"דואר קולי"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"הוסר מהמועדפים"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"בטל"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"התקשר אל <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 55d31e9..25cb120 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"クイックアクセス"</string>
     <string name="tab_recents" msgid="929949073851377206">"最近"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"連絡先"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"ボイスメール"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"お気に入りから削除されました"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"元に戻す"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g>に発信"</string>
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml
index ae9d44c..e1098bf 100644
--- a/res/values-ka-rGE/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"სწრაფი დარეკვა"</string>
     <string name="tab_recents" msgid="929949073851377206">"ბოლო"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"კონტაქტები"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"ხმოვანი ფოსტა"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"წაიშალა რჩეულებიდან"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"დაბრუნება"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"დარეკვა <xliff:g id="NUMBER">%s</xliff:g>-ზე"</string>
diff --git a/res/values-kk-rKZ/strings.xml b/res/values-kk-rKZ/strings.xml
index 83b0120..de4a879 100644
--- a/res/values-kk-rKZ/strings.xml
+++ b/res/values-kk-rKZ/strings.xml
@@ -47,7 +47,7 @@
     <string name="call_log_incoming_header" msgid="2787722299753674684">"Келген қоңыраулар ғана"</string>
     <string name="call_log_outgoing_header" msgid="761009180766735769">"Шығыс қоңыраулары ғана"</string>
     <string name="call_log_missed_header" msgid="8017148056610855956">"Қабылданбаған қоңыраулар ғана"</string>
-    <string name="voicemail_status_voicemail_not_available" msgid="5222480147701456390">"Дауыс-хабар жаңартулары қол жетімді емес"</string>
+    <string name="voicemail_status_voicemail_not_available" msgid="5222480147701456390">"Дауыстық пошта жаңартулары қол жетімді емес"</string>
     <string name="voicemail_status_messages_waiting" msgid="6329544650250068650">"Жаңа дауыстық хабар күтуде. Дәл қазір жүктеу мүмкін емес."</string>
     <string name="voicemail_status_configure_voicemail" msgid="8300808991932816153">"Дауыс-хабарды реттеу"</string>
     <string name="voicemail_status_audio_not_available" msgid="2449801102560158082">"Аудио қол жетімді емес"</string>
@@ -90,7 +90,7 @@
     <string name="type_incoming_video" msgid="82323391702796181">"Кіріс бейне қоңырау"</string>
     <string name="type_outgoing_video" msgid="2858140021680755266">"Шығыс бейне қоңырау"</string>
     <string name="type_missed_video" msgid="954396897034220545">"Өткізіп алынған бейне қоңырау"</string>
-    <string name="type_voicemail" msgid="5153139450668549908">"Дауыс-хабар"</string>
+    <string name="type_voicemail" msgid="5153139450668549908">"Дауыстық пошта"</string>
     <string name="actionIncomingCall" msgid="6028930669817038600">"Келген қоңыраулар"</string>
     <string name="description_call_log_play_button" msgid="651182125650429846">"Дауыс-хабарды ойнату"</string>
     <string name="description_view_contact" msgid="5205669345700598415">"<xliff:g id="NAME">%1$s</xliff:g> контактісін көру"</string>
@@ -104,7 +104,7 @@
     <string name="description_start_voice_search" msgid="520539488194946012">"Дауыс іздеуді бастау"</string>
     <string name="menu_callNumber" msgid="997146291983360266">"<xliff:g id="NUMBER">%s</xliff:g> нөміріне қоңырау шалу"</string>
     <string name="unknown" msgid="740067747858270469">"Белгісіз"</string>
-    <string name="voicemail" msgid="3851469869202611441">"Дауыс-хабар"</string>
+    <string name="voicemail" msgid="3851469869202611441">"Дауыстық пошта"</string>
     <string name="private_num" msgid="6374339738119166953">"Жеке нөмір"</string>
     <string name="payphone" msgid="7726415831153618726">"Автомат-телефон"</string>
     <string name="callDetailsDurationFormat" msgid="6061406028764382234">"<xliff:g id="MINUTES">%s</xliff:g> мин <xliff:g id="SECONDS">%s</xliff:g> сек"</string>
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Жылдам теру"</string>
     <string name="tab_recents" msgid="929949073851377206">"Жақындағылар"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Контактілер"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Дауыстық хабар"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Сүйіктілерден алынған"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Кері орындау"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g> нөміріне қоңырау шалу"</string>
diff --git a/res/values-km-rKH/strings.xml b/res/values-km-rKH/strings.xml
index 36ce36a..168fbe3 100644
--- a/res/values-km-rKH/strings.xml
+++ b/res/values-km-rKH/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"ហៅទូរស័ព្ទល្បឿនលឿន"</string>
     <string name="tab_recents" msgid="929949073851377206">"ថ្មីៗ"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"ទំនាក់ទំនង"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"សារជាសំឡេង"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"បាន​លុប​ចេញពី​ទំនាក់ទំនង​ដែល​និយម​ប្រើ"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"មិនធ្វើវិញ"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"ហៅ <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-kn-rIN/strings.xml b/res/values-kn-rIN/strings.xml
index ace7517..40e6127 100644
--- a/res/values-kn-rIN/strings.xml
+++ b/res/values-kn-rIN/strings.xml
@@ -132,6 +132,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"ಸ್ಪೀಡ್ ಡಯಲ್"</string>
     <string name="tab_recents" msgid="929949073851377206">"ಇತ್ತೀಚಿನವುಗಳು"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"ಸಂಪರ್ಕಗಳು"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"ಧ್ವನಿಮೇಲ್"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"ಮೆಚ್ಚಿನವುಗಳಿಂದ ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"ರದ್ದುಮಾಡು"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g> ಕರೆ ಮಾಡಿ"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 1fd8cde..33c40e2 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"단축번호"</string>
     <string name="tab_recents" msgid="929949073851377206">"최근"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"주소록"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"음성사서함"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"즐겨찾기에서 삭제됨"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"실행취소"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g>에 전화"</string>
diff --git a/res/values-ky-rKG/strings.xml b/res/values-ky-rKG/strings.xml
index 7349947..0983c97 100644
--- a/res/values-ky-rKG/strings.xml
+++ b/res/values-ky-rKG/strings.xml
@@ -158,6 +158,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Тез терүү"</string>
     <string name="tab_recents" msgid="929949073851377206">"Акыркылар"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Байланыштар"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Үн почтасы"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Тандамалдардан өчүрүлдү"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Кайтаруу"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Чалуу <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml
index 1303d22..2e29d91 100644
--- a/res/values-lo-rLA/strings.xml
+++ b/res/values-lo-rLA/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"ການ​ໂທ​ດ່ວນ"</string>
     <string name="tab_recents" msgid="929949073851377206">"ຫາ​ກໍ​ໃຊ້"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"ລາຍ​ຊື່​ຜູ່​ຕິດ​ຕໍ່"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"ຂໍ້ຄວາມສຽງ"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"ລຶບອອກຈາກລາຍການທີ່ມັກແລ້ວ"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"ຍົກເລີກ"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"ໂທ​ຫາ <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index d803ced..147c974 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -133,6 +133,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Spartusis rinkimas"</string>
     <string name="tab_recents" msgid="929949073851377206">"Naujausi"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kontaktai"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Balso paštas"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Pašalintas iš adresyno"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Anuliuoti"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Skambinti numeriu <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 6541493..b39562d 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -132,6 +132,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Ātrie zvani"</string>
     <string name="tab_recents" msgid="929949073851377206">"Pēdējie"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kontaktpersonas"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Balss pasts"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Noņemts no izlases"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Atsaukt"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Zvaniet: <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-mk-rMK/strings.xml b/res/values-mk-rMK/strings.xml
index c5668b6..d79e7b9 100644
--- a/res/values-mk-rMK/strings.xml
+++ b/res/values-mk-rMK/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Брзо бирање"</string>
     <string name="tab_recents" msgid="929949073851377206">"Неодамнешни"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Контакти"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Говорна пошта"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Отстранет од омилени"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Врати"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Повикај <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-ml-rIN/strings.xml b/res/values-ml-rIN/strings.xml
index 95aac8a..caac273 100644
--- a/res/values-ml-rIN/strings.xml
+++ b/res/values-ml-rIN/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"സ്‌പീഡ് ഡയൽ"</string>
     <string name="tab_recents" msgid="929949073851377206">"പുതിയവ"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"കോണ്‍ടാക്റ്റുകള്‍"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"വോയ്‌സ്‌മെയിൽ"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"പ്രിയപ്പെട്ടവയിൽ നിന്നും നീക്കംചെയ്‌തു"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"പഴയപടിയാക്കുക"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g> എന്നതിൽ വിളിക്കുക"</string>
diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn-rMN/strings.xml
index c005bc9..92f29f8 100644
--- a/res/values-mn-rMN/strings.xml
+++ b/res/values-mn-rMN/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Түргэн залгалт"</string>
     <string name="tab_recents" msgid="929949073851377206">"Саяхных"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Харилцагчид"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Дуут шуудан"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Дуртай жагсаалтаас хасав"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Буцаах"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g> руу залгах"</string>
diff --git a/res/values-mr-rIN/strings.xml b/res/values-mr-rIN/strings.xml
index 4594d81..998fba6 100644
--- a/res/values-mr-rIN/strings.xml
+++ b/res/values-mr-rIN/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"स्पीड डायल"</string>
     <string name="tab_recents" msgid="929949073851377206">"अलीकडील"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"संपर्क"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"व्हॉइसमेल"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"आवडी मधून काढले"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"पूर्ववत करा"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g> ला कॉल  करा"</string>
diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml
index 0ed605a..18f9545 100644
--- a/res/values-ms-rMY/strings.xml
+++ b/res/values-ms-rMY/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Dail laju"</string>
     <string name="tab_recents" msgid="929949073851377206">"Terkini"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kenalan"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Mel suara"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Dialih keluar daripada kegemaran"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Buat asal"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Panggil <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-my-rMM/strings.xml b/res/values-my-rMM/strings.xml
index 441aa42..52dc93b 100644
--- a/res/values-my-rMM/strings.xml
+++ b/res/values-my-rMM/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"အမြန် နံပါတ်လှည့်မှု"</string>
     <string name="tab_recents" msgid="929949073851377206">"မကြာမီက"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"အဆက်အသွယ်များ"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"အသံမေးလ်"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"အနှစ်သက်ဆုံးများထဲမှာ ထုတ်လိုက်ပါပြီ"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"နောက်ပြန်လုပ်ပါ"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g> ကိုခေါ်ပါ"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 09d7d3c..220324c 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Hurtigvalg"</string>
     <string name="tab_recents" msgid="929949073851377206">"Sist brukte"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kontakter"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Talepostkasse"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Fjernet fra favoritter"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Angre"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Ring <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-ne-rNP/strings.xml b/res/values-ne-rNP/strings.xml
index c042fa7..46786f9 100644
--- a/res/values-ne-rNP/strings.xml
+++ b/res/values-ne-rNP/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"द्रूत डायल"</string>
     <string name="tab_recents" msgid="929949073851377206">"हालैका"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"सम्पर्कहरू"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"भ्वाइसमेल"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"मनपर्नेहरूबाट हटाइयो"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"अनडु गर्नुहोस्"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g> कल गर्नुहोस्"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 1e338ff..7991394 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Snelkeuze"</string>
     <string name="tab_recents" msgid="929949073851377206">"Recent"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Contacten"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Voicemail"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Verwijderd uit favorieten"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Ongedaan maken"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Bel <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-pa-rIN/strings.xml b/res/values-pa-rIN/strings.xml
index 76b8f40..d73dce0 100644
--- a/res/values-pa-rIN/strings.xml
+++ b/res/values-pa-rIN/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"ਸਪੀਡ ਡਾਇਲ"</string>
     <string name="tab_recents" msgid="929949073851377206">"ਹਾਲੀਆ"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"ਸੰਪਰਕ"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"ਵੌਇਸਮੇਲ"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"ਮਨਪਸੰਦ ਵਿੱਚੋਂ ਹਟਾਇਆ ਗਿਆ"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"ਪਹਿਲਾਂ ਵਰਗਾ ਕਰੋ"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g> ਨੂੰ ਕਾਲ ਕਰੋ"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 5ca819a..eda54a8 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -133,6 +133,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Szybkie wybieranie"</string>
     <string name="tab_recents" msgid="929949073851377206">"Ostatnie"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kontakty"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Poczta głosowa"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Usunięto z ulubionych"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Cofnij"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Zadzwoń: <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 0a12b2c..fd1896f 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Marcação rápida"</string>
     <string name="tab_recents" msgid="929949073851377206">"Recentes"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Contactos"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Correio de voz"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Removido dos favoritos"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Anular"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Telefonar para <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index ba4a950..57bc9d1 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Discagem rápida"</string>
     <string name="tab_recents" msgid="929949073851377206">"Recentes"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Contatos"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Correio de voz"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Removido dos favoritos"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Desfazer"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Ligar para <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 04ca243..55e9f1d 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -132,6 +132,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Apelare rapidă"</string>
     <string name="tab_recents" msgid="929949073851377206">"Recente"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Agendă"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Mesagerie vocală"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"S-a eliminat din preferate"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Anulați"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Apelați <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index b0d950c..3100c6c 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -133,6 +133,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Быстрый набор"</string>
     <string name="tab_recents" msgid="929949073851377206">"Недавние"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Контакты"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Голосовая почта"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Контакт удален из избранных"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Отмена"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Позвонить: <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-si-rLK/strings.xml b/res/values-si-rLK/strings.xml
index 78c0179..c3f2c5a 100644
--- a/res/values-si-rLK/strings.xml
+++ b/res/values-si-rLK/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"වේග ඩයල් කිරීම"</string>
     <string name="tab_recents" msgid="929949073851377206">"මෑත"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"සම්බන්ධතා"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"හඬ තැපෑල"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"ප්‍රියතමයන්ගෙන් ඉවත් කරන්න"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"අස් කරන්න"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g> අමතන්න"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 0929e12..85b0aa2 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -133,6 +133,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Rýchla voľba"</string>
     <string name="tab_recents" msgid="929949073851377206">"Nedávne"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kontakty"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Hlasová schránka"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Odstránené z obľúbených"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Späť"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Volať na číslo <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 48d0349..2beeb77 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -133,6 +133,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Hitro izbiranje"</string>
     <string name="tab_recents" msgid="929949073851377206">"Nedavni"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Stiki"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Odzivnik"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Odstranjeno iz priljubljenih"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Razveljavi"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Pokliči <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-sq-rAL/strings.xml b/res/values-sq-rAL/strings.xml
index a3d247d..8de2b4b 100644
--- a/res/values-sq-rAL/strings.xml
+++ b/res/values-sq-rAL/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Telefonatë e shpejtë"</string>
     <string name="tab_recents" msgid="929949073851377206">"Të fundit"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kontaktet"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Posta zanore"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"U hoq nga të preferuarat"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Zhbëj"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Telefono <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 6a9b9fb..d4a73f8 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -132,6 +132,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Брзо бирање"</string>
     <string name="tab_recents" msgid="929949073851377206">"Недавни контакти"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Контакти"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Говорна пошта"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Уклоњено је из омиљених"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Опозови"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Позови <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 1eaeeaf..61d01c5 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Kortnummer"</string>
     <string name="tab_recents" msgid="929949073851377206">"Senaste"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kontakter"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Röstbrevlåda"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Borttagen från favoriter"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Ångra"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Ring <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index ea99b51..bebcd10 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Unaowasiliana nao zaidi"</string>
     <string name="tab_recents" msgid="929949073851377206">"Zilizotumika majuzi"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Anwani zote"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Ujumbe wa sauti"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Imeondolowa kwenye vipendwa"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Tendua"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Piga simu <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-ta-rIN/strings.xml b/res/values-ta-rIN/strings.xml
index 8bd2e85..f0fe1e7 100644
--- a/res/values-ta-rIN/strings.xml
+++ b/res/values-ta-rIN/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"விரைவு டயல்"</string>
     <string name="tab_recents" msgid="929949073851377206">"சமீபத்தியவை"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"தொடர்புகள்"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"குரலஞ்சல்"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"பிடித்தவற்றிலிருந்து அகற்றப்பட்டது"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"செயல்தவிர்"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g> ஐ அழை"</string>
diff --git a/res/values-te-rIN/strings.xml b/res/values-te-rIN/strings.xml
index 76b79c2..c6ba2c3 100644
--- a/res/values-te-rIN/strings.xml
+++ b/res/values-te-rIN/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"స్పీడ్ డయల్"</string>
     <string name="tab_recents" msgid="929949073851377206">"ఇటీవలివి"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"పరిచయాలు"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"వాయిస్ మెయిల్"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"ఇష్టమైనవాటి నుండి తీసివేయబడింది"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"చర్య రద్దు చేయి"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g>కు కాల్ చేయండి"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 2bac245..e946ae5 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"การโทรด่วน"</string>
     <string name="tab_recents" msgid="929949073851377206">"ล่าสุด"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"รายชื่อติดต่อ"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"ข้อความเสียง"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"ลบจากรายการโปรด"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"เลิกทำ"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"โทร <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 9493e14..d0ffdc3 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Speed dial"</string>
     <string name="tab_recents" msgid="929949073851377206">"Mga Kamakailan"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Mga Contact"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Voicemail"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Inalis sa mga paborito"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"I-undo"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Tumawag sa <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 8fc84d7..c9132a3 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Hızlı arama"</string>
     <string name="tab_recents" msgid="929949073851377206">"Son Kişiler"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kişiler"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Sesli mesaj"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Favorilerden kaldırıldı"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Geri al"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Telefon et: <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 041f453..5df028b 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -133,6 +133,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Швидкий набір"</string>
     <string name="tab_recents" msgid="929949073851377206">"Останні"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Контакти"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Голосова пошта"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Вилучено з вибраного"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Відмінити"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Набрати <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-ur-rPK/strings.xml b/res/values-ur-rPK/strings.xml
index fded54a..80469a6 100644
--- a/res/values-ur-rPK/strings.xml
+++ b/res/values-ur-rPK/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"اسپیڈ ڈائل"</string>
     <string name="tab_recents" msgid="929949073851377206">"حالیہ"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"رابطے"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"صوتی میل"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"پسندیدہ سے ہٹا دیا گیا"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"کالعدم کریں"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"<xliff:g id="NUMBER">%s</xliff:g> کو کال کریں"</string>
diff --git a/res/values-uz-rUZ/strings.xml b/res/values-uz-rUZ/strings.xml
index 6735fa3..6d67c6d 100644
--- a/res/values-uz-rUZ/strings.xml
+++ b/res/values-uz-rUZ/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Tezkor terish"</string>
     <string name="tab_recents" msgid="929949073851377206">"So‘nggi"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Kontaktlar"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Ovozli pochta"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Tanlanganlardan o‘chirilgan"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Bekor qilish"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Qo‘ng‘iroq: <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index eb4ea3f..ce5deeb 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Quay số nhanh"</string>
     <string name="tab_recents" msgid="929949073851377206">"Gần đây"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Địa chỉ liên hệ"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Thư thoại"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Đã xóa khỏi mục yêu thích"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Hoàn tác"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Gọi <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 290263d..86abaa6 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"快速拨号"</string>
     <string name="tab_recents" msgid="929949073851377206">"最近"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"联系人"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"语音邮件"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"已从收藏中移除"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"撤消"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"拨打<xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index b6917fd..55d5cae 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"快速撥號"</string>
     <string name="tab_recents" msgid="929949073851377206">"最近存取的聯絡人"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"聯絡人"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"留言信箱"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"已從「我的最愛」中移除"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"復原"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"撥打 <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index ee66149..16e06ba 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"快速撥號"</string>
     <string name="tab_recents" msgid="929949073851377206">"近期通話"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"聯絡人"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"語音信箱"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"已從最愛的聯絡人移除"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"復原"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"撥打 <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 1a5b0c6..798044c 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -131,6 +131,7 @@
     <string name="tab_speed_dial" msgid="7552166276545648893">"Ukudayela okusheshayo"</string>
     <string name="tab_recents" msgid="929949073851377206">"Okwakamuva"</string>
     <string name="tab_all_contacts" msgid="1410922767166533690">"Oxhumana nabo"</string>
+    <string name="tab_voicemail" msgid="155024725947496746">"Ivoyisimeyili"</string>
     <string name="favorite_hidden" msgid="5011234945140912047">"Kukhishiwe kusuka kuzintandokazi"</string>
     <string name="favorite_hidden_undo" msgid="2508998611039406474">"Hlehlisa"</string>
     <string name="search_shortcut_call_number" msgid="7277194656832895870">"Shayela ku-<xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/src/com/android/dialer/CallDetailActivity.java b/src/com/android/dialer/CallDetailActivity.java
index 1c684a5..ce29049 100644
--- a/src/com/android/dialer/CallDetailActivity.java
+++ b/src/com/android/dialer/CallDetailActivity.java
@@ -61,7 +61,8 @@
 import com.android.dialer.util.IntentUtil;
 import com.android.dialer.util.DialerUtils;
 import com.android.dialer.util.TelecomUtil;
-import com.android.dialer.voicemail.VoicemailPlaybackFragment;
+import com.android.dialer.voicemail.VoicemailPlaybackLayout;
+import com.android.dialer.voicemail.VoicemailPlaybackPresenter;
 
 import java.util.List;
 
@@ -217,7 +218,7 @@
     /** Helper to load contact photos. */
     private ContactPhotoManager mContactPhotoManager;
 
-    private LinearLayout mVoicemailHeader;
+    private VoicemailPlaybackPresenter mVoicemailPlaybackPresenter;
 
     private Uri mVoicemailUri;
     private BidiFormatter mBidiFormatter = BidiFormatter.getInstance();
@@ -255,6 +256,7 @@
         getActionBar().setDisplayHomeAsUpEnabled(true);
 
         optionallyHandleVoicemail();
+
         if (getIntent().getBooleanExtra(EXTRA_FROM_NOTIFICATION, false)) {
             closeSystemDialogs();
         }
@@ -267,6 +269,38 @@
         CallLogAsyncTaskUtil.getCallDetails(this, getCallLogEntryUris(), mCallLogAsyncTaskListener);
     }
 
+    @Override
+    public void onPause() {
+        if (mVoicemailPlaybackPresenter != null) {
+            mVoicemailPlaybackPresenter.onPause(isFinishing());
+        }
+        super.onPause();
+    }
+
+    @Override
+    public void onDestroy() {
+        if (mVoicemailPlaybackPresenter != null) {
+            mVoicemailPlaybackPresenter.onDestroy(isFinishing());
+        }
+        super.onDestroy();
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        if (mVoicemailPlaybackPresenter != null) {
+            mVoicemailPlaybackPresenter.onSaveInstanceState(outState);
+        }
+    }
+
+    @Override
+    public void onRestoreInstanceState(Bundle savedInstanceState) {
+        if (mVoicemailPlaybackPresenter != null) {
+            mVoicemailPlaybackPresenter.onRestoreInstanceState(savedInstanceState);
+        }
+        super.onRestoreInstanceState(savedInstanceState);
+    }
+
     /**
      * Handle voicemail playback or hide voicemail ui.
      * <p>
@@ -274,37 +308,15 @@
      * playback.  If it doesn't, then don't inflate the voicemail ui.
      */
     private void optionallyHandleVoicemail() {
-
         if (hasVoicemail()) {
-            LayoutInflater inflater =
-                    (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-            mVoicemailHeader =
-                    (LinearLayout) inflater.inflate(R.layout.call_details_voicemail_header, null);
-            View voicemailContainer = mVoicemailHeader.findViewById(R.id.voicemail_container);
-            ListView historyList = (ListView) findViewById(R.id.history);
-            historyList.addHeaderView(mVoicemailHeader);
-            // Has voicemail: add the voicemail fragment.  Add suitable arguments to set the uri
-            // to play and optionally start the playback.
-            // Do a query to fetch the voicemail status messages.
-            VoicemailPlaybackFragment playbackFragment;
+            VoicemailPlaybackLayout voicemailPlaybackLayout =
+                (VoicemailPlaybackLayout) findViewById(R.id.voicemail_playback_layout);
 
-            playbackFragment = (VoicemailPlaybackFragment) getFragmentManager().findFragmentByTag(
-                    VOICEMAIL_FRAGMENT_TAG);
+            mVoicemailPlaybackPresenter = new VoicemailPlaybackPresenter(this);
+            mVoicemailPlaybackPresenter.setPlaybackView(
+                    voicemailPlaybackLayout, mVoicemailUri, false /* startPlayingImmediately */);
 
-            if (playbackFragment == null) {
-                playbackFragment = new VoicemailPlaybackFragment();
-                Bundle fragmentArguments = new Bundle();
-                fragmentArguments.putParcelable(EXTRA_VOICEMAIL_URI, mVoicemailUri);
-                if (getIntent().getBooleanExtra(EXTRA_VOICEMAIL_START_PLAYBACK, false)) {
-                    fragmentArguments.putBoolean(EXTRA_VOICEMAIL_START_PLAYBACK, true);
-                }
-                playbackFragment.setArguments(fragmentArguments);
-                getFragmentManager().beginTransaction()
-                        .add(R.id.voicemail_container, playbackFragment, VOICEMAIL_FRAGMENT_TAG)
-                                .commitAllowingStateLoss();
-            }
-
-            voicemailContainer.setVisibility(View.VISIBLE);
+            voicemailPlaybackLayout.setVisibility(View.VISIBLE);
             CallLogAsyncTaskUtil.markVoicemailAsRead(this, mVoicemailUri);
         }
     }
diff --git a/src/com/android/dialer/DialerApplication.java b/src/com/android/dialer/DialerApplication.java
index 7bc3bb4..b177d83 100644
--- a/src/com/android/dialer/DialerApplication.java
+++ b/src/com/android/dialer/DialerApplication.java
@@ -19,14 +19,12 @@
 import android.app.Application;
 import android.os.Trace;
 
-import com.android.contacts.common.ContactPhotoManager;
 import com.android.contacts.common.extensions.ExtensionsFactory;
 import com.android.contacts.commonbind.analytics.AnalyticsUtil;
 
 public class DialerApplication extends Application {
 
     private static final String TAG = "DialerApplication";
-    private ContactPhotoManager mContactPhotoManager;
 
     @Override
     public void onCreate() {
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index 56d5ad1..aefe01f 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -29,12 +29,10 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Trace;
-import android.provider.ContactsContract.Intents;
 import android.speech.RecognizerIntent;
 import android.support.v4.view.ViewPager;
 import android.telecom.PhoneAccount;
 import android.telecom.TelecomManager;
-import android.telephony.TelephonyManager;
 import android.text.Editable;
 import android.text.TextUtils;
 import android.text.TextWatcher;
@@ -63,6 +61,7 @@
 import com.android.contacts.common.interactions.ImportExportDialogFragment;
 import com.android.contacts.common.interactions.TouchPointManager;
 import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
+import com.android.contacts.common.util.PermissionsUtil;
 import com.android.contacts.common.widget.FloatingActionButtonController;
 import com.android.contacts.commonbind.analytics.AnalyticsUtil;
 import com.android.dialer.calllog.CallLogActivity;
@@ -111,7 +110,7 @@
         ActionBarController.ActivityUi {
     private static final String TAG = "DialtactsActivity";
 
-    public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    public static final boolean DEBUG = false;
 
     public static final String SHARED_PREFS_NAME = "com.android.dialer_preferences";
 
@@ -167,9 +166,7 @@
     AnimationListenerAdapter mSlideInListener = new AnimationListenerAdapter() {
         @Override
         public void onAnimationEnd(Animation animation) {
-            if (!isInSearchUi()) {
-                enterSearchUi(true /* isSmartDial */, mSearchQuery, false);
-            }
+            maybeEnterSearchUi();
         }
     };
 
@@ -248,11 +245,19 @@
 
         @Override
         public void show() {
+            final boolean hasContactsPermission =
+                    PermissionsUtil.hasContactsPermissions(DialtactsActivity.this);
             final Menu menu = getMenu();
             final MenuItem clearFrequents = menu.findItem(R.id.menu_clear_frequents);
             clearFrequents.setVisible(mListsFragment != null &&
                     mListsFragment.getSpeedDialFragment() != null &&
-                    mListsFragment.getSpeedDialFragment().hasFrequents());
+                    mListsFragment.getSpeedDialFragment().hasFrequents() && hasContactsPermission);
+
+            menu.findItem(R.id.menu_import_export).setVisible(hasContactsPermission);
+            menu.findItem(R.id.menu_add_contact).setVisible(hasContactsPermission);
+
+            menu.findItem(R.id.menu_history).setVisible(
+                    PermissionsUtil.hasPhonePermissions(DialtactsActivity.this));
             super.show();
         }
     }
@@ -359,6 +364,7 @@
     protected void onCreate(Bundle savedInstanceState) {
         Trace.beginSection(TAG + " onCreate");
         super.onCreate(savedInstanceState);
+
         mFirstLaunch = true;
 
         final Resources resources = getResources();
@@ -585,7 +591,7 @@
     public void onClick(View view) {
         switch (view.getId()) {
             case R.id.floating_action_button:
-                if (mListsFragment.getTabPosition() == ListsFragment.TAB_INDEX_ALL_CONTACTS) {
+                if (mListsFragment.getCurrentTabIndex() == ListsFragment.TAB_INDEX_ALL_CONTACTS) {
                     DialerUtils.startActivityWithErrorToast(
                             this,
                             IntentUtil.getNewContactIntent(),
@@ -695,6 +701,7 @@
             mFloatingActionButtonController.scaleOut();
         } else {
             mFloatingActionButtonController.setVisible(false);
+            maybeEnterSearchUi();
         }
         mActionBarController.onDialpadUp();
 
@@ -818,7 +825,6 @@
     protected OptionsPopupMenu buildOptionsMenu(View invoker) {
         final OptionsPopupMenu popupMenu = new OptionsPopupMenu(this, invoker);
         popupMenu.inflate(R.menu.dialtacts_options);
-        final Menu menu = popupMenu.getMenu();
         popupMenu.setOnMenuItemClickListener(this);
         return popupMenu;
     }
@@ -829,7 +835,9 @@
             mSearchView.setText(mPendingSearchViewQuery);
             mPendingSearchViewQuery = null;
         }
-        mActionBarController.restoreActionBarOffset();
+        if (mActionBarController != null) {
+            mActionBarController.restoreActionBarOffset();
+        }
         return false;
     }
 
@@ -1029,6 +1037,12 @@
         }
     }
 
+    private void maybeEnterSearchUi() {
+        if (!isInSearchUi()) {
+            enterSearchUi(true /* isSmartDial */, mSearchQuery, false);
+        }
+    }
+
     /**
      * @return True if the search UI was exited, false otherwise
      */
@@ -1162,25 +1176,25 @@
 
     @Override
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
-        position = mListsFragment.getRtlPosition(position);
-        // Only scroll the button when the first tab is selected. The button should scroll from
-        // the middle to right position only on the transition from the first tab to the second
-        // tab.
-        // If the app is in RTL mode, we need to check against the second tab, rather than the
-        // first. This is because if we are scrolling between the first and second tabs, the
-        // viewpager will report that the starting tab position is 1 rather than 0, due to the
-        // reversal of the order of the tabs.
-        final boolean isLayoutRtl = DialerUtils.isRtl();
-        final boolean shouldScrollButton = position == (isLayoutRtl
-                ? ListsFragment.TAB_INDEX_RECENTS : ListsFragment.TAB_INDEX_SPEED_DIAL);
-        if (shouldScrollButton && !mIsLandscape) {
-            mFloatingActionButtonController.onPageScrolled(
-                    isLayoutRtl ? 1 - positionOffset : positionOffset);
-        } else if (position != ListsFragment.TAB_INDEX_SPEED_DIAL) {
+        int tabIndex = mListsFragment.getCurrentTabIndex();
+
+        // Scroll the button from center to end when moving from the Speed Dial to Recents tab.
+        // In RTL, scroll when the current tab is Recents instead of Speed Dial, because the order
+        // of the tabs is reversed and the ViewPager returns the left tab position during scroll.
+        boolean isRtl = DialerUtils.isRtl();
+        if (!isRtl && tabIndex == ListsFragment.TAB_INDEX_SPEED_DIAL && !mIsLandscape) {
+            mFloatingActionButtonController.onPageScrolled(positionOffset);
+        } else if (isRtl && tabIndex == ListsFragment.TAB_INDEX_RECENTS && !mIsLandscape) {
+            mFloatingActionButtonController.onPageScrolled(1 - positionOffset);
+        } else if (tabIndex != ListsFragment.TAB_INDEX_SPEED_DIAL) {
             mFloatingActionButtonController.onPageScrolled(1);
         }
+    }
 
-        if (position == ListsFragment.TAB_INDEX_ALL_CONTACTS) {
+    @Override
+    public void onPageSelected(int position) {
+        int tabIndex = mListsFragment.getCurrentTabIndex();
+        if (tabIndex == ListsFragment.TAB_INDEX_ALL_CONTACTS) {
             mFloatingActionButtonController.changeIcon(
                     getResources().getDrawable(R.drawable.ic_person_add_24dp),
                     getResources().getString(R.string.search_shortcut_create_new_contact));
@@ -1192,10 +1206,6 @@
     }
 
     @Override
-    public void onPageSelected(int position) {
-    }
-
-    @Override
     public void onPageScrollStateChanged(int state) {
     }
 
@@ -1239,7 +1249,7 @@
      */
     private void updateFloatingActionButtonControllerAlignment(boolean animate) {
         int align = (!mIsLandscape &&
-                mListsFragment.getTabPosition() == ListsFragment.TAB_INDEX_SPEED_DIAL) ?
+                mListsFragment.getCurrentTabIndex() == ListsFragment.TAB_INDEX_SPEED_DIAL) ?
                 FloatingActionButtonController.ALIGN_MIDDLE :
                         FloatingActionButtonController.ALIGN_END;
         mFloatingActionButtonController.align(align, 0 /* offsetX */, 0 /* offsetY */, animate);
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index 523b5b9..c472ef2 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -34,6 +34,7 @@
 import android.view.ViewTreeObserver;
 import android.view.accessibility.AccessibilityEvent;
 
+import com.android.contacts.common.util.PermissionsUtil;
 import com.android.dialer.PhoneCallDetails;
 import com.android.dialer.PhoneCallDetailsHelper;
 import com.android.dialer.R;
@@ -163,10 +164,15 @@
      */
     private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() {
         @Override
-        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
-                AccessibilityEvent event) {
+        public boolean onRequestSendAccessibilityEvent(
+                ViewGroup host, View child, AccessibilityEvent event) {
             if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
-                expandViewHolderActions((CallLogListItemViewHolder) host.getTag());
+                // Only expand if actions are not already expanded, because triggering the expand
+                // function on clicks causes the action views to lose the focus indicator.
+                CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder) host.getTag();
+                if (mCurrentlyExpandedPosition != viewHolder.getAdapterPosition()) {
+                    expandViewHolderActions((CallLogListItemViewHolder) host.getTag());
+                }
             }
             return super.onRequestSendAccessibilityEvent(host, child, event);
         }
@@ -184,8 +190,9 @@
     public boolean onPreDraw() {
         // We only wanted to listen for the first draw (and this is it).
         unregisterPreDrawListener();
-
-        mContactInfoCache.start();
+        if (PermissionsUtil.hasContactsPermissions(mContext)) {
+            mContactInfoCache.start();
+        }
         return true;
     }
 
@@ -205,6 +212,9 @@
 
         mContactInfoCache = new ContactInfoCache(
                 mContactInfoHelper, mOnContactInfoChangedListener);
+        if (!PermissionsUtil.hasContactsPermissions(context)) {
+            mContactInfoCache.disableRequestProcessing();
+        }
 
         Resources resources = mContext.getResources();
         CallTypeHelper callTypeHelper = new CallTypeHelper(resources);
@@ -534,7 +544,7 @@
     @VisibleForTesting
     void disableRequestProcessingForTest() {
         // TODO: Remove this and test the cache directly.
-        mContactInfoCache.disableRequestProcessingForTest();
+        mContactInfoCache.disableRequestProcessing();
     }
 
     @VisibleForTesting
diff --git a/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java b/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java
index 20e213c..aa186eb 100644
--- a/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java
+++ b/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java
@@ -34,6 +34,8 @@
 import com.android.dialer.util.AsyncTaskExecutors;
 import com.android.dialer.util.TelecomUtil;
 
+import com.google.common.annotations.VisibleForTesting;
+
 public class CallLogAsyncTaskUtil {
     private static String TAG = CallLogAsyncTaskUtil.class.getSimpleName();
 
@@ -297,4 +299,9 @@
                     }
                 });
     }
+
+    @VisibleForTesting
+    public static void resetForTest() {
+        sAsyncTaskExecutor = null;
+    }
 }
diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java
index e8ed17e..36d9bb6 100644
--- a/src/com/android/dialer/calllog/CallLogFragment.java
+++ b/src/com/android/dialer/calllog/CallLogFragment.java
@@ -92,7 +92,6 @@
     /** Whether there is at least one voicemail source installed. */
     private boolean mVoicemailSourcesAvailable = false;
 
-    private VoicemailStatusHelper mVoicemailStatusHelper;
     private View mEmptyListView;
     private KeyguardManager mKeyguardManager;
 
@@ -188,7 +187,6 @@
                 mContactsObserver);
         resolver.registerContentObserver(Status.CONTENT_URI, true, mVoicemailStatusObserver);
         setHasOptionsMenu(true);
-        fetchCalls();
     }
 
     /** Called by the CallLogQueryHandler when the list of calls has been fetched or updated. */
@@ -203,7 +201,7 @@
         // This will update the state of the "Clear call log" menu item.
         getActivity().invalidateOptionsMenu();
 
-        boolean showListView = cursor.getCount() > 0;
+        boolean showListView = cursor != null && cursor.getCount() > 0;
         mRecyclerView.setVisibility(showListView ? View.VISIBLE : View.GONE);
         mEmptyListView.setVisibility(!showListView ? View.VISIBLE : View.GONE);
 
@@ -266,6 +264,7 @@
         mRecyclerView.setHasFixedSize(true);
         mLayoutManager = new LinearLayoutManager(getActivity());
         mRecyclerView.setLayoutManager(mLayoutManager);
+        mEmptyListView = view.findViewById(R.id.empty_list_view);
 
         String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity());
         boolean isShowingRecentsTab = mLogLimit != NO_LOG_LIMIT || mDateLimit != NO_DATE_LIMIT;
@@ -277,15 +276,13 @@
                 this);
         mRecyclerView.setAdapter(mAdapter);
 
-        mVoicemailStatusHelper = new VoicemailStatusHelperImpl();
+        fetchCalls();
         return view;
     }
 
     @Override
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
-        mEmptyListView = view.findViewById(R.id.empty_list_view);
-
         updateEmptyMessage(mCallTypeFilter);
     }
 
diff --git a/src/com/android/dialer/calllog/CallLogNotificationsService.java b/src/com/android/dialer/calllog/CallLogNotificationsService.java
index 22809db..9f48b09 100644
--- a/src/com/android/dialer/calllog/CallLogNotificationsService.java
+++ b/src/com/android/dialer/calllog/CallLogNotificationsService.java
@@ -22,6 +22,7 @@
 import android.net.Uri;
 import android.util.Log;
 
+import com.android.contacts.common.util.PermissionsUtil;
 import com.android.dialer.util.TelecomUtil;
 
 /**
@@ -78,6 +79,10 @@
             return;
         }
 
+        if (!PermissionsUtil.hasPhonePermissions(this)) {
+            return;
+        }
+
         if (ACTION_MARK_NEW_VOICEMAILS_AS_OLD.equals(intent.getAction())) {
             mVoicemailQueryHandler.markNewVoicemailsAsOld();
         } else if (ACTION_UPDATE_NOTIFICATIONS.equals(intent.getAction())) {
diff --git a/src/com/android/dialer/calllog/CallLogQueryHandler.java b/src/com/android/dialer/calllog/CallLogQueryHandler.java
index 49d6a41..a0e563a 100644
--- a/src/com/android/dialer/calllog/CallLogQueryHandler.java
+++ b/src/com/android/dialer/calllog/CallLogQueryHandler.java
@@ -35,6 +35,7 @@
 import android.util.Log;
 
 import com.android.contacts.common.database.NoNullCursorAsyncQueryHandler;
+import com.android.contacts.common.util.PermissionsUtil;
 import com.android.dialer.util.TelecomUtil;
 import com.android.dialer.voicemail.VoicemailStatusHelperImpl;
 
@@ -93,6 +94,10 @@
                 Log.w(TAG, "Exception on background worker thread", e);
             } catch (IllegalArgumentException e) {
                 Log.w(TAG, "ContactsProvider not present on device", e);
+            } catch (SecurityException e) {
+                // Shouldn't happen if we are protecting the entry points correctly,
+                // but just in case.
+                Log.w(TAG, "No permission to access ContactsProvider.", e);
             }
         }
     }
@@ -124,7 +129,11 @@
      */
     public void fetchCalls(int callType, long newerThan) {
         cancelFetch();
-        fetchCalls(QUERY_CALLLOG_TOKEN, callType, false /* newOnly */, newerThan);
+        if (PermissionsUtil.hasPhonePermissions(mContext)) {
+            fetchCalls(QUERY_CALLLOG_TOKEN, callType, false /* newOnly */, newerThan);
+        } else {
+            updateAdapterData(null);
+        }
     }
 
     public void fetchCalls(int callType) {
@@ -187,6 +196,9 @@
 
     /** Updates all new calls to mark them as old. */
     public void markNewCallsAsOld() {
+        if (!PermissionsUtil.hasPhonePermissions(mContext)) {
+            return;
+        }
         // Mark all "new" calls as not new anymore.
         StringBuilder where = new StringBuilder();
         where.append(Calls.NEW);
@@ -201,6 +213,9 @@
 
     /** Updates all missed calls to mark them as read. */
     public void markMissedCallsAsRead() {
+        if (!PermissionsUtil.hasPhonePermissions(mContext)) {
+            return;
+        }
         // Mark all "new" calls as not new anymore.
         StringBuilder where = new StringBuilder();
         where.append(Calls.IS_READ).append(" = 0");
diff --git a/src/com/android/dialer/calllog/ContactInfoHelper.java b/src/com/android/dialer/calllog/ContactInfoHelper.java
index 38c9bba..9a660e1 100644
--- a/src/com/android/dialer/calllog/ContactInfoHelper.java
+++ b/src/com/android/dialer/calllog/ContactInfoHelper.java
@@ -30,6 +30,7 @@
 import android.util.Log;
 
 import com.android.contacts.common.util.Constants;
+import com.android.contacts.common.util.PermissionsUtil;
 import com.android.contacts.common.util.PhoneNumberHelper;
 import com.android.contacts.common.util.UriUtils;
 import com.android.dialer.service.CachedNumberLookupService;
@@ -162,6 +163,9 @@
         if (uri == null) {
             return null;
         }
+        if (!PermissionsUtil.hasContactsPermissions(mContext)) {
+            return ContactInfo.EMPTY;
+        }
         final ContactInfo info;
         Cursor phonesCursor =
                 mContext.getContentResolver().query(uri, PhoneQuery._PROJECTION, null, null, null);
diff --git a/src/com/android/dialer/contactinfo/ContactInfoCache.java b/src/com/android/dialer/contactinfo/ContactInfoCache.java
index 2bb0f1e..568f488 100644
--- a/src/com/android/dialer/contactinfo/ContactInfoCache.java
+++ b/src/com/android/dialer/contactinfo/ContactInfoCache.java
@@ -51,7 +51,7 @@
         private volatile boolean mDone = false;
 
         public QueryThread() {
-            super("CallLogAdapter.QueryThread");
+            super("ContactInfoCache.QueryThread");
         }
 
         public void stopProcessing() {
@@ -316,20 +316,12 @@
                 && TextUtils.equals(callLogInfo.label, info.label);
     }
 
-    /**
-     * Can be set to true by tests to disable processing of requests.
-     */
-    @VisibleForTesting
     private volatile boolean mRequestProcessingDisabled = false;
 
     /**
      * Sets whether processing of requests for contact details should be enabled.
-     *
-     * This method should be called in tests to disable such processing of requests when not
-     * needed.
      */
-    @VisibleForTesting
-    public void disableRequestProcessingForTest() {
+    public void disableRequestProcessing() {
         mRequestProcessingDisabled = true;
     }
 
diff --git a/src/com/android/dialer/database/DialerDatabaseHelper.java b/src/com/android/dialer/database/DialerDatabaseHelper.java
index 2177878..eec24f5 100644
--- a/src/com/android/dialer/database/DialerDatabaseHelper.java
+++ b/src/com/android/dialer/database/DialerDatabaseHelper.java
@@ -36,6 +36,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.contacts.common.util.PermissionsUtil;
 import com.android.contacts.common.util.StopWatch;
 import com.android.dialer.R;
 import com.android.dialer.dialpad.SmartDialNameMatcher;
@@ -485,7 +486,9 @@
      * Starts the database upgrade process in the background.
      */
     public void startSmartDialUpdateThread() {
-        new SmartDialUpdateAsyncTask().execute();
+        if (PermissionsUtil.hasContactsPermissions(mContext)) {
+            new SmartDialUpdateAsyncTask().execute();
+        }
     }
 
     private class SmartDialUpdateAsyncTask extends AsyncTask {
diff --git a/src/com/android/dialer/dialpad/DialpadFragment.java b/src/com/android/dialer/dialpad/DialpadFragment.java
index 8d27c14..89cab41 100644
--- a/src/com/android/dialer/dialpad/DialpadFragment.java
+++ b/src/com/android/dialer/dialpad/DialpadFragment.java
@@ -70,6 +70,7 @@
 
 import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.common.GeoUtil;
+import com.android.contacts.common.util.PermissionsUtil;
 import com.android.contacts.common.util.PhoneNumberFormatter;
 import com.android.contacts.common.util.StopWatch;
 import com.android.contacts.common.widget.FloatingActionButtonController;
@@ -441,6 +442,9 @@
                     setFormattedDigits(converted, null);
                     return true;
                 } else {
+                    if (!PermissionsUtil.hasContactsPermissions(getActivity())) {
+                        return false;
+                    }
                     String type = intent.getType();
                     if (People.CONTENT_ITEM_TYPE.equals(type)
                             || Phones.CONTENT_ITEM_TYPE.equals(type)) {
@@ -1596,6 +1600,9 @@
      */
     private void queryLastOutgoingCall() {
         mLastNumberDialed = EMPTY_NUMBER;
+        if (!PermissionsUtil.hasPhonePermissions(getActivity())) {
+            return;
+        }
         CallLogAsync.GetLastOutgoingCallArgs lastCallArgs =
                 new CallLogAsync.GetLastOutgoingCallArgs(
                     getActivity(),
diff --git a/src/com/android/dialer/dialpad/SmartDialCursorLoader.java b/src/com/android/dialer/dialpad/SmartDialCursorLoader.java
index 372692e..f83f18c 100644
--- a/src/com/android/dialer/dialpad/SmartDialCursorLoader.java
+++ b/src/com/android/dialer/dialpad/SmartDialCursorLoader.java
@@ -25,6 +25,7 @@
 import android.util.Log;
 
 import com.android.contacts.common.list.PhoneNumberListAdapter.PhoneQuery;
+import com.android.contacts.common.util.PermissionsUtil;
 import com.android.dialer.database.DialerDatabaseHelper;
 import com.android.dialer.database.DialerDatabaseHelper.ContactNumber;
 import com.android.dialerbind.DatabaseHelperManager;
@@ -77,6 +78,10 @@
             Log.v(TAG, "Load in background " + mQuery);
         }
 
+        if (!PermissionsUtil.hasContactsPermissions(mContext)) {
+            return new MatrixCursor(PhoneQuery.PROJECTION_PRIMARY);
+        }
+
         /** Loads results from the database helper. */
         final DialerDatabaseHelper dialerDatabaseHelper = DatabaseHelperManager.getDatabaseHelper(
                 mContext);
diff --git a/src/com/android/dialer/interactions/UndemoteOutgoingCallReceiver.java b/src/com/android/dialer/interactions/UndemoteOutgoingCallReceiver.java
index 960a31b..fd3d512 100644
--- a/src/com/android/dialer/interactions/UndemoteOutgoingCallReceiver.java
+++ b/src/com/android/dialer/interactions/UndemoteOutgoingCallReceiver.java
@@ -27,6 +27,8 @@
 import android.provider.ContactsContract.PinnedPositions;
 import android.text.TextUtils;
 
+import com.android.contacts.common.util.PermissionsUtil;
+
 /**
  * This broadcast receiver is used to listen to outgoing calls and undemote formerly demoted
  * contacts if a phone call is made to a phone number belonging to that contact.
@@ -39,12 +41,15 @@
 
     @Override
     public void onReceive(final Context context, Intent intent) {
+        if (!PermissionsUtil.hasContactsPermissions(context)) {
+            return;
+        }
         if (intent != null && Intent.ACTION_NEW_OUTGOING_CALL.equals(intent.getAction())) {
             final String number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
             if (TextUtils.isEmpty(number)) {
                 return;
             }
-            final Thread thread = new Thread() {
+            new Thread() {
                 @Override
                 public void run() {
                     final long id = getContactIdFromPhoneNumber(context, number);
@@ -52,8 +57,7 @@
                         undemoteContactWithId(context, id);
                     }
                 }
-            };
-            thread.start();
+            }.start();
         }
     }
 
diff --git a/src/com/android/dialer/list/AllContactsFragment.java b/src/com/android/dialer/list/AllContactsFragment.java
index 94efc48..eaa5cc8 100644
--- a/src/com/android/dialer/list/AllContactsFragment.java
+++ b/src/com/android/dialer/list/AllContactsFragment.java
@@ -29,6 +29,7 @@
 import com.android.contacts.common.list.ContactEntryListFragment;
 import com.android.contacts.common.list.ContactListFilter;
 import com.android.contacts.common.list.DefaultContactListAdapter;
+import com.android.contacts.common.util.PermissionsUtil;
 import com.android.contacts.common.util.ViewUtil;
 import com.android.dialer.R;
 import com.android.dialer.util.DialerUtils;
@@ -60,7 +61,18 @@
     }
 
     @Override
+    protected void startLoading() {
+        if (PermissionsUtil.hasContactsPermissions(getActivity())) {
+            super.startLoading();
+        }
+    }
+
+    @Override
     protected ContactEntryListAdapter createListAdapter() {
+        if (!PermissionsUtil.hasContactsPermissions(getActivity())) {
+            return new EmptyContactsListAdapter(getActivity());
+        }
+
         final DefaultContactListAdapter adapter = new DefaultContactListAdapter(getActivity()) {
             @Override
             protected void bindView(View itemView, int partition, Cursor cursor, int position) {
diff --git a/src/com/android/dialer/list/EmptyContactsListAdapter.java b/src/com/android/dialer/list/EmptyContactsListAdapter.java
new file mode 100644
index 0000000..54bd477
--- /dev/null
+++ b/src/com/android/dialer/list/EmptyContactsListAdapter.java
@@ -0,0 +1,47 @@
+/*
+ * 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.dialer.list;
+
+import android.content.Context;
+import android.content.CursorLoader;
+
+import com.android.contacts.common.list.ContactEntryListAdapter;
+
+/**
+ * Used to display an empty contact list when we don't have the permissions to read contacts.
+ */
+public class EmptyContactsListAdapter extends ContactEntryListAdapter {
+
+    public EmptyContactsListAdapter(Context context) {
+        super(context);
+    }
+
+    @Override
+    public String getContactDisplayName(int position) {
+        return null;
+    }
+
+    @Override
+    public void configureLoader(CursorLoader loader, long directoryId) {
+        loader.setUri(null);
+    }
+
+    @Override
+    public int getCount() {
+        return 0;
+    }
+}
diff --git a/src/com/android/dialer/list/ListsFragment.java b/src/com/android/dialer/list/ListsFragment.java
index 0ac6b1a..a0e443c 100644
--- a/src/com/android/dialer/list/ListsFragment.java
+++ b/src/com/android/dialer/list/ListsFragment.java
@@ -62,9 +62,6 @@
     // Oldest recents entry to display is 2 weeks old.
     private static final long OLDEST_RECENTS_DATE = 1000L * 60 * 60 * 24 * 14;
 
-    private static final String KEY_LAST_DISMISSED_CALL_SHORTCUT_DATE =
-            "key_last_dismissed_call_shortcut_date";
-
     public interface HostInterface {
         public ActionBarController getActionBarController();
     }
@@ -92,18 +89,7 @@
     /**
      * The position of the currently selected tab.
      */
-    private int mTabPosition = TAB_INDEX_SPEED_DIAL;
-
-    /**
-     * Call shortcuts older than this date (persisted in shared preferences) will not show up in
-     * at the top of the screen
-     */
-    private long mLastCallShortcutDate = 0;
-
-    /**
-     * The date of the current call shortcut that is showing on screen.
-     */
-    private long mCurrentCallShortcutDate = 0;
+    private int mTabIndex = TAB_INDEX_SPEED_DIAL;
 
     public class ViewPagerAdapter extends FragmentPagerAdapter {
         public ViewPagerAdapter(FragmentManager fm) {
@@ -182,12 +168,9 @@
     public void onResume() {
         Trace.beginSection(TAG + " onResume");
         super.onResume();
-        final SharedPreferences prefs = getActivity().getSharedPreferences(
-                DialtactsActivity.SHARED_PREFS_NAME, Context.MODE_PRIVATE);
-        mLastCallShortcutDate = prefs.getLong(KEY_LAST_DISMISSED_CALL_SHORTCUT_DATE, 0);
         mActionBar = getActivity().getActionBar();
         if (getUserVisibleHint()) {
-            sendScreenViewForPosition(mViewPager.getCurrentItem());
+            sendScreenViewForCurrentPosition();
         }
 
         // Fetch voicemail status to determine if we should show the voicemail tab.
@@ -208,7 +191,7 @@
         mViewPager = (ViewPager) parentView.findViewById(R.id.lists_pager);
         mViewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
         mViewPager.setAdapter(mViewPagerAdapter);
-        mViewPager.setOffscreenPageLimit(TAB_COUNT_DEFAULT - 1);
+        mViewPager.setOffscreenPageLimit(TAB_COUNT_WITH_VOICEMAIL - 1);
         mViewPager.setOnPageChangeListener(this);
         mViewPager.setCurrentItem(getRtlPosition(TAB_INDEX_SPEED_DIAL));
 
@@ -245,6 +228,8 @@
 
     @Override
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+        mTabIndex = getRtlPosition(position);
+
         final int count = mOnPageChangeListeners.size();
         for (int i = 0; i < count; i++) {
             mOnPageChangeListeners.get(i).onPageScrolled(position, positionOffset,
@@ -254,13 +239,13 @@
 
     @Override
     public void onPageSelected(int position) {
-        mTabPosition = getRtlPosition(position);
+        mTabIndex = getRtlPosition(position);
 
         final int count = mOnPageChangeListeners.size();
         for (int i = 0; i < count; i++) {
             mOnPageChangeListeners.get(i).onPageSelected(position);
         }
-        sendScreenViewForPosition(position);
+        sendScreenViewForCurrentPosition();
     }
 
     @Override
@@ -293,8 +278,8 @@
         return false;
     }
 
-    public int getTabPosition() {
-        return mTabPosition;
+    public int getCurrentTabIndex() {
+        return mTabIndex;
     }
 
     public void showRemoveView(boolean show) {
@@ -316,7 +301,7 @@
         return mRemoveView;
     }
 
-    public int getRtlPosition(int position) {
+    private int getRtlPosition(int position) {
         if (DialerUtils.isRtl()) {
             return mViewPagerAdapter.getCount() - 1 - position;
         }
@@ -324,15 +309,12 @@
     }
 
     public void sendScreenViewForCurrentPosition() {
-        sendScreenViewForPosition(mViewPager.getCurrentItem());
-    }
-
-    private void sendScreenViewForPosition(int position) {
         if (!isResumed()) {
             return;
         }
+
         String fragmentName;
-        switch (getRtlPosition(position)) {
+        switch (getCurrentTabIndex()) {
             case TAB_INDEX_SPEED_DIAL:
                 fragmentName = SpeedDialFragment.class.getSimpleName();
                 break;
diff --git a/src/com/android/dialer/list/RegularSearchListAdapter.java b/src/com/android/dialer/list/RegularSearchListAdapter.java
index 6c70458..2be8a1d 100644
--- a/src/com/android/dialer/list/RegularSearchListAdapter.java
+++ b/src/com/android/dialer/list/RegularSearchListAdapter.java
@@ -22,6 +22,7 @@
 
 import com.android.contacts.common.CallUtil;
 import com.android.contacts.common.list.DirectoryPartition;
+import com.android.contacts.common.util.PhoneNumberHelper;
 import com.android.dialer.calllog.ContactInfo;
 import com.android.dialer.service.CachedNumberLookupService;
 import com.android.dialer.service.CachedNumberLookupService.CachedContactInfo;
@@ -30,6 +31,7 @@
  * List adapter to display regular search results.
  */
 public class RegularSearchListAdapter extends DialerPhoneNumberListAdapter {
+    private boolean mIsQuerySipAddress;
 
     public RegularSearchListAdapter(Context context) {
         super(context);
@@ -67,12 +69,24 @@
     }
 
     @Override
+    public String getFormattedQueryString() {
+        if (mIsQuerySipAddress) {
+            // Return unnormalized SIP address
+            return getQueryString();
+        }
+        return super.getFormattedQueryString();
+    }
+
+    @Override
     public void setQueryString(String queryString) {
         // Don't show actions if the query string contains a letter.
         final boolean showNumberShortcuts = !TextUtils.isEmpty(getFormattedQueryString())
                 && hasDigitsInQueryString();
+        // Email addresses that could be SIP addresses are an exception.
+        mIsQuerySipAddress = PhoneNumberHelper.isUriNumber(queryString);
         boolean changed = false;
-        changed |= setShortcutEnabled(SHORTCUT_DIRECT_CALL, showNumberShortcuts);
+        changed |= setShortcutEnabled(SHORTCUT_DIRECT_CALL,
+                showNumberShortcuts || mIsQuerySipAddress);
         changed |= setShortcutEnabled(SHORTCUT_SEND_SMS_MESSAGE, showNumberShortcuts);
         changed |= setShortcutEnabled(SHORTCUT_MAKE_VIDEO_CALL,
                 showNumberShortcuts && CallUtil.isVideoEnabled(getContext()));
diff --git a/src/com/android/dialer/list/SearchFragment.java b/src/com/android/dialer/list/SearchFragment.java
index c314478..f86c0e5 100644
--- a/src/com/android/dialer/list/SearchFragment.java
+++ b/src/com/android/dialer/list/SearchFragment.java
@@ -37,6 +37,7 @@
 import com.android.contacts.common.list.ContactListItemView;
 import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
 import com.android.contacts.common.list.PhoneNumberPickerFragment;
+import com.android.contacts.common.util.PermissionsUtil;
 import com.android.contacts.common.util.ViewUtil;
 import com.android.contacts.commonbind.analytics.AnalyticsUtil;
 import com.android.dialer.dialpad.DialpadFragment.ErrorDialogFragment;
@@ -287,4 +288,14 @@
                 listView.getPaddingEnd(),
                 listView.getPaddingBottom());
     }
+
+    @Override
+    protected void startLoading() {
+        if (PermissionsUtil.hasContactsPermissions(getActivity())) {
+            super.startLoading();
+        } else if (TextUtils.isEmpty(getQueryString())) {
+            // Clear out any existing call shortcuts.
+            getAdapter().setQueryString(null);
+        }
+    }
 }
diff --git a/src/com/android/dialer/list/SpeedDialFragment.java b/src/com/android/dialer/list/SpeedDialFragment.java
index e72b250..541cdf6 100644
--- a/src/com/android/dialer/list/SpeedDialFragment.java
+++ b/src/com/android/dialer/list/SpeedDialFragment.java
@@ -23,7 +23,6 @@
 import android.app.LoaderManager;
 import android.content.CursorLoader;
 import android.content.Loader;
-import android.content.res.Resources;
 import android.database.Cursor;
 import android.graphics.Rect;
 import android.net.Uri;
@@ -43,12 +42,12 @@
 import android.widget.FrameLayout.LayoutParams;
 import android.widget.ImageView;
 import android.widget.ListView;
-import android.widget.RelativeLayout;
 
 import com.android.contacts.common.ContactPhotoManager;
 import com.android.contacts.common.ContactTileLoaderFactory;
 import com.android.contacts.common.list.ContactTileView;
 import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
+import com.android.contacts.common.util.PermissionsUtil;
 import com.android.dialer.R;
 import com.android.dialer.util.DialerUtils;
 
@@ -194,7 +193,9 @@
         Trace.beginSection(TAG + " onResume");
         super.onResume();
 
-        getLoaderManager().getLoader(LOADER_ID_CONTACT_TILE).forceLoad();
+        if (PermissionsUtil.hasContactsPermissions(getActivity())) {
+            getLoaderManager().getLoader(LOADER_ID_CONTACT_TILE).forceLoad();
+        }
         Trace.endSection();
     }
 
@@ -286,7 +287,11 @@
         // Use initLoader() instead of restartLoader() to refraining unnecessary reload.
         // This method call implicitly assures ContactTileLoaderListener's onLoadFinished() will
         // be called, on which we'll check if "all" contacts should be reloaded again or not.
-        getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, mContactTileLoaderListener);
+        if (PermissionsUtil.hasContactsPermissions(activity)) {
+            getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, mContactTileLoaderListener);
+        } else {
+            setEmptyViewVisibility(true);
+        }
     }
 
     /**
diff --git a/src/com/android/dialer/voicemail/VoicemailPlaybackFragment.java b/src/com/android/dialer/voicemail/VoicemailPlaybackFragment.java
deleted file mode 100644
index 8aa0197..0000000
--- a/src/com/android/dialer/voicemail/VoicemailPlaybackFragment.java
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * Copyright (C) 2011 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.dialer.voicemail;
-
-import static com.android.dialer.CallDetailActivity.EXTRA_VOICEMAIL_START_PLAYBACK;
-import static com.android.dialer.CallDetailActivity.EXTRA_VOICEMAIL_URI;
-
-import android.app.Activity;
-import android.app.Fragment;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.media.AudioManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.PowerManager;
-import android.provider.VoicemailContract;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageButton;
-import android.widget.SeekBar;
-import android.widget.TextView;
-
-import com.android.common.io.MoreCloseables;
-import com.android.contacts.commonbind.analytics.AnalyticsUtil;
-import com.android.dialer.R;
-import com.android.dialer.util.AsyncTaskExecutors;
-import com.android.ex.variablespeed.MediaPlayerProxy;
-import com.android.ex.variablespeed.VariableSpeed;
-
-import com.google.common.base.Preconditions;
-
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.annotation.concurrent.NotThreadSafe;
-
-/**
- * Displays and plays back a single voicemail.
- * <p>
- * When the Activity containing this Fragment is created, voicemail playback
- * will begin immediately. The Activity is expected to be started via an intent
- * containing a suitable voicemail uri to playback.
- * <p>
- * This class is not thread-safe, it is thread-confined. All calls to all public
- * methods on this class are expected to come from the main ui thread.
- */
-@NotThreadSafe
-public class VoicemailPlaybackFragment extends Fragment {
-    private static final String TAG = VoicemailPlaybackFragment.class.getSimpleName();
-    private static final int NUMBER_OF_THREADS_IN_POOL = 2;
-    private static final String[] HAS_CONTENT_PROJECTION = new String[] {
-        VoicemailContract.Voicemails.HAS_CONTENT,
-    };
-
-    private VoicemailPlaybackPresenter mPresenter;
-    private static int mMediaPlayerRefCount = 0;
-    private static MediaPlayerProxy mMediaPlayerInstance;
-    private static ScheduledExecutorService mScheduledExecutorService;
-    private View mPlaybackLayout;
-
-    private PowerManager.WakeLock mProximityWakeLock;
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-            Bundle savedInstanceState) {
-        mPlaybackLayout = inflater.inflate(R.layout.playback_layout, null);
-        return mPlaybackLayout;
-    }
-
-    @Override
-    public void onActivityCreated(Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
-        Bundle arguments = getArguments();
-        Preconditions.checkNotNull(arguments, "fragment must be started with arguments");
-        Uri voicemailUri = arguments.getParcelable(EXTRA_VOICEMAIL_URI);
-        Preconditions.checkNotNull(voicemailUri, "fragment must contain EXTRA_VOICEMAIL_URI");
-        boolean startPlayback = arguments.getBoolean(EXTRA_VOICEMAIL_START_PLAYBACK, false);
-
-        PowerManager powerManager =
-                (PowerManager) getActivity().getSystemService(Context.POWER_SERVICE);
-        if (powerManager.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
-            mProximityWakeLock = powerManager.newWakeLock(
-                    PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG);
-        } else {
-            mProximityWakeLock = null;
-        }
-
-        mPresenter = new VoicemailPlaybackPresenter(
-                createPlaybackViewImpl(),
-                getMediaPlayerInstance(),
-                voicemailUri,
-                getScheduledExecutorServiceInstance(),
-                startPlayback,
-                AsyncTaskExecutors.createAsyncTaskExecutor(),
-                mProximityWakeLock);
-        mPresenter.onCreate(savedInstanceState);
-    }
-
-    @Override
-    public void onSaveInstanceState(Bundle outState) {
-        mPresenter.onSaveInstanceState(outState);
-        super.onSaveInstanceState(outState);
-    }
-
-    @Override
-    public void onStart() {
-        super.onStart();
-        AnalyticsUtil.sendScreenView(this);
-    }
-
-    @Override
-    public void onViewStateRestored(Bundle savedInstanceState) {
-        mPresenter.onRestoreInstanceState(savedInstanceState);
-        super.onViewStateRestored(savedInstanceState);
-    }
-
-    @Override
-    public void onDestroy() {
-        shutdownMediaPlayer();
-        mPresenter.onDestroy();
-        super.onDestroy();
-    }
-
-    @Override
-    public void onPause() {
-        releaseProximitySensor(false /* waitForFarState */);
-        mPresenter.onPause();
-        super.onPause();
-    }
-
-    private PlaybackViewImpl createPlaybackViewImpl() {
-        return new PlaybackViewImpl(new ActivityReference(), getActivity().getApplicationContext(),
-                mPlaybackLayout);
-    }
-
-    private static synchronized MediaPlayerProxy getMediaPlayerInstance() {
-        ++mMediaPlayerRefCount;
-        if (mMediaPlayerInstance == null) {
-            mMediaPlayerInstance = VariableSpeed.createVariableSpeed(
-                    getScheduledExecutorServiceInstance());
-        }
-        return mMediaPlayerInstance;
-    }
-
-    private static synchronized ScheduledExecutorService getScheduledExecutorServiceInstance() {
-        if (mScheduledExecutorService == null) {
-            mScheduledExecutorService = Executors.newScheduledThreadPool(
-                    NUMBER_OF_THREADS_IN_POOL);
-        }
-        return mScheduledExecutorService;
-    }
-
-    private static synchronized void shutdownMediaPlayer() {
-        --mMediaPlayerRefCount;
-        if (mMediaPlayerRefCount > 0) {
-            return;
-        }
-        if (mScheduledExecutorService != null) {
-            mScheduledExecutorService.shutdown();
-            mScheduledExecutorService = null;
-        }
-        if (mMediaPlayerInstance != null) {
-            mMediaPlayerInstance.release();
-            mMediaPlayerInstance = null;
-        }
-    }
-
-    private void acquireProximitySensor() {
-        if (mProximityWakeLock == null) {
-            return;
-        }
-        if (!mProximityWakeLock.isHeld()) {
-            Log.i(TAG, "Acquiring proximity wake lock");
-            mProximityWakeLock.acquire();
-        } else {
-            Log.i(TAG, "Proximity wake lock already acquired");
-        }
-    }
-
-    private void releaseProximitySensor(boolean waitForFarState) {
-        if (mProximityWakeLock == null) {
-            return;
-        }
-        if (mProximityWakeLock.isHeld()) {
-            Log.i(TAG, "Releasing proximity wake lock");
-            int flags = waitForFarState ? PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY : 0;
-            mProximityWakeLock.release(flags);
-        } else {
-            Log.i(TAG, "Proximity wake lock already released");
-        }
-    }
-
-    /**
-     * Formats a number of milliseconds as something that looks like {@code 00:05}.
-     * <p>
-     * We always use four digits, two for minutes two for seconds.  In the very unlikely event
-     * that the voicemail duration exceeds 99 minutes, the display is capped at 99 minutes.
-     */
-    private static String formatAsMinutesAndSeconds(int millis) {
-        int seconds = millis / 1000;
-        int minutes = seconds / 60;
-        seconds -= minutes * 60;
-        if (minutes > 99) {
-            minutes = 99;
-        }
-        return String.format("%02d:%02d", minutes, seconds);
-    }
-
-    /**
-     * An object that can provide us with an Activity.
-     * <p>
-     * Fragments suffer the drawback that the Activity they belong to may sometimes be null. This
-     * can happen if the Fragment is detached, for example. In that situation a call to
-     * {@link Fragment#getString(int)} will throw and {@link IllegalStateException}. Also, calling
-     * {@link Fragment#getActivity()} is dangerous - it may sometimes return null. And thus blindly
-     * calling a method on the result of getActivity() is dangerous too.
-     * <p>
-     * To work around this, I have made the {@link PlaybackViewImpl} class static, so that it does
-     * not have access to any Fragment methods directly. Instead it uses an application Context for
-     * things like accessing strings, accessing system services. It only uses the Activity when it
-     * absolutely needs it - and does so through this class. This makes it easy to see where we have
-     * to check for null properly.
-     */
-    private final class ActivityReference {
-        /** Gets this Fragment's Activity: <b>may be null</b>. */
-        public final Activity get() {
-            return getActivity();
-        }
-    }
-
-    /**  Methods required by the PlaybackView for the VoicemailPlaybackPresenter. */
-    private final class PlaybackViewImpl implements VoicemailPlaybackPresenter.PlaybackView {
-        private final ActivityReference mActivityReference;
-        private final Context mApplicationContext;
-        private final SeekBar mPlaybackSeek;
-        private final ImageButton mStartStopButton;
-        private final ImageButton mPlaybackSpeakerphone;
-        private final TextView mPlaybackPosition;
-
-        public PlaybackViewImpl(ActivityReference activityReference, Context applicationContext,
-                View playbackLayout) {
-            Preconditions.checkNotNull(activityReference);
-            Preconditions.checkNotNull(applicationContext);
-            Preconditions.checkNotNull(playbackLayout);
-            mActivityReference = activityReference;
-            mApplicationContext = applicationContext;
-            mPlaybackSeek = (SeekBar) playbackLayout.findViewById(R.id.playback_seek);
-            mStartStopButton = (ImageButton) playbackLayout.findViewById(
-                    R.id.playback_start_stop);
-            mPlaybackSpeakerphone = (ImageButton) playbackLayout.findViewById(
-                    R.id.playback_speakerphone);
-            mPlaybackPosition =
-                    (TextView) playbackLayout.findViewById(R.id.playback_position_text);
-        }
-
-        @Override
-        public void finish() {
-            Activity activity = mActivityReference.get();
-            if (activity != null) {
-                activity.finish();
-            }
-        }
-
-        @Override
-        public void runOnUiThread(Runnable runnable) {
-            Activity activity = mActivityReference.get();
-            if (activity != null) {
-                activity.runOnUiThread(runnable);
-            }
-        }
-
-        @Override
-        public Context getDataSourceContext() {
-            return mApplicationContext;
-        }
-
-        @Override
-        public void setStartStopListener(View.OnClickListener listener) {
-            mStartStopButton.setOnClickListener(listener);
-        }
-
-        @Override
-        public void setSpeakerphoneListener(View.OnClickListener listener) {
-            mPlaybackSpeakerphone.setOnClickListener(listener);
-        }
-
-        @Override
-        public void setPositionSeekListener(SeekBar.OnSeekBarChangeListener listener) {
-            mPlaybackSeek.setOnSeekBarChangeListener(listener);
-        }
-
-        @Override
-        public void playbackStarted() {
-            mStartStopButton.setImageResource(R.drawable.ic_hold_pause);
-        }
-
-        @Override
-        public void playbackStopped() {
-            mStartStopButton.setImageResource(R.drawable.ic_play);
-        }
-
-        @Override
-        public void enableProximitySensor() {
-            // Only change the state if the activity is still around.
-            Activity activity = mActivityReference.get();
-            if (activity != null) {
-                acquireProximitySensor();
-            }
-        }
-
-        @Override
-        public void disableProximitySensor() {
-            // Only change the state if the activity is still around.
-            Activity activity = mActivityReference.get();
-            if (activity != null) {
-                releaseProximitySensor(true /* waitForFarState */);
-            }
-        }
-
-        @Override
-        public void registerContentObserver(Uri uri, ContentObserver observer) {
-            mApplicationContext.getContentResolver().registerContentObserver(uri, false, observer);
-        }
-
-        @Override
-        public void unregisterContentObserver(ContentObserver observer) {
-            mApplicationContext.getContentResolver().unregisterContentObserver(observer);
-        }
-
-        @Override
-        public void setClipPosition(int clipPositionInMillis, int clipLengthInMillis) {
-            int seekBarPosition = Math.max(0, clipPositionInMillis);
-            int seekBarMax = Math.max(seekBarPosition, clipLengthInMillis);
-            if (mPlaybackSeek.getMax() != seekBarMax) {
-                mPlaybackSeek.setMax(seekBarMax);
-            }
-            mPlaybackSeek.setProgress(seekBarPosition);
-            mPlaybackPosition.setText(formatAsMinutesAndSeconds(seekBarMax - seekBarPosition));
-        }
-
-        private String getString(int resId) {
-            return mApplicationContext.getString(resId);
-        }
-
-        @Override
-        public void setIsBuffering() {
-            disableUiElements();
-            mPlaybackPosition.setText(getString(R.string.voicemail_buffering));
-        }
-
-        @Override
-        public void setIsFetchingContent() {
-            disableUiElements();
-            mPlaybackPosition.setText(getString(R.string.voicemail_fetching_content));
-        }
-
-        @Override
-        public void setFetchContentTimeout() {
-            disableUiElements();
-            mPlaybackPosition.setText(getString(R.string.voicemail_fetching_timout));
-        }
-
-        @Override
-        public int getDesiredClipPosition() {
-            return mPlaybackSeek.getProgress();
-        }
-
-        @Override
-        public void disableUiElements() {
-            mStartStopButton.setEnabled(false);
-            mPlaybackSpeakerphone.setEnabled(false);
-            mPlaybackSeek.setProgress(0);
-            mPlaybackSeek.setEnabled(false);
-        }
-
-        @Override
-        public void playbackError(Exception e) {
-            disableUiElements();
-            mPlaybackPosition.setText(getString(R.string.voicemail_playback_error));
-            Log.e(TAG, "Could not play voicemail", e);
-        }
-
-        @Override
-        public void enableUiElements() {
-            mStartStopButton.setEnabled(true);
-            mPlaybackSpeakerphone.setEnabled(true);
-            mPlaybackSeek.setEnabled(true);
-        }
-
-        @Override
-        public void sendFetchVoicemailRequest(Uri voicemailUri) {
-            Intent intent = new Intent(VoicemailContract.ACTION_FETCH_VOICEMAIL, voicemailUri);
-            mApplicationContext.sendBroadcast(intent);
-        }
-
-        @Override
-        public boolean queryHasContent(Uri voicemailUri) {
-            ContentResolver contentResolver = mApplicationContext.getContentResolver();
-            Cursor cursor = contentResolver.query(
-                    voicemailUri, HAS_CONTENT_PROJECTION, null, null, null);
-            try {
-                if (cursor != null && cursor.moveToNext()) {
-                    return cursor.getInt(cursor.getColumnIndexOrThrow(
-                            VoicemailContract.Voicemails.HAS_CONTENT)) == 1;
-                }
-            } finally {
-                MoreCloseables.closeQuietly(cursor);
-            }
-            return false;
-        }
-
-        private AudioManager getAudioManager() {
-            return (AudioManager) mApplicationContext.getSystemService(Context.AUDIO_SERVICE);
-        }
-
-        @Override
-        public boolean isSpeakerPhoneOn() {
-            return getAudioManager().isSpeakerphoneOn();
-        }
-
-        @Override
-        public void setSpeakerPhoneOn(boolean on) {
-            getAudioManager().setSpeakerphoneOn(on);
-            if (on) {
-                mPlaybackSpeakerphone.setImageResource(R.drawable.ic_speakerphone_on);
-                // Speaker is now on, tapping button will turn it off.
-                mPlaybackSpeakerphone.setContentDescription(
-                        mApplicationContext.getString(R.string.voicemail_speaker_off));
-            } else {
-                mPlaybackSpeakerphone.setImageResource(R.drawable.ic_speakerphone_off);
-                // Speaker is now off, tapping button will turn it on.
-                mPlaybackSpeakerphone.setContentDescription(
-                        mApplicationContext.getString(R.string.voicemail_speaker_on));
-            }
-        }
-
-        @Override
-        public void setVolumeControlStream(int streamType) {
-            Activity activity = mActivityReference.get();
-            if (activity != null) {
-                activity.setVolumeControlStream(streamType);
-            }
-        }
-    }
-}
diff --git a/src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java b/src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java
new file mode 100644
index 0000000..0e9ff3b
--- /dev/null
+++ b/src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2011 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.dialer.voicemail;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.PowerManager;
+import android.provider.VoicemailContract;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
+
+import com.android.common.io.MoreCloseables;
+import com.android.dialer.R;
+
+import com.google.common.base.Preconditions;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ScheduledExecutorService;
+
+import javax.annotation.concurrent.GuardedBy;
+import javax.annotation.concurrent.NotThreadSafe;
+import javax.annotation.concurrent.ThreadSafe;
+
+/**
+ * Displays and plays a single voicemail.
+ * <p>
+ * This class is not thread-safe, it is thread-confined. All calls to all public
+ * methods on this class are expected to come from the main ui thread.
+ */
+@NotThreadSafe
+public class VoicemailPlaybackLayout extends LinearLayout
+        implements VoicemailPlaybackPresenter.PlaybackView {
+    private static final String TAG = VoicemailPlaybackLayout.class.getSimpleName();
+
+    /**
+     * Controls the animation of the playback slider.
+     */
+    @ThreadSafe
+    private final class PositionUpdater implements Runnable {
+
+        /** Update rate for the slider, 30fps. */
+        private static final int SLIDER_UPDATE_PERIOD_MILLIS = 1000 / 30;
+
+        private final MediaPlayer mMediaPlayer;
+        private final int mDuration;
+        private final ScheduledExecutorService mExecutorService;
+        private final Object mLock = new Object();
+        @GuardedBy("mLock") private ScheduledFuture<?> mScheduledFuture;
+
+        public PositionUpdater(
+                MediaPlayer mediaPlayer,
+                int duration,
+                ScheduledExecutorService executorService) {
+            mMediaPlayer = mediaPlayer;
+            mDuration = duration;
+            mExecutorService = executorService;
+        }
+
+        @Override
+        public void run() {
+            post(new Runnable() {
+                @Override
+                public void run() {
+                    int currentPosition = 0;
+                    synchronized (mLock) {
+                        if (mScheduledFuture == null) {
+                            // This task has been canceled. Just stop now.
+                            return;
+                        }
+                        currentPosition = mMediaPlayer.getCurrentPosition();
+                    }
+                    setClipPosition(currentPosition, mDuration);
+                }
+            });
+        }
+
+        public void startUpdating() {
+            synchronized (mLock) {
+                if (mScheduledFuture != null) {
+                    mScheduledFuture.cancel(false);
+                    mScheduledFuture = null;
+                }
+                mScheduledFuture = mExecutorService.scheduleAtFixedRate(
+                        this, 0, SLIDER_UPDATE_PERIOD_MILLIS, TimeUnit.MILLISECONDS);
+            }
+        }
+
+        public void stopUpdating() {
+            synchronized (mLock) {
+                if (mScheduledFuture != null) {
+                    mScheduledFuture.cancel(false);
+                    mScheduledFuture = null;
+                }
+            }
+        }
+    }
+
+    /**
+     * Handle state changes when the user manipulates the seek bar.
+     */
+    private final OnSeekBarChangeListener seekBarChangeListener = new OnSeekBarChangeListener() {
+        @Override
+        public void onStartTrackingTouch(SeekBar seekBar) {
+            if (mPresenter != null) {
+                mPresenter.pausePlaybackForSeeking();
+            }
+        }
+
+        @Override
+        public void onStopTrackingTouch(SeekBar seekBar) {
+            if (mPresenter != null) {
+                mPresenter.resumePlaybackAfterSeeking(seekBar.getProgress());
+            }
+        }
+
+        @Override
+        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+            setClipPosition(seekBar.getProgress(), seekBar.getMax());
+        }
+    };
+
+    /**
+     * Click listener to toggle speakerphone.
+     */
+    private final View.OnClickListener speakerphoneListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            if (mPresenter != null) {
+                onSpeakerphoneOn(!mPresenter.isSpeakerphoneOn());
+            }
+        }
+    };
+
+    /**
+     * Click listener to play or pause voicemail playback.
+     */
+    private final View.OnClickListener startStopButtonListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View view) {
+            if (mPresenter == null) {
+                return;
+            }
+            if (mIsPlaying) {
+                mPresenter.pausePlayback();
+            } else {
+                mPresenter.resumePlayback();
+            }
+        }
+    };
+
+    private Context mContext;
+    private VoicemailPlaybackPresenter mPresenter;
+
+    private boolean mIsPlaying = false;
+
+    private SeekBar mPlaybackSeek;
+    private ImageButton mStartStopButton;
+    private ImageButton mPlaybackSpeakerphone;
+    private TextView mPlaybackPosition;
+
+    private PositionUpdater mPositionUpdater;
+
+    public VoicemailPlaybackLayout(Context context) {
+        this(context, null);
+    }
+
+    public VoicemailPlaybackLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        mContext = context;
+        LayoutInflater inflater =
+                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        inflater.inflate(R.layout.playback_layout, this);
+    }
+
+    @Override
+    public void setPresenter(VoicemailPlaybackPresenter presenter) {
+        mPresenter = presenter;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mPlaybackSeek = (SeekBar) findViewById(R.id.playback_seek);
+        mStartStopButton = (ImageButton) findViewById(R.id.playback_start_stop);
+        mPlaybackSpeakerphone = (ImageButton) findViewById(R.id.playback_speakerphone);
+        mPlaybackPosition = (TextView) findViewById(R.id.playback_position_text);
+
+        mPlaybackSeek.setOnSeekBarChangeListener(seekBarChangeListener);
+        mStartStopButton.setOnClickListener(startStopButtonListener);
+        mPlaybackSpeakerphone.setOnClickListener(speakerphoneListener);
+    }
+
+    @Override
+    public void onPlaybackStarted(
+            MediaPlayer mediaPlayer,
+            int duration,
+            ScheduledExecutorService executorService) {
+        mIsPlaying = true;
+
+        mStartStopButton.setImageResource(R.drawable.ic_hold_pause);
+
+        if (mPresenter != null) {
+            onSpeakerphoneOn(mPresenter.isSpeakerphoneOn());
+        }
+
+        mPositionUpdater = new PositionUpdater(mediaPlayer, duration, executorService);
+        mPositionUpdater.startUpdating();
+    }
+
+    @Override
+    public void onPlaybackStopped() {
+        mIsPlaying = false;
+
+        mStartStopButton.setImageResource(R.drawable.ic_play);
+
+        if (mPositionUpdater != null) {
+            mPositionUpdater.stopUpdating();
+            mPositionUpdater = null;
+        }
+    }
+
+    @Override
+    public void onPlaybackError(Exception e) {
+        if (mPositionUpdater != null) {
+            mPositionUpdater.stopUpdating();
+        }
+
+        disableUiElements();
+        mPlaybackPosition.setText(getString(R.string.voicemail_playback_error));
+
+        Log.e(TAG, "Could not play voicemail", e);
+    }
+
+
+    public void onSpeakerphoneOn(boolean on) {
+        if (mPresenter != null) {
+            mPresenter.setSpeakerphoneOn(on);
+        }
+
+        if (on) {
+            mPlaybackSpeakerphone.setImageResource(R.drawable.ic_speakerphone_on);
+            // Speaker is now on, tapping button will turn it off.
+            mPlaybackSpeakerphone.setContentDescription(
+                    mContext.getString(R.string.voicemail_speaker_off));
+        } else {
+            mPlaybackSpeakerphone.setImageResource(R.drawable.ic_speakerphone_off);
+            // Speaker is now off, tapping button will turn it on.
+            mPlaybackSpeakerphone.setContentDescription(
+                    mContext.getString(R.string.voicemail_speaker_on));
+        }
+    }
+
+    @Override
+    public void setClipPosition(int clipPositionInMillis, int clipLengthInMillis) {
+        int seekBarPosition = Math.max(0, clipPositionInMillis);
+        int seekBarMax = Math.max(seekBarPosition, clipLengthInMillis);
+        if (mPlaybackSeek.getMax() != seekBarMax) {
+            mPlaybackSeek.setMax(seekBarMax);
+        }
+        mPlaybackSeek.setProgress(seekBarPosition);
+        mPlaybackPosition.setText(formatAsMinutesAndSeconds(seekBarMax - seekBarPosition));
+    }
+
+    @Override
+    public void setIsBuffering() {
+        disableUiElements();
+        mPlaybackPosition.setText(getString(R.string.voicemail_buffering));
+    }
+
+    @Override
+    public void setIsFetchingContent() {
+        disableUiElements();
+        mPlaybackPosition.setText(getString(R.string.voicemail_fetching_content));
+    }
+
+    @Override
+    public void setFetchContentTimeout() {
+        disableUiElements();
+        mPlaybackPosition.setText(getString(R.string.voicemail_fetching_timout));
+    }
+
+    @Override
+    public int getDesiredClipPosition() {
+        return mPlaybackSeek.getProgress();
+    }
+
+    @Override
+    public void disableUiElements() {
+        mStartStopButton.setEnabled(false);
+        mPlaybackSpeakerphone.setEnabled(false);
+        mPlaybackSeek.setProgress(0);
+        mPlaybackSeek.setEnabled(false);
+    }
+
+    @Override
+    public void enableUiElements() {
+        mStartStopButton.setEnabled(true);
+        mPlaybackSpeakerphone.setEnabled(true);
+        mPlaybackSeek.setEnabled(true);
+    }
+
+    private String getString(int resId) {
+        return mContext.getString(resId);
+    }
+
+    /**
+     * Formats a number of milliseconds as something that looks like {@code 00:05}.
+     * <p>
+     * We always use four digits, two for minutes two for seconds.  In the very unlikely event
+     * that the voicemail duration exceeds 99 minutes, the display is capped at 99 minutes.
+     */
+    private String formatAsMinutesAndSeconds(int millis) {
+        int seconds = millis / 1000;
+        int minutes = seconds / 60;
+        seconds -= minutes * 60;
+        if (minutes > 99) {
+            minutes = 99;
+        }
+        return String.format("%02d:%02d", minutes, seconds);
+    }
+}
diff --git a/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java b/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
index 029f5bd..e8b0460 100644
--- a/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
+++ b/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
@@ -16,8 +16,12 @@
 
 package com.android.dialer.voicemail;
 
+import android.app.Activity;
 import android.content.Context;
+import android.content.ContentResolver;
+import android.content.Intent;
 import android.database.ContentObserver;
+import android.database.Cursor;
 import android.media.AudioManager;
 import android.media.AudioManager.OnAudioFocusChangeListener;
 import android.media.MediaPlayer;
@@ -26,97 +30,85 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.PowerManager;
+import android.provider.VoicemailContract;
+import android.util.Log;
 import android.view.View;
 import android.widget.SeekBar;
 
 import com.android.dialer.R;
 import com.android.dialer.util.AsyncTaskExecutor;
-import com.android.ex.variablespeed.MediaPlayerProxy;
-import com.android.ex.variablespeed.SingleThreadedMediaPlayerProxy;
+import com.android.dialer.util.AsyncTaskExecutors;
 
+import com.android.common.io.MoreCloseables;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 
+import java.io.IOException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import javax.annotation.concurrent.GuardedBy;
 import javax.annotation.concurrent.NotThreadSafe;
 import javax.annotation.concurrent.ThreadSafe;
 
 /**
- * Contains the controlling logic for a voicemail playback ui.
+ * Contains the controlling logic for a voicemail playback UI.
  * <p>
- * Specifically right now this class is used to control the
- * {@link com.android.dialer.voicemail.VoicemailPlaybackFragment}.
+ * This controls a single {@link com.android.dialer.voicemail.VoicemailPlaybackLayout}. A single
+ * instance can be reused for different such layouts, using {@link #setVoicemailPlaybackView}.
  * <p>
- * This class is not thread safe. The thread policy for this class is
- * thread-confinement, all calls into this class from outside must be done from
- * the main ui thread.
+ * This class is not thread safe. The thread policy for this class is thread-confinement, all calls
+ * into this class from outside must be done from the main UI thread.
  */
 @NotThreadSafe
 @VisibleForTesting
-public class VoicemailPlaybackPresenter implements OnAudioFocusChangeListener {
-    /** The stream used to playback voicemail. */
-    private static final int PLAYBACK_STREAM = AudioManager.STREAM_VOICE_CALL;
+public class VoicemailPlaybackPresenter
+        implements OnAudioFocusChangeListener, MediaPlayer.OnPreparedListener,
+                MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {
+
+    private static final String TAG = VoicemailPlaybackPresenter.class.getSimpleName();
 
     /** Contract describing the behaviour we need from the ui we are controlling. */
     public interface PlaybackView {
-        Context getDataSourceContext();
-        void runOnUiThread(Runnable runnable);
-        void setStartStopListener(View.OnClickListener listener);
-        void setPositionSeekListener(SeekBar.OnSeekBarChangeListener listener);
-        void setSpeakerphoneListener(View.OnClickListener listener);
-        void setIsBuffering();
-        void setClipPosition(int clipPositionInMillis, int clipLengthInMillis);
         int getDesiredClipPosition();
-        void playbackStarted();
-        void playbackStopped();
-        void playbackError(Exception e);
-        boolean isSpeakerPhoneOn();
-        void setSpeakerPhoneOn(boolean on);
-        void finish();
-        void setIsFetchingContent();
         void disableUiElements();
         void enableUiElements();
-        void sendFetchVoicemailRequest(Uri voicemailUri);
-        boolean queryHasContent(Uri voicemailUri);
+        void onPlaybackError(Exception e);
+        void onPlaybackStarted(MediaPlayer mediaPlayer, int duration,
+                ScheduledExecutorService executorService);
+        void onPlaybackStopped();
+        void setClipPosition(int clipPositionInMillis, int clipLengthInMillis);
         void setFetchContentTimeout();
-        void registerContentObserver(Uri uri, ContentObserver observer);
-        void unregisterContentObserver(ContentObserver observer);
-        void enableProximitySensor();
-        void disableProximitySensor();
-        void setVolumeControlStream(int streamType);
+        void setIsBuffering();
+        void setIsFetchingContent();
+        void setPresenter(VoicemailPlaybackPresenter presenter);
     }
 
     /** The enumeration of {@link AsyncTask} objects we use in this class. */
     public enum Tasks {
         CHECK_FOR_CONTENT,
         CHECK_CONTENT_AFTER_CHANGE,
-        PREPARE_MEDIA_PLAYER,
-        RESET_PREPARE_START_MEDIA_PLAYER,
     }
 
-    /** Update rate for the slider, 30fps. */
-    private static final int SLIDER_UPDATE_PERIOD_MILLIS = 1000 / 30;
-    /** Time our ui will wait for content to be fetched before reporting not available. */
+    private static final String[] HAS_CONTENT_PROJECTION = new String[] {
+        VoicemailContract.Voicemails.HAS_CONTENT,
+    };
+
+    private static final int PLAYBACK_STREAM = AudioManager.STREAM_VOICE_CALL;
+    private static final int NUMBER_OF_THREADS_IN_POOL = 2;
+    // Time to wait for content to be fetched before timing out.
     private static final long FETCH_CONTENT_TIMEOUT_MS = 20000;
-    /**
-     * If present in the saved instance bundle, we should not resume playback on
-     * create.
-     */
-    private static final String IS_PLAYING_STATE_KEY = VoicemailPlaybackPresenter.class.getName()
-            + ".IS_PLAYING_STATE_KEY";
-    /**
-     * If present in the saved instance bundle, indicates where to set the
-     * playback slider.
-     */
-    private static final String CLIP_POSITION_KEY = VoicemailPlaybackPresenter.class.getName()
-            + ".CLIP_POSITION_KEY";
+
+    // If present in the saved instance bundle, we should not resume playback on create.
+    private static final String IS_PLAYING_STATE_KEY =
+            VoicemailPlaybackPresenter.class.getName() + ".IS_PLAYING_STATE_KEY";
+    // If present in the saved instance bundle, indicates where to set the playback slider.
+    private static final String CLIP_POSITION_KEY =
+            VoicemailPlaybackPresenter.class.getName() + ".CLIP_POSITION_KEY";
 
     /**
      * The most recently calculated duration.
@@ -127,45 +119,108 @@
      */
     private final AtomicInteger mDuration = new AtomicInteger(0);
 
-    private final PlaybackView mView;
-    private final MediaPlayerProxy mPlayer;
-    private final PositionUpdater mPositionUpdater;
+    private Context mContext;
+    private MediaPlayer mMediaPlayer;
+    private PlaybackView mView;
 
-    /** Voicemail uri to play. */
-    private final Uri mVoicemailUri;
-    /** Start playing in onCreate iff this is true. */
-    private final boolean mStartPlayingImmediately;
-    /** Used to run async tasks that need to interact with the ui. */
+    private Uri mVoicemailUri;
+    private int mPosition;
+    private boolean mIsPrepared;
+    private boolean mIsPlaying;
+    private boolean mShouldResumePlaybackAfterSeeking;
+
+    // Used to run async tasks that need to interact with the UI.
     private final AsyncTaskExecutor mAsyncTaskExecutor;
-
+    private static ScheduledExecutorService mScheduledExecutorService;
     /**
      * Used to handle the result of a successful or time-out fetch result.
      * <p>
      * This variable is thread-contained, accessed only on the ui thread.
      */
     private FetchResultHandler mFetchResultHandler;
-    private PowerManager.WakeLock mWakeLock;
-    private AsyncTask<Void, ?, ?> mPrepareTask;
-    private int mPosition;
-    private boolean mPlaying;
+    private PowerManager.WakeLock mProximityWakeLock;
     private AudioManager mAudioManager;
 
-    public VoicemailPlaybackPresenter(PlaybackView view, MediaPlayerProxy player,
-            Uri voicemailUri, ScheduledExecutorService executorService,
-            boolean startPlayingImmediately, AsyncTaskExecutor asyncTaskExecutor,
-            PowerManager.WakeLock wakeLock) {
-        mView = view;
-        mPlayer = player;
-        mVoicemailUri = voicemailUri;
-        mStartPlayingImmediately = startPlayingImmediately;
-        mAsyncTaskExecutor = asyncTaskExecutor;
-        mPositionUpdater = new PositionUpdater(executorService, SLIDER_UPDATE_PERIOD_MILLIS);
-        mWakeLock = wakeLock;
+    public VoicemailPlaybackPresenter(Activity activity) {
+        mContext = activity;
+        mAsyncTaskExecutor = AsyncTaskExecutors.createAsyncTaskExecutor();
+        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+
+        PowerManager powerManager =
+                (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        if (powerManager.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
+            mProximityWakeLock = powerManager.newWakeLock(
+                    PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG);
+        }
+
+        if (mMediaPlayer == null) {
+            mMediaPlayer = new MediaPlayer();
+            mMediaPlayer.setOnPreparedListener(this);
+            mMediaPlayer.setOnErrorListener(this);
+            mMediaPlayer.setOnCompletionListener(this);
+        }
+
+        activity.setVolumeControlStream(PLAYBACK_STREAM);
     }
 
-    public void onCreate(Bundle bundle) {
-        mView.setVolumeControlStream(PLAYBACK_STREAM);
-        checkThatWeHaveContent();
+    /**
+     * Specify the view which this presenter controls and the voicemail for playback.
+     */
+    public void setPlaybackView(
+            PlaybackView view, Uri voicemailUri, boolean startPlayingImmediately) {
+        mView = view;
+        mVoicemailUri = voicemailUri;
+
+        mView.setPresenter(this);
+
+        if (!mMediaPlayer.isPlaying()) {
+            setPosition(0, startPlayingImmediately);
+            mIsPrepared = false;
+        }
+        checkForContent();
+    }
+
+    public void onPause(boolean isFinishing) {
+        // Do not pause for orientation changes.
+        if (mMediaPlayer.isPlaying() && isFinishing) {
+            pausePlayback(mMediaPlayer.getCurrentPosition(), mIsPlaying);
+        }
+
+        disableProximitySensor(false /* waitForFarState */);
+    }
+
+    public void onDestroy(boolean isFinishing) {
+        // Do not release for orientation changes.
+        if (mIsPrepared && isFinishing) {
+            mMediaPlayer.release();
+            mIsPrepared = false;
+        }
+
+        if (mScheduledExecutorService != null) {
+            mScheduledExecutorService.shutdown();
+            mScheduledExecutorService = null;
+        }
+
+        if (mFetchResultHandler != null) {
+            mFetchResultHandler.destroy();
+            mFetchResultHandler = null;
+        }
+
+        disableProximitySensor(false /* waitForFarState */);
+    }
+
+    public void onSaveInstanceState(Bundle outState) {
+        outState.putInt(CLIP_POSITION_KEY, mView.getDesiredClipPosition());
+        outState.putBoolean(IS_PLAYING_STATE_KEY, mIsPlaying);
+    }
+
+    public void onRestoreInstanceState(Bundle inState) {
+        if (inState != null) {
+            int position = inState.getInt(CLIP_POSITION_KEY, 0);
+            boolean isPlaying = inState.getBoolean(IS_PLAYING_STATE_KEY, false);
+            // Playback will be automatically resumed, if appropriate, in onPrepared().
+            setPosition(position, isPlaying);
+        }
     }
 
     /**
@@ -174,30 +229,44 @@
      * This method will be called once, after the fragment has been created, before we know if the
      * voicemail we've been asked to play has any content available.
      * <p>
-     * This method will notify the user through the ui that we are fetching the content, then check
-     * to see if the content field in the db is set. If set, we proceed to
-     * {@link #postSuccessfullyFetchedContent()} method. If not set, we will make a request to fetch
-     * the content asynchronously via {@link #makeRequestForContent()}.
+     * Notify the user that we are fetching the content, then check to see if the content field in
+     * the DB is set. If set, we proceed to {@link #prepareToPlayContent()} method. If not set, make
+     * a request to fetch the content asynchronously via {@link #requestContent()}.
      */
-    private void checkThatWeHaveContent() {
+    private void checkForContent() {
         mView.setIsFetchingContent();
         mAsyncTaskExecutor.submit(Tasks.CHECK_FOR_CONTENT, new AsyncTask<Void, Void, Boolean>() {
             @Override
             public Boolean doInBackground(Void... params) {
-                return mView.queryHasContent(mVoicemailUri);
+                return queryHasContent(mVoicemailUri);
             }
 
             @Override
             public void onPostExecute(Boolean hasContent) {
                 if (hasContent) {
-                    postSuccessfullyFetchedContent();
+                    prepareToPlayContent();
                 } else {
-                    makeRequestForContent();
+                    requestContent();
                 }
             }
         });
     }
 
+    private boolean queryHasContent(Uri voicemailUri) {
+        ContentResolver contentResolver = mContext.getContentResolver();
+        Cursor cursor = contentResolver.query(
+                voicemailUri, HAS_CONTENT_PROJECTION, null, null, null);
+        try {
+            if (cursor != null && cursor.moveToNext()) {
+                return cursor.getInt(cursor.getColumnIndexOrThrow(
+                        VoicemailContract.Voicemails.HAS_CONTENT)) == 1;
+            }
+        } finally {
+            MoreCloseables.closeQuietly(cursor);
+        }
+        return false;
+    }
+
     /**
      * Makes a broadcast request to ask that a voicemail source fetch this content.
      * <p>
@@ -207,17 +276,22 @@
      * will trigger a broadcast to request that the content be downloaded. It will add a listener to
      * the content resolver so that it will be notified when the has_content field changes. It will
      * also set a timer. If the has_content field changes to true within the allowed time, we will
-     * proceed to {@link #postSuccessfullyFetchedContent()}. If the has_content field does not
+     * proceed to {@link #prepareToPlayContent()}. If the has_content field does not
      * become true within the allowed time, we will update the ui to reflect the fact that content
      * was not available.
      */
-    private void makeRequestForContent() {
-        Handler handler = new Handler();
+    private void requestContent() {
         Preconditions.checkState(mFetchResultHandler == null, "mFetchResultHandler should be null");
+
+        Handler handler = new Handler();
         mFetchResultHandler = new FetchResultHandler(handler);
-        mView.registerContentObserver(mVoicemailUri, mFetchResultHandler);
+        mContext.getContentResolver().registerContentObserver(
+                mVoicemailUri, false, mFetchResultHandler);
         handler.postDelayed(mFetchResultHandler.getTimeoutRunnable(), FETCH_CONTENT_TIMEOUT_MS);
-        mView.sendFetchVoicemailRequest(mVoicemailUri);
+
+        // Send voicemail fetch request.
+        Intent intent = new Intent(VoicemailContract.ACTION_FETCH_VOICEMAIL, mVoicemailUri);
+        mContext.sendBroadcast(intent);
     }
 
     @ThreadSafe
@@ -237,14 +311,14 @@
         @Override
         public void run() {
             if (mResultStillPending.getAndSet(false)) {
-                mView.unregisterContentObserver(FetchResultHandler.this);
+                mContext.getContentResolver().unregisterContentObserver(FetchResultHandler.this);
                 mView.setFetchContentTimeout();
             }
         }
 
         public void destroy() {
             if (mResultStillPending.getAndSet(false)) {
-                mView.unregisterContentObserver(FetchResultHandler.this);
+                mContext.getContentResolver().unregisterContentObserver(FetchResultHandler.this);
                 mHandler.removeCallbacks(this);
             }
         }
@@ -255,15 +329,16 @@
                     new AsyncTask<Void, Void, Boolean>() {
                 @Override
                 public Boolean doInBackground(Void... params) {
-                    return mView.queryHasContent(mVoicemailUri);
+                    return queryHasContent(mVoicemailUri);
                 }
 
                 @Override
                 public void onPostExecute(Boolean hasContent) {
                     if (hasContent) {
                         if (mResultStillPending.getAndSet(false)) {
-                            mView.unregisterContentObserver(FetchResultHandler.this);
-                            postSuccessfullyFetchedContent();
+                            mContext.getContentResolver().unregisterContentObserver(
+                                    FetchResultHandler.this);
+                            prepareToPlayContent();
                         }
                     }
                 }
@@ -275,378 +350,205 @@
      * Prepares the voicemail content for playback.
      * <p>
      * This method will be called once we know that our voicemail has content (according to the
-     * content provider). This method will try to prepare the data source through the media player.
-     * If preparing the media player works, we will call through to
-     * {@link #postSuccessfulPrepareActions()}. If preparing the media player fails (perhaps the
-     * file the content provider points to is actually missing, perhaps it is of an unknown file
-     * format that we can't play, who knows) then we will show an error on the ui.
+     * content provider). this method asynchronously tries to prepare the data source through the
+     * media player. If preparation is successful, the media player will {@link #onPrepared()},
+     * and it will call {@link #onError()} otherwise.
      */
-    private void postSuccessfullyFetchedContent() {
+    private void prepareToPlayContent() {
         mView.setIsBuffering();
-        mAsyncTaskExecutor.submit(Tasks.PREPARE_MEDIA_PLAYER,
-                new AsyncTask<Void, Void, Exception>() {
-                    @Override
-                    public Exception doInBackground(Void... params) {
-                        try {
-                            mPlayer.reset();
-                            mPlayer.setDataSource(mView.getDataSourceContext(), mVoicemailUri);
-                            mPlayer.setAudioStreamType(PLAYBACK_STREAM);
-                            mPlayer.prepare();
-                            mDuration.set(mPlayer.getDuration());
-                            return null;
-                        } catch (Exception e) {
-                            return e;
-                        }
-                    }
 
-                    @Override
-                    public void onPostExecute(Exception exception) {
-                        if (exception == null) {
-                            postSuccessfulPrepareActions();
-                        } else {
-                            mView.playbackError(exception);
-                        }
-                    }
-                });
+        try {
+            mMediaPlayer.reset();
+            mMediaPlayer.setDataSource(mContext, mVoicemailUri);
+            mMediaPlayer.setAudioStreamType(PLAYBACK_STREAM);
+            mMediaPlayer.prepareAsync();
+        } catch (IOException e) {
+            handleError(e);
+        }
     }
 
     /**
-     * Enables the ui, and optionally starts playback immediately.
-     * <p>
-     * This will be called once we have successfully prepared the media player, and will optionally
-     * playback immediately.
+     * Once the media player is prepared, enables the UI and adopts the appropriate playback state.
      */
-    private void postSuccessfulPrepareActions() {
+    @Override
+    public void onPrepared(MediaPlayer mp) {
+        mIsPrepared = true;
+
         mView.enableUiElements();
-        mView.setPositionSeekListener(new PlaybackPositionListener());
-        mView.setStartStopListener(new StartStopButtonListener());
-        mView.setSpeakerphoneListener(new SpeakerphoneListener());
-        mPlayer.setOnErrorListener(new MediaPlayerErrorListener());
-        mPlayer.setOnCompletionListener(new MediaPlayerCompletionListener());
-        mView.setSpeakerPhoneOn(mView.isSpeakerPhoneOn());
-        if (mPlaying) {
-           resetPrepareStartPlaying(mPosition);
+
+        if (mIsPlaying) {
+            resumePlayback();
         } else {
-           stopPlaybackAtPosition(mPosition, mDuration.get());
-           if ((mPosition == 0) && (mStartPlayingImmediately)) {
-               resetPrepareStartPlaying(0);
-           }
+            pausePlayback();
         }
     }
 
-    public void onSaveInstanceState(Bundle outState) {
-        outState.putInt(CLIP_POSITION_KEY, mView.getDesiredClipPosition());
-        outState.putBoolean(IS_PLAYING_STATE_KEY, mPlaying);
+    /**
+     * Invoked if preparing the media player fails, for example, if file is missing or the voicemail
+     * is an unknown file format that can't be played.
+     */
+    @Override
+    public boolean onError(MediaPlayer mp, int what, int extra) {
+        handleError(new IllegalStateException("MediaPlayer error listener invoked"));
+        return true;
     }
 
-    public void onRestoreInstanceState(Bundle inState) {
-        int position = 0;
-        boolean isPlaying = false;
-        if (inState != null) {
-            position = inState.getInt(CLIP_POSITION_KEY, 0);
-            isPlaying = inState.getBoolean(IS_PLAYING_STATE_KEY, false);
+    private void handleError(Exception e) {
+        if (mIsPrepared) {
+            mMediaPlayer.release();
+            mIsPrepared = false;
         }
-        setPositionAndPlayingStatus(position, isPlaying) ;
+
+        mView.onPlaybackError(e);
+        setPosition(0, false);
     }
 
-    private void setPositionAndPlayingStatus(int position, boolean isPlaying) {
-       mPosition = position;
-       mPlaying = isPlaying;
-    }
-
-    public void onDestroy() {
-        if (mPrepareTask != null) {
-            mPrepareTask.cancel(false);
-            mPrepareTask = null;
-        }
-        mPlayer.release();
-        if (mFetchResultHandler != null) {
-            mFetchResultHandler.destroy();
-            mFetchResultHandler = null;
-        }
-        mPositionUpdater.stopUpdating();
-        if (mWakeLock.isHeld()) {
-            mWakeLock.release();
-        }
-    }
-
-    private class MediaPlayerErrorListener implements MediaPlayer.OnErrorListener {
-        @Override
-        public boolean onError(MediaPlayer mp, int what, int extra) {
-            mView.runOnUiThread(new Runnable() {
-                @Override
-                public void run() {
-                    handleError(new IllegalStateException("MediaPlayer error listener invoked"));
-                }
-            });
-            return true;
-        }
-    }
-
-    private class MediaPlayerCompletionListener implements MediaPlayer.OnCompletionListener {
-        @Override
-        public void onCompletion(final MediaPlayer mp) {
-            mView.runOnUiThread(new Runnable() {
-                @Override
-                public void run() {
-                    handleCompletion(mp);
-                }
-            });
-        }
-    }
-
-    private class AsyncPrepareTask extends AsyncTask<Void, Void, Exception> {
-        private int mClipPositionInMillis;
-
-        AsyncPrepareTask(int clipPositionInMillis) {
-            mClipPositionInMillis = clipPositionInMillis;
-        }
-
-        @Override
-        public Exception doInBackground(Void... params) {
-            try {
-                mPlayer.reset();
-                mPlayer.setDataSource(mView.getDataSourceContext(), mVoicemailUri);
-                mPlayer.setAudioStreamType(PLAYBACK_STREAM);
-                mPlayer.prepare();
-                return null;
-            } catch (Exception e) {
-                return e;
-            }
-        }
-
-        @Override
-        public void onPostExecute(Exception exception) {
-            mPrepareTask = null;
-            if (exception == null) {
-                final int duration = mPlayer.getDuration();
-                mDuration.set(duration);
-                int startPosition =
-                    constrain(mClipPositionInMillis, 0, duration);
-                mPlayer.seekTo(startPosition);
-                mView.setClipPosition(startPosition, duration);
-                try {
-                    // Grab audio focus here
-                    int result = getAudioManager().requestAudioFocus(
-                            VoicemailPlaybackPresenter.this,
-                            PLAYBACK_STREAM,
-                            AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
-
-                    if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
-                        throw new RejectedExecutionException("Could not capture audio focus.");
-                    }
-                    // Can throw RejectedExecutionException
-                    mPlayer.start();
-                    setPositionAndPlayingStatus(mPlayer.getCurrentPosition(), true);
-                    mView.playbackStarted();
-                    if (!mWakeLock.isHeld()) {
-                        mWakeLock.acquire();
-                    }
-                    // Only enable if we are not currently using the speaker phone.
-                    if (!mView.isSpeakerPhoneOn()) {
-                        mView.enableProximitySensor();
-                    }
-                    // Can throw RejectedExecutionException
-                    mPositionUpdater.startUpdating(startPosition, duration);
-                } catch (RejectedExecutionException e) {
-                    handleError(e);
-                }
-            } else {
-                handleError(exception);
-            }
-        }
-    }
-
-    private AudioManager getAudioManager() {
-        if (mAudioManager == null) {
-            mAudioManager = (AudioManager)
-                    mView.getDataSourceContext().getSystemService(Context.AUDIO_SERVICE);
-        }
-        return mAudioManager;
+    /**
+     * After done playing the voicemail clip, reset the clip position to the start.
+     */
+    @Override
+    public void onCompletion(MediaPlayer mediaPlayer) {
+        pausePlayback(0, false);
     }
 
     @Override
     public void onAudioFocusChange(int focusChange) {
         boolean lostFocus = focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT ||
                 focusChange == AudioManager.AUDIOFOCUS_LOSS;
-        // Note: the below logic is the same as in {@code StartStopButtonListener}.
-        if (mPlayer.isPlaying() && lostFocus) {
-            setPositionAndPlayingStatus(mPlayer.getCurrentPosition(), false);
-            stopPlaybackAtPosition(mPlayer.getCurrentPosition(), mDuration.get());
-        } else if (!mPlayer.isPlaying() && focusChange == AudioManager.AUDIOFOCUS_GAIN) {
-            setPositionAndPlayingStatus(mPosition, true);
-            postSuccessfullyFetchedContent();
-        }
-    }
-
-
-    private void resetPrepareStartPlaying(final int clipPositionInMillis) {
-        if (mPrepareTask != null) {
-            mPrepareTask.cancel(false);
-            mPrepareTask = null;
-        }
-        mPrepareTask = mAsyncTaskExecutor.submit(Tasks.RESET_PREPARE_START_MEDIA_PLAYER,
-                new AsyncPrepareTask(clipPositionInMillis));
-    }
-
-    private void handleError(Exception e) {
-        mView.playbackError(e);
-        mPositionUpdater.stopUpdating();
-        mPlayer.release();
-        setPositionAndPlayingStatus(0, false);
-    }
-
-    public void handleCompletion(MediaPlayer mediaPlayer) {
-        stopPlaybackAtPosition(0, mDuration.get());
-    }
-
-    private void stopPlaybackAtPosition(int clipPosition, int duration) {
-        getAudioManager().abandonAudioFocus(this);
-        mPositionUpdater.stopUpdating();
-        mView.playbackStopped();
-        if (mWakeLock.isHeld()) {
-            mWakeLock.release();
-        }
-        // Always disable on stop.
-        mView.disableProximitySensor();
-        mView.setClipPosition(clipPosition, duration);
-        if (mPlayer.isPlaying()) {
-            mPlayer.pause();
-        }
-    }
-
-    private class PlaybackPositionListener implements SeekBar.OnSeekBarChangeListener {
-        private boolean mShouldResumePlaybackAfterSeeking;
-
-        @Override
-        public void onStartTrackingTouch(SeekBar arg0) {
-            if (mPlayer.isPlaying()) {
-                mShouldResumePlaybackAfterSeeking = true;
-                stopPlaybackAtPosition(mPlayer.getCurrentPosition(), mDuration.get());
-            } else {
-                mShouldResumePlaybackAfterSeeking = false;
-            }
-        }
-
-        @Override
-        public void onStopTrackingTouch(SeekBar arg0) {
-            if (mPlayer.isPlaying()) {
-                setPositionAndPlayingStatus(mPlayer.getCurrentPosition(), false);
-                stopPlaybackAtPosition(mPlayer.getCurrentPosition(), mDuration.get());
-            } else {
-                setPositionAndPlayingStatus(mView.getDesiredClipPosition(),
-                        mShouldResumePlaybackAfterSeeking);
-            }
-
-            if (mShouldResumePlaybackAfterSeeking) {
-                postSuccessfullyFetchedContent();
-            }
-        }
-
-        @Override
-        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
-            mView.setClipPosition(seekBar.getProgress(), seekBar.getMax());
-        }
-    }
-
-    private class SpeakerphoneListener implements View.OnClickListener {
-        @Override
-        public void onClick(View v) {
-            boolean previousState = mView.isSpeakerPhoneOn();
-            mView.setSpeakerPhoneOn(!previousState);
-            if (mPlayer.isPlaying() && previousState) {
-                // If we are currently playing and we are disabling the speaker phone, enable the
-                // sensor.
-                mView.enableProximitySensor();
-            } else {
-                // If we are not currently playing, disable the sensor.
-                mView.disableProximitySensor();
-            }
-        }
-    }
-
-    private class StartStopButtonListener implements View.OnClickListener {
-        @Override
-        public void onClick(View arg0) {
-            if (mPlayer.isPlaying()) {
-                setPositionAndPlayingStatus(mPlayer.getCurrentPosition(), false);
-                stopPlaybackAtPosition(mPlayer.getCurrentPosition(), mDuration.get());
-            } else {
-                setPositionAndPlayingStatus(mPosition, true);
-                postSuccessfullyFetchedContent();
-            }
+        if (mMediaPlayer.isPlaying() && lostFocus) {
+            pausePlayback();
+        } else if (!mMediaPlayer.isPlaying() && focusChange == AudioManager.AUDIOFOCUS_GAIN) {
+            resumePlayback();
         }
     }
 
     /**
-     * Controls the animation of the playback slider.
+     * Sets the position and playing state for when playback is resumed.
      */
-    @ThreadSafe
-    private final class PositionUpdater implements Runnable {
-        private final ScheduledExecutorService mExecutorService;
-        private final int mPeriodMillis;
-        private final Object mLock = new Object();
-        @GuardedBy("mLock") private ScheduledFuture<?> mScheduledFuture;
-        private final Runnable mSetClipPostitionRunnable = new Runnable() {
-            @Override
-            public void run() {
-                int currentPosition = 0;
-                synchronized (mLock) {
-                    if (mScheduledFuture == null) {
-                        // This task has been canceled. Just stop now.
-                        return;
-                    }
-                    currentPosition = mPlayer.getCurrentPosition();
-                }
-                mView.setClipPosition(currentPosition, mDuration.get());
+    private void setPosition(int position, boolean isPlaying) {
+        mPosition = position;
+        mIsPlaying = isPlaying;
+    }
+
+    /**
+     * Resumes voicemail playback at the clip position stored by the presenter.
+     */
+    public void resumePlayback() {
+        final int duration = mMediaPlayer.getDuration();
+        mDuration.set(duration);
+
+        // Clamp the start position between 0 and the duration.
+        int startPosition = Math.max(0, Math.min(mPosition, duration));
+        mMediaPlayer.seekTo(startPosition);
+        setPosition(startPosition, true);
+
+        try {
+            // Grab audio focus here
+            int result = mAudioManager.requestAudioFocus(
+                    VoicemailPlaybackPresenter.this,
+                    PLAYBACK_STREAM,
+                    AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+
+            if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
+                throw new RejectedExecutionException("Could not capture audio focus.");
             }
-        };
 
-        public PositionUpdater(ScheduledExecutorService executorService, int periodMillis) {
-            mExecutorService = executorService;
-            mPeriodMillis = periodMillis;
-        }
+            // Can throw RejectedExecutionException
+            mMediaPlayer.start();
 
-        @Override
-        public void run() {
-            mView.runOnUiThread(mSetClipPostitionRunnable);
-        }
-
-        public void startUpdating(int beginPosition, int endPosition) {
-            synchronized (mLock) {
-                if (mScheduledFuture != null) {
-                    mScheduledFuture.cancel(false);
-                    mScheduledFuture = null;
-                }
-                mScheduledFuture = mExecutorService.scheduleAtFixedRate(this, 0, mPeriodMillis,
-                        TimeUnit.MILLISECONDS);
-            }
-        }
-
-        public void stopUpdating() {
-            synchronized (mLock) {
-                if (mScheduledFuture != null) {
-                    mScheduledFuture.cancel(false);
-                    mScheduledFuture = null;
-                }
-            }
+            mView.onPlaybackStarted(mMediaPlayer, duration, getScheduledExecutorServiceInstance());
+            enableProximitySensor();
+        } catch (RejectedExecutionException e) {
+            handleError(e);
         }
     }
 
-    public void onPause() {
-        if (mPlayer.isPlaying()) {
-            stopPlaybackAtPosition(mPlayer.getCurrentPosition(), mDuration.get());
+    public void pausePlayback() {
+        pausePlayback(mMediaPlayer.getCurrentPosition(), false);
+    }
+
+    /**
+     * {@link isPlaying} may be set to {@code true} so voicemail playback can be resumed after a
+     * rotation.
+     */
+    private void pausePlayback(int position, boolean isPlaying) {
+        setPosition(position, isPlaying);
+
+        if (mMediaPlayer.isPlaying()) {
+            mMediaPlayer.pause();
         }
-        if (mPrepareTask != null) {
-            mPrepareTask.cancel(false);
-            mPrepareTask = null;
+
+        mAudioManager.abandonAudioFocus(this);
+        mView.onPlaybackStopped();
+
+        // Always disable the proximity sensor on stop.
+        disableProximitySensor(true /* waitForFarState */);
+
+        int duration = mDuration.get();
+        mView.setClipPosition(position, duration);
+    }
+
+    /**
+     * Pauses playback when the user starts seeking the position, and notes whether the voicemail is
+     * playing to know whether to resume playback once the user selects a new position.
+     */
+    public void pausePlaybackForSeeking() {
+        mShouldResumePlaybackAfterSeeking = mMediaPlayer.isPlaying();
+        pausePlayback();
+    }
+
+    public void resumePlaybackAfterSeeking(int desiredPosition) {
+        setPosition(desiredPosition, mShouldResumePlaybackAfterSeeking);
+        if (mShouldResumePlaybackAfterSeeking) {
+            resumePlayback();
         }
-        if (mWakeLock.isHeld()) {
-            mWakeLock.release();
+        mShouldResumePlaybackAfterSeeking = false;
+    }
+
+    private void enableProximitySensor() {
+        if (mProximityWakeLock == null || isSpeakerphoneOn() || !mMediaPlayer.isPlaying()) {
+            return;
+        }
+
+        if (!mProximityWakeLock.isHeld()) {
+            Log.i(TAG, "Acquiring proximity wake lock");
+            mProximityWakeLock.acquire();
+        } else {
+            Log.i(TAG, "Proximity wake lock already acquired");
         }
     }
 
-    private static int constrain(int amount, int low, int high) {
-        return amount < low ? low : (amount > high ? high : amount);
+    private void disableProximitySensor(boolean waitForFarState) {
+        if (mProximityWakeLock == null) {
+            return;
+        }
+        if (mProximityWakeLock.isHeld()) {
+            Log.i(TAG, "Releasing proximity wake lock");
+            int flags = waitForFarState ? PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY : 0;
+            mProximityWakeLock.release(flags);
+        } else {
+            Log.i(TAG, "Proximity wake lock already released");
+        }
     }
+
+    public void setSpeakerphoneOn(boolean on) {
+        mAudioManager.setSpeakerphoneOn(on);
+        if (on) {
+            disableProximitySensor(false /* waitForFarState */);
+        } else {
+            enableProximitySensor();
+        }
+    }
+
+    public boolean isSpeakerphoneOn() {
+        return mAudioManager.isSpeakerphoneOn();
+    }
+
+    private static synchronized ScheduledExecutorService getScheduledExecutorServiceInstance() {
+        if (mScheduledExecutorService == null) {
+            mScheduledExecutorService = Executors.newScheduledThreadPool(NUMBER_OF_THREADS_IN_POOL);
+        }
+        return mScheduledExecutorService;
+    }
+
 }
diff --git a/tests/assets/README.txt b/tests/assets/README.txt
new file mode 100644
index 0000000..6cea058
--- /dev/null
+++ b/tests/assets/README.txt
@@ -0,0 +1,3 @@
+quick_test_recording.mp3 is copyright 2011 by Hugo Hudson and is licensed under a
+Creative Commons Attribution 3.0 Unported License:
+  http://creativecommons.org/licenses/by/3.0/
diff --git a/tests/assets/quick_test_recording.mp3 b/tests/assets/quick_test_recording.mp3
new file mode 100644
index 0000000..ad7cb9c
--- /dev/null
+++ b/tests/assets/quick_test_recording.mp3
Binary files differ
diff --git a/tests/src/com/android/dialer/CallDetailActivityTest.java b/tests/src/com/android/dialer/CallDetailActivityTest.java
index aca8f29..97b1b09 100644
--- a/tests/src/com/android/dialer/CallDetailActivityTest.java
+++ b/tests/src/com/android/dialer/CallDetailActivityTest.java
@@ -18,7 +18,6 @@
 
 import static com.android.dialer.calllog.CallLogAsyncTaskUtil.Tasks.GET_CALL_DETAILS;
 import static com.android.dialer.voicemail.VoicemailPlaybackPresenter.Tasks.CHECK_FOR_CONTENT;
-import static com.android.dialer.voicemail.VoicemailPlaybackPresenter.Tasks.PREPARE_MEDIA_PLAYER;
 
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -34,12 +33,12 @@
 import android.view.Menu;
 import android.widget.TextView;
 
+import com.android.dialer.calllog.CallLogAsyncTaskUtil;
 import com.android.dialer.util.AsyncTaskExecutors;
 import com.android.dialer.util.FakeAsyncTaskExecutor;
 import com.android.contacts.common.test.IntegrationTestUtils;
 import com.android.dialer.util.LocaleTestUtils;
 import com.android.internal.view.menu.ContextMenuBuilder;
-import com.google.common.io.Closeables;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -91,37 +90,37 @@
         cleanUpUri();
         mTestUtils = null;
         AsyncTaskExecutors.setFactoryForTest(null);
+        CallLogAsyncTaskUtil.resetForTest();
         super.tearDown();
     }
 
     public void testInitialActivityStartsWithFetchingVoicemail() throws Throwable {
-        setActivityIntentForTestVoicemailEntry();
+        setActivityIntentForRealFileVoicemailEntry();
         startActivityUnderTest();
-        // When the activity first starts, we will show "Fetching voicemail" on the screen.
+        // When the activity first starts, we will show "Loading voicemail" on the screen.
         // The duration should not be visible.
-        assertHasOneTextViewContaining("Fetching voicemail");
+        assertHasOneTextViewContaining("Loading voicemail");
         assertZeroTextViewsContaining("00:00");
     }
 
-    public void testWhenCheckForContentCompletes_UiShowsBuffering() throws Throwable {
-        setActivityIntentForTestVoicemailEntry();
+    public void testWhenCheckForContentCompletes() throws Throwable {
+        setActivityIntentForRealFileVoicemailEntry();
         startActivityUnderTest();
         // There is a background check that is testing to see if we have the content available.
-        // Once that task completes, we shouldn't be showing the fetching message, we should
-        // be showing "Buffering".
+        // Once that task completes, we shouldn't be showing the fetching message.
         mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
-        assertHasOneTextViewContaining("Buffering");
-        assertZeroTextViewsContaining("Fetching voicemail");
+
+        // The voicemail async call may or may not return before we check the asserts.
+        assertHasOneTextViewContaining("Buffering", "00:00");
+        assertZeroTextViewsContaining("Loading voicemail");
     }
 
     public void testInvalidVoicemailShowsErrorMessage() throws Throwable {
         setActivityIntentForTestVoicemailEntry();
         startActivityUnderTest();
         mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
-        // There should be exactly one background task ready to prepare the media player.
-        // Preparing the media player will have thrown an IOException since the file doesn't exist.
+        // The media player will have thrown an IOException since the file doesn't exist.
         // This should have put a failed to play message on screen, buffering is gone.
-        mFakeAsyncTaskExecutor.runTask(PREPARE_MEDIA_PLAYER);
         assertHasOneTextViewContaining("Couldn't play voicemail");
         assertZeroTextViewsContaining("Buffering");
     }
@@ -129,7 +128,7 @@
     public void testOnResumeDoesNotCreateManyFragments() throws Throwable {
         // There was a bug where every time the activity was resumed, a new fragment was created.
         // Before the fix, this was failing reproducibly with at least 3 "Buffering" views.
-        setActivityIntentForTestVoicemailEntry();
+        setActivityIntentForRealFileVoicemailEntry();
         startActivityUnderTest();
         mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
         getInstrumentation().runOnMainSync(new Runnable() {
@@ -141,7 +140,7 @@
                 getInstrumentation().callActivityOnResume(mActivityUnderTest);
             }
         });
-        assertHasOneTextViewContaining("Buffering");
+        assertHasOneTextViewContaining("Buffering", "00:00");
     }
 
     /**
@@ -192,7 +191,6 @@
         setActivityIntentForRealFileVoicemailEntry();
         startActivityUnderTest();
         mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
-        mFakeAsyncTaskExecutor.runTask(PREPARE_MEDIA_PLAYER);
         mTestUtils.clickButton(mActivityUnderTest, R.id.playback_speakerphone);
         mTestUtils.clickButton(mActivityUnderTest, R.id.playback_start_stop);
         Thread.sleep(2000);
@@ -219,6 +217,7 @@
         values.put(VoicemailContract.Voicemails.HAS_CONTENT, 1);
         values.put(VoicemailContract.Voicemails._DATA, VOICEMAIL_FILE_LOCATION);
         mVoicemailUri = contentResolver.insert(VoicemailContract.Voicemails.CONTENT_URI, values);
+
         Uri callLogUri = ContentUris.withAppendedId(CallLog.Calls.CONTENT_URI_WITH_VOICEMAIL,
                 ContentUris.parseId(mVoicemailUri));
         Intent intent = new Intent(Intent.ACTION_VIEW, callLogUri);
@@ -237,15 +236,9 @@
         mVoicemailUri = getContentResolver().insert(
                 VoicemailContract.Voicemails.buildSourceUri(packageName), values);
         AssetManager assets = getAssets();
-        OutputStream outputStream = null;
-        InputStream inputStream = null;
-        try {
-            inputStream = assets.open(TEST_ASSET_NAME);
-            outputStream = getContentResolver().openOutputStream(mVoicemailUri);
+        try (InputStream inputStream = assets.open(TEST_ASSET_NAME);
+             OutputStream outputStream = getContentResolver().openOutputStream(mVoicemailUri)) {
             copyBetweenStreams(inputStream, outputStream);
-        } finally {
-            Closeables.closeQuietly(outputStream);
-            Closeables.closeQuietly(inputStream);
         }
         Uri callLogUri = ContentUris.withAppendedId(CallLog.Calls.CONTENT_URI_WITH_VOICEMAIL,
                 ContentUris.parseId(mVoicemailUri));
@@ -257,9 +250,7 @@
     public void copyBetweenStreams(InputStream in, OutputStream out) throws IOException {
         byte[] buffer = new byte[1024];
         int bytesRead;
-        int total = 0;
-        while ((bytesRead = in.read(buffer)) != -1) {
-            total += bytesRead;
+        while ((bytesRead = in.read(buffer)) > 0) {
             out.write(buffer, 0, bytesRead);
         }
     }
@@ -289,6 +280,14 @@
         return views.get(0);
     }
 
+    private void assertHasOneTextViewContaining(String text1, String text2) throws Throwable {
+        assertNotNull(mActivityUnderTest);
+        List<TextView> view1s = mTestUtils.getTextViewsWithString(mActivityUnderTest, text1);
+        List<TextView> view2s = mTestUtils.getTextViewsWithString(mActivityUnderTest, text2);
+        assertEquals("There should have been one TextView with text '" + text1 + "' or text '"
+                + text2  + "' but found " + view1s + view2s, 1, view1s.size() + view2s.size());
+    }
+
     private void assertZeroTextViewsContaining(String text) throws Throwable {
         assertNotNull(mActivityUnderTest);
         List<TextView> views = mTestUtils.getTextViewsWithString(mActivityUnderTest, text);
@@ -304,6 +303,7 @@
         // This is because it seems that we can have onResume, onPause, onResume during the course
         // of a single unit test.
         mFakeAsyncTaskExecutor.runAllTasks(GET_CALL_DETAILS);
+        CallLogAsyncTaskUtil.resetForTest();
     }
 
     private AssetManager getAssets() {