[automerger skipped] Merge "Set communication device when device become active Bluetooth device" into tm-qpr-dev am: 636de5a474 -s ours am: 11049d6e91 -s ours
am skip reason: Merged-In I559e1ba6880cd6d429031b81622bf30c981526e2 with SHA-1 ea9881f3be is already in history
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/services/Telecomm/+/20533352
Change-Id: I8b3972220705168e9a914cadaf431c31420bb36e
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c26650c..648b4a9 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -137,6 +137,7 @@
android:permission="android.permission.CALL_PHONE"
android:excludeFromRecents="true"
android:process=":ui"
+ android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|density|fontScale|keyboard|layoutDirection|locale|navigation|smallestScreenSize|touchscreen|uiMode"
android:exported="true">
<!-- CALL action intent filters for the various ways of initiating an outgoing call. -->
<intent-filter>
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 2707a08..5d9fcd7 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Die oproep na <xliff:g id="CALLER">%s</xliff:g> is ontkoppel as gevolg van \'n noodoproep wat gemaak word."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Jou oproep is ontkoppel as gevolg van \'n noodoproep wat gemaak word."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Agtergrondoproep"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> het \'n oproep in die agtergrond geplaas. Hierdie program kan dalk toegang tot oudio kry en dit oor die oproep speel."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> verwerk ’n oproep in die agtergrond. Hierdie program kan dalk toegang tot oudio kry en dit oor die oproep speel."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> het opgehou reageer"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Jou oproep het die foonprogram gebruik wat saam met jou toestel gekom het"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Oproep stilgemaak."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom-ontwikkelaarkieslys"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Oproepe kan nie gedurende \'n noodoproep geneem word nie."</string>
<string name="cancel" msgid="6733466216239934756">"Kanselleer"</string>
+ <string name="back" msgid="6915955601805550206">"Terug"</string>
</resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index b171af6..b537050 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"የአደጋ ጊዜ ጥሪ እየተደረገ ስለሆነ ወደ <xliff:g id="CALLER">%s</xliff:g> የሚደረገው ጥሪ ተቋርጧል።"</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"የአደጋ ጊዜ ጥሪ እየተደረገ ስለሆነ የእርስዎ ጥሪ ተቋርጧል።"</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"የጀርባ ጥሪ"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ጥሪን ወደ ጀርባ አስቀምጧል። ይህ መተግበሪያ ጥሪው ላይ ኦዲዮ ላይ እየደረሰ ወይም እያጫወተ ሊሆን ይችላል።"</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ከዳራ ጥሪ እያስሄደ ነው። ይህ መተግበሪያ ወደ ጥሪው ኦዲዮ እየደረሰ ወይም እያጫወተ ሊሆን ይችላል።"</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> ምላሽ መስጠት አቁሟል"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"ጥሪዎ ከእርስዎ መሣሪያ ጋር የመጣውን የስልክ መተግበሪያ ተጠቅሟል"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"ጥሪ ፀጥ ብሏል"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"የቴሌኮም ገንቢ ምናሌ"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"ጥሪዎች በአደጋ ጊዜ ጥሪ ላይ ሊነሱ አይችሉም።"</string>
<string name="cancel" msgid="6733466216239934756">"ይቅር"</string>
+ <string name="back" msgid="6915955601805550206">"ተመለስ"</string>
</resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index d310271..88ed166 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"تم قطع اتصالك بجهة الاتصال <xliff:g id="CALLER">%s</xliff:g> بسبب إجراء مكالمة طوارئ."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"تم قطع مكالمتك بسبب إجراء مكالمة طوارئ."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"مكالمة في الخلفية"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"وضَع <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> مكالمة في الخلفية. يمكن لهذا التطبيق الوصول إلى الصوت وتشغيله عبر المكالمة."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"يعالج تطبيق <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> مكالمة في الخلفية. يمكن لهذا التطبيق الوصول إلى الصوت وتشغيله عبر المكالمة."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"توقّف <xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> عن الاستجابة"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"تمت مكالمتك باستخدام تطبيق \"الهاتف\" الذي أتى مع جهازك."</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"تم كتم صوت المكالمة."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"قائمة مطوّر برامج الاتصالات"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"لا يمكن تلقّي المكالمات أثناء إجراء مكالمة طوارئ."</string>
<string name="cancel" msgid="6733466216239934756">"إلغاء"</string>
+ <string name="back" msgid="6915955601805550206">"رجوع"</string>
</resources>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 33a56ad..a63ffd6 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -30,15 +30,15 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"এট জৰুৰীকালীন কল কৰাৰ কাৰণে <xliff:g id="CALLER">%s</xliff:g>লৈ কৰা কলটোৰ সংযোগ বিচ্ছিন্ন কৰা হৈছে।"</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"এট জৰুৰীকালীন কল কৰাৰ কাৰণে আপোনাৰ কলটোৰ সংযোগ বিচ্ছিন্ন কৰা হৈছে।"</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"নেপথ্যৰ কল"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>এ নেপথ্যত এটা কল কৰিছে। এই এপ্টোৱে কলটোত অডিঅ’ এক্সেছ আৰু প্লে’ কৰি থাকিব পাৰে।"</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>এ নেপথ্যত এটা কল প্ৰক্ৰিয়াকৰণ কৰি আছে। এই এপ্টোৱে কলটো চলি থাকোঁতে অডিঅ’ এক্সেছ আৰু প্লে’ কৰি থাকিব পাৰে।"</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g>এ সঁহাৰি দিয়া বন্ধ কৰিছে"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"আপোনাৰ কলটোৱে আপোনাৰ ডিভাইচটোৰ লগত অহা ফ’ন এপ্টো ব্যৱহাৰ কৰিছে"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"কল মিউট কৰা হৈছে।"</string>
<string name="accessibility_speakerphone_enabled" msgid="555386652061614267">"স্পীকাৰফ\'ন সক্ষম কৰা হৈছে।"</string>
<string name="respond_via_sms_canned_response_1" msgid="6332561460870382561">"এতিয়া কথা পাতিব নোৱাৰোঁ। কি খবৰ?"</string>
<string name="respond_via_sms_canned_response_2" msgid="2052951316129952406">"মই আপোনাক লগে লগে কলবেক কৰি আছোঁ।"</string>
- <string name="respond_via_sms_canned_response_3" msgid="6656147963478092035">"মই আপোনাক পিছত কল কৰিম।"</string>
- <string name="respond_via_sms_canned_response_4" msgid="9141132488345561047">"এতিয়া কথা পাতিব নোৱাৰোঁ। মোক পিছত কল কৰিবনে?"</string>
+ <string name="respond_via_sms_canned_response_3" msgid="6656147963478092035">"মই আপোনাক পাছত কল কৰিম।"</string>
+ <string name="respond_via_sms_canned_response_4" msgid="9141132488345561047">"এতিয়া কথা পাতিব নোৱাৰোঁ। মোক পাছত কল কৰিবনে?"</string>
<string name="respond_via_sms_setting_title" msgid="4762275482898830160">"ক্ষীপ্ৰ উত্তৰসমূহ"</string>
<string name="respond_via_sms_setting_title_2" msgid="4914853536609553457">"ক্ষীপ্ৰ উত্তৰসমূহ সম্পাদনা কৰক"</string>
<string name="respond_via_sms_setting_summary" msgid="8054571501085436868"></string>
@@ -57,9 +57,9 @@
<string name="change_default_dialer_dialog_affirmative" msgid="8604665314757739550">"ডিফ\'ল্ট ছেট কৰক"</string>
<string name="change_default_dialer_dialog_negative" msgid="8648669840052697821">"বাতিল কৰক"</string>
<string name="change_default_dialer_warning_message" msgid="8461963987376916114">"<xliff:g id="NEW_APP">%s</xliff:g>এ কল কৰা লগতে কলৰ সকলো দিশ নিয়ন্ত্ৰণ কৰিবলৈ সক্ষম হ\'ব। কেৱল আপুনি সম্পূৰ্ণৰূপে বিশ্বাস কৰা এপক হে আপোনাৰ ডিফ\'ল্ট ফ\'ন এপ্ হিচাপে চিহ্নিত কৰা উচিত।"</string>
- <string name="change_default_call_screening_dialog_title" msgid="5365787219927262408">"<xliff:g id="NEW_APP">%s</xliff:g>ক আপোনাৰ ডিফ\'ল্ট কল স্ক্ৰীণ কৰা এপ্ হিচাপে ছেট কৰিবনে?"</string>
- <string name="change_default_call_screening_warning_message_for_disable_old_app" msgid="2039830033533243164">"<xliff:g id="OLD_APP">%s</xliff:g>য়ে আৰু কল স্ক্ৰীণ কৰিব নোৱাৰিব।"</string>
- <string name="change_default_call_screening_warning_message" msgid="9020537562292754269">"<xliff:g id="NEW_APP">%s</xliff:g>য়ে আপোনাৰ সম্পৰ্কসূচীত নথকা কল কৰোঁতাৰ বিষয়ে তথ্য চাব আৰু এই কলবোৰ অৱৰোধ কৰিব পাৰিব। আপুনি বিশ্বাস কৰা এপবোৰহে ডিফ\'ল্ট কল স্ক্ৰীণ কৰা এপ্ হিচাপে ছেট কৰা উচিত।"</string>
+ <string name="change_default_call_screening_dialog_title" msgid="5365787219927262408">"<xliff:g id="NEW_APP">%s</xliff:g>ক আপোনাৰ ডিফ\'ল্ট কল স্ক্ৰীন কৰা এপ্ হিচাপে ছেট কৰিবনে?"</string>
+ <string name="change_default_call_screening_warning_message_for_disable_old_app" msgid="2039830033533243164">"<xliff:g id="OLD_APP">%s</xliff:g>য়ে আৰু কল স্ক্ৰীন কৰিব নোৱাৰিব।"</string>
+ <string name="change_default_call_screening_warning_message" msgid="9020537562292754269">"<xliff:g id="NEW_APP">%s</xliff:g>য়ে আপোনাৰ সম্পৰ্কসূচীত নথকা কল কৰোঁতাৰ বিষয়ে তথ্য চাব আৰু এই কলবোৰ অৱৰোধ কৰিব পাৰিব। আপুনি বিশ্বাস কৰা এপবোৰহে ডিফ\'ল্ট কল স্ক্ৰীন কৰা এপ্ হিচাপে ছেট কৰা উচিত।"</string>
<string name="change_default_call_screening_dialog_affirmative" msgid="7162433828280058647">"ডিফ\'ল্ট ছেট কৰক"</string>
<string name="change_default_call_screening_dialog_negative" msgid="1839266125623106342">"বাতিল কৰক"</string>
<string name="blocked_numbers" msgid="8322134197039865180">"অৱৰোধ কৰা নম্বৰসমূহ"</string>
@@ -73,7 +73,7 @@
<string name="non_primary_user" msgid="315564589279622098">"কেৱল ডিভাইচটোৰ গৰাকীয়েহে অৱৰোধ কৰা নম্বৰসমূহ চাব আৰু পৰিচালনা কৰিব পাৰে।"</string>
<string name="delete_icon_description" msgid="5335959254954774373">"অৱৰোধৰ পৰা আঁতৰাওক"</string>
<string name="blocked_numbers_butter_bar_title" msgid="582982373755950791">"সাময়িকভাৱে অৱৰোধৰ সুবিধা বন্ধ কৰি থোৱা হৈছে"</string>
- <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"আপুনি জৰুৰীকালীন নম্বৰ এটা ডায়েল কৰাৰ পিছত বা সেই নম্বৰটোলৈ পাঠ বাৰ্তা পঠিওৱাৰ পিছত নম্বৰটো অৱৰোধৰ পৰা আঁতৰোৱা হয় যাতে জৰুৰীকালীন সেৱাসমূহে আপোনাৰ সৈতে যোগাযোগ কৰিব পাৰে।"</string>
+ <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"আপুনি জৰুৰীকালীন নম্বৰ এটা ডায়েল কৰাৰ পাছত বা সেই নম্বৰটোলৈ পাঠ বাৰ্তা পঠিওৱাৰ পাছত নম্বৰটো অৱৰোধৰ পৰা আঁতৰোৱা হয় যাতে জৰুৰীকালীন সেৱাসমূহে আপোনাৰ সৈতে যোগাযোগ কৰিব পাৰে।"</string>
<string name="blocked_numbers_butter_bar_button" msgid="2704456308072489793">"এতিয়াই পুনঃসক্ষম কৰক"</string>
<string name="blocked_numbers_number_blocked_message" msgid="4314736791180919167">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> অৱৰোধ কৰা হৈছে"</string>
<string name="blocked_numbers_number_unblocked_message" msgid="2933071624674945601">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> অৱৰোধৰ পৰা আঁতৰ কৰা হৈছে"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"দূৰ-সংযোগ সম্পৰ্কীয় বিকাশকৰ্তাৰ মেনু"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"কোনো জৰুৰীকালীন কলত থাকিলে কলসমূহ গ্ৰহণ কৰিব নোৱাৰি।"</string>
<string name="cancel" msgid="6733466216239934756">"বাতিল কৰক"</string>
+ <string name="back" msgid="6915955601805550206">"উভতি যাওক"</string>
</resources>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 61dbd67..953f691 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Hazırda təcili zəng edildiyi üçün <xliff:g id="CALLER">%s</xliff:g> ilə zəng kəsilib."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Təcili zəng edildiyinə görə zənginizin əlaqəsi kəsildi."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Arxa fon zəngi"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> arxa fonda zəng edib. Bu tətbiq zəng ilə daxil ola və oxuda bilər."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> arxa fonda zəngi qəbul edir. Bu tətbiq zəng zamanı audioya daxil ola və oxuda bilər."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> tətbiqində xəta baş verdi"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Zəng üçün cihazda əvvəlcədən quraşdırılan telefon tətbiqindən istifadə edildi"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Səssiz zəng edin."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom Tərtibatçı Menyusu"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Təcili zəng zamanı zəng edilə bilməz."</string>
<string name="cancel" msgid="6733466216239934756">"Ləğv edin"</string>
+ <string name="back" msgid="6915955601805550206">"Geri"</string>
</resources>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 85dc005..a1e4393 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Poziv sa <xliff:g id="CALLER">%s</xliff:g> je prekinut jer se upućuje hitni poziv."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Poziv je prekinut jer se upućuje hitni poziv."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Poziv u pozadini"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"Aplikacija <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> je uputila poziv u pozadini. Ona može da pristupa zvuku i pušta ga tokom poziva."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"Aplikacija <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> obrađuje poziv u pozadini. Ona može da pristupa zvuku i da ga pušta tokom poziva."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> više ne reaguje"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Poziv je koristio aplikaciju za telefoniranje koju ste dobili uz uređaj"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Zvuk poziva je isključen."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Meni za programere Telecom-a"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Za vreme hitnog poziva nije moguće preuzimati druge pozive."</string>
<string name="cancel" msgid="6733466216239934756">"Otkaži"</string>
+ <string name="back" msgid="6915955601805550206">"Nazad"</string>
</resources>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 07e0adf..6e7552f 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Выклік да абанента <xliff:g id="CALLER">%s</xliff:g> перарваны, бо выконваецца экстранны выклік."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Бягучы выклік перарваны, бо выконваецца экстранны выклік."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Фонавы выклік"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"Праграма \"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>\" перавяла выклік у фонавы рэжым і можа прайграваць аўдыя падчас выкліку."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"Праграма \"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>\" апрацоўвае выклік у фонавым рэжыме. Яна можа прайграваць аўдыя падчас выкліку."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"Праграма \"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g>\" не адказвае"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Выклік зроблены ў стандартнай праграме \"Тэлефон\" на прыладзе"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Гук выключаны."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Меню распрацоўшчыка Telecom"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Падчас экстраннага выкліку іншыя выклікі прымаць немагчыма."</string>
<string name="cancel" msgid="6733466216239934756">"Скасаваць"</string>
+ <string name="back" msgid="6915955601805550206">"Назад"</string>
</resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 4bc13bb..9583a8b 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Обаждането до <xliff:g id="CALLER">%s</xliff:g> бе прекъснато, тъй като се извършва спешно обаждане."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Обаждането ви бе прекъснато, тъй като се извършва спешно обаждане."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Обаждане: заден план"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> постави обаждане на заден план. Приложението може да има достъп до обаждането и да възпроизвежда звук върху него."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> обработва обаждане на заден план. Приложението може да има достъп до обаждането и да възпроизвежда звук върху него."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> престана да реагира"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Обаждането ви бе извършено с приложението за телефон, което сте получили с устройството си"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Обаждането бе спряно."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Меню за програмисти на Telecom"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"По време на спешно обаждане не могат да се поемат обаждания."</string>
<string name="cancel" msgid="6733466216239934756">"Отказ"</string>
+ <string name="back" msgid="6915955601805550206">"Назад"</string>
</resources>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 2ecd8e1..de896ce 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"জরুরি কল করার জন্য <xliff:g id="CALLER">%s</xliff:g>-কে করা কল ডিসকানেক্ট করা হয়েছে।"</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"জরুরী কল করার জন্য আপনার কল ডিসকানেক্ট করা হয়েছে।"</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"ব্যাকগ্রাউন্ডের কল"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ব্যাকগ্রাউন্ডে কল রেখেছে। এই অ্যাপটি হয়ত কলের মাধ্যমে অডিও অ্যাক্সেস করে চালাচ্ছে।"</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ব্যাকগ্রাউন্ডে কল প্রসেস করছে। এই অ্যাপটি হয়ত কল থেকে অডিও অ্যাক্সেস করে চালাচ্ছে।"</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> কাজ করছে না"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"আপনার ডিভাইসের ফোন অ্যাপ ব্যবহার করে কল করা হত"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"কল মিউট করা আছে৷"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"টেলিকম ডেভেলপার মেনু"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"জরুরি কল চলাকালীন কোনও কল রিসিভ করা যাবে না।"</string>
<string name="cancel" msgid="6733466216239934756">"বাতিল করুন"</string>
+ <string name="back" msgid="6915955601805550206">"ফিরে যান"</string>
</resources>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index a1f9156..0b427d9 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Poziv upućen kontaktu <xliff:g id="CALLER">%s</xliff:g> je prekinut zbog upućivanja hitnog poziva."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Poziv je prekinut zbog upućivanja hitnog poziva."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Poziv u pozadini"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"Aplikacija <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> je uputila poziv u pozadini. Ova aplikacija može pristupati zvuku i reproducirati ga tokom poziva."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"Aplikacija <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> obrađuje poziv u pozadini. Ova aplikacija može pristupati zvuku i reproducirati ga tokom poziva."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"Aplikacija <xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> je prestala reagirati"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Za poziv se koristila aplikacija za telefon koju ste dobili uz uređaj"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Zvuk poziva je isključen."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Meni za programere iz telekoma"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Pozivi se ne mogu primati tokom hitnog poziva"</string>
<string name="cancel" msgid="6733466216239934756">"Otkaži"</string>
+ <string name="back" msgid="6915955601805550206">"Nazad"</string>
</resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 3978d69..d8728b8 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"La trucada a <xliff:g id="CALLER">%s</xliff:g> s\'ha desconnectat perquè s\'ha fet una trucada d\'emergència."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"La teva trucada s\'ha desconnectat perquè s\'ha fet una trucada d\'emergència."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Trucada en segon pla"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ha fet una trucada en segon pla. És possible que aquesta aplicació estigui accedint a l\'àudio i reproduint-lo a través de la trucada."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> està processant una trucada en segon pla. És possible que aquesta aplicació estigui accedint a l\'àudio i reproduint-lo a través de la trucada."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> ha deixat de respondre"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"A la trucada s\'ha fet servir l\'aplicació de telèfon que hi ha al dispositiu"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Trucada silenciada."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Menú per a desenvolupadors de telecomunicacions"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"No es poden respondre trucades durant una trucada d\'emergència."</string>
<string name="cancel" msgid="6733466216239934756">"Cancel·la"</string>
+ <string name="back" msgid="6915955601805550206">"Enrere"</string>
</resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 3b144aa..48655f3 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Hovor s volajícím <xliff:g id="CALLER">%s</xliff:g> byl odpojen, protože začalo být prováděno tísňové volání."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Váš hovor byl odpojen, protože bylo zahájeno tísňové volání."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Hovor na pozadí"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"Aplikace <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> přesunula hovor na pozadí. Tato aplikace může v hovoru používat a přehrávat zvuk."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"Aplikace <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> zpracovává hovor na pozadí. Tato aplikace může v hovoru používat a přehrávat zvuk."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"Aplikace <xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> přestala reagovat"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Při hovoru byla použita předinstalovaná telefonní aplikace"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Hovor ztlumen."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Nabídka pro vývojáře Telecomu"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Během tísňového volání není možné přijímat hovory."</string>
<string name="cancel" msgid="6733466216239934756">"Zrušit"</string>
+ <string name="back" msgid="6915955601805550206">"Zpět"</string>
</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 70a19ce..269c841 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Opkaldet til <xliff:g id="CALLER">%s</xliff:g> er blevet afbrudt, fordi der foretages et nødopkald."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Dit opkald er blevet afbrudt, fordi der foretages et nødopkald."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Opkald i baggrunden"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> har foretaget et opkald i baggrunden. Denne app har muligvis adgang til og afspiller lyd i opkaldet."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> behandler et opkald i baggrunden. Denne app har muligvis adgang til og afspiller lyd i opkaldet."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> svarer ikke"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Dit opkald brugte den opkaldsapp, din enhed er født med"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Lyd slået fra opkald."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Udviklermenu for Telecom"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Du kan ikke besvare opkald, mens du er i et nødopkald."</string>
<string name="cancel" msgid="6733466216239934756">"Annuller"</string>
+ <string name="back" msgid="6915955601805550206">"Tilbage"</string>
</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index e73ac10..6f532ba 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Der Anruf mit <xliff:g id="CALLER">%s</xliff:g> wurde beendet, weil ein Notruf getätigt wurde."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Der Anruf wurde beendet, weil ein Notruf getätigt wurde."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Anruf im Hintergrund"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> hat einen Anruf in den Hintergrund verschoben. Diese App greift möglicherweise auf den Anruf zu und spielt Audio darüber ab."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> verarbeitet einen Anruf im Hintergrund. Diese App greift möglicherweise auf den Anruf zu und spielt Audio darüber ab."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> reagiert nicht mehr"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Für den Anruf wurde die auf deinem Gerät vorinstallierte App verwendet"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Anruf stummgeschaltet"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom-Entwicklermenü"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Während eines Notrufs kannst du keine Anrufe annehmen."</string>
<string name="cancel" msgid="6733466216239934756">"Abbrechen"</string>
+ <string name="back" msgid="6915955601805550206">"Zurück"</string>
</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index b677874..85636b1 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Η κλήση προς <xliff:g id="CALLER">%s</xliff:g> αποσυνδέθηκε λόγω πραγματοποίησης κλήσης έκτακτης ανάγκης."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Η κλήση σας αποσυνδέθηκε λόγω πραγματοποίησης κλήσης έκτακτης ανάγκης."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Κλήση στο παρασκήνιο"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"Η εφαρμογή <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> πραγματοποίησε μια κλήση στο παρασκήνιο. Η εφαρμογή αυτή ενδέχεται να έχει δικαίωμα προσπέλασης και αναπαραγωγής ήχου κατά τη διάρκεια της κλήσης."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"Η εφαρμογή <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> επεξεργάζεται μια κλήση στο παρασκήνιο. Η εφαρμογή αυτή ενδέχεται να έχει δικαίωμα πρόσβασης και αναπαραγωγής ήχου κατά τη διάρκεια της κλήσης."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"Η εφαρμογή <xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> έπαψε να αποκρίνεται"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Η κλήση σας πραγματοποιήθηκε μέσω της αρχικής εφαρμογής τηλεφώνου της συσκευής σας."</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Η κλήση τέθηκε σε σίγαση."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Μενού προγραμματιστών τηλεπικοινωνιών"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Δεν είναι δυνατή η λήψη κλήσεων κατά τη διάρκεια κλήσης επείγουσας ανάγκης."</string>
<string name="cancel" msgid="6733466216239934756">"Ακύρωση"</string>
+ <string name="back" msgid="6915955601805550206">"Πίσω"</string>
</resources>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index cef6db5..2d526cd 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"The call to <xliff:g id="CALLER">%s</xliff:g> has been disconnected due to an emergency call being placed."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Your call has been disconnected due to an emergency call being placed."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Background call"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> has placed a call into the background. This app may be accessing and playing audio over the call."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> is processing a call in the background. This app may be accessing and playing audio over the call."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> stopped responding"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Your call used the phone app that came with your device"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Call muted."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom Developer Menu"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Calls can not be taken while in an emergency call."</string>
<string name="cancel" msgid="6733466216239934756">"Cancel"</string>
+ <string name="back" msgid="6915955601805550206">"Back"</string>
</resources>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index cef6db5..538aa38 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="telecommAppLabel" product="default" msgid="1825598513414129827">"Phone calls"</string>
+ <string name="telecommAppLabel" product="default" msgid="1825598513414129827">"Phone Calls"</string>
<string name="userCallActivityLabel" product="default" msgid="3605391260292846248">"Phone"</string>
<string name="unknown" msgid="6993977514360123431">"Unknown"</string>
<string name="notification_missedCallTitle" msgid="5060387047205532974">"Missed call"</string>
@@ -30,13 +30,13 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"The call to <xliff:g id="CALLER">%s</xliff:g> has been disconnected due to an emergency call being placed."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Your call has been disconnected due to an emergency call being placed."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Background call"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> has placed a call into the background. This app may be accessing and playing audio over the call."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> is processing a call in the background. This app may be accessing and playing audio over the call."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> stopped responding"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Your call used the phone app that came with your device"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Call muted."</string>
<string name="accessibility_speakerphone_enabled" msgid="555386652061614267">"Speakerphone enabled."</string>
- <string name="respond_via_sms_canned_response_1" msgid="6332561460870382561">"I am so sorry, I can\'t answer the phone right now. How can I help you?"</string>
- <string name="respond_via_sms_canned_response_2" msgid="2052951316129952406">"I\'ll call you back."</string>
+ <string name="respond_via_sms_canned_response_1" msgid="6332561460870382561">"Can\'t talk now. What\'s up?"</string>
+ <string name="respond_via_sms_canned_response_2" msgid="2052951316129952406">"I\'ll call you right back."</string>
<string name="respond_via_sms_canned_response_3" msgid="6656147963478092035">"I\'ll call you later."</string>
<string name="respond_via_sms_canned_response_4" msgid="9141132488345561047">"Can\'t talk now. Call me later?"</string>
<string name="respond_via_sms_setting_title" msgid="4762275482898830160">"Quick responses"</string>
@@ -47,7 +47,7 @@
<string name="respond_via_sms_failure_format" msgid="5198680980054596391">"Message failed to send to <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
<string name="enable_account_preference_title" msgid="6949224486748457976">"Calling accounts"</string>
<string name="outgoing_call_not_allowed_user_restriction" msgid="3424338207838851646">"Only emergency calls are allowed."</string>
- <string name="outgoing_call_not_allowed_no_permission" msgid="8590468836581488679">"This application cannot make outgoing calls without Phone permission."</string>
+ <string name="outgoing_call_not_allowed_no_permission" msgid="8590468836581488679">"This application cannot make outgoing calls without the Phone permission."</string>
<string name="outgoing_call_error_no_phone_number_supplied" msgid="7665135102566099778">"To place a call, enter a valid number."</string>
<string name="duplicate_video_call_not_allowed" msgid="5754746140185781159">"Call cannot be added at this time."</string>
<string name="no_vm_number" msgid="2179959110602180844">"Missing voicemail number"</string>
@@ -56,10 +56,10 @@
<string name="change_default_dialer_dialog_title" msgid="5861469279421508060">"Make <xliff:g id="NEW_APP">%s</xliff:g> your default Phone app?"</string>
<string name="change_default_dialer_dialog_affirmative" msgid="8604665314757739550">"Set Default"</string>
<string name="change_default_dialer_dialog_negative" msgid="8648669840052697821">"Cancel"</string>
- <string name="change_default_dialer_warning_message" msgid="8461963987376916114">"<xliff:g id="NEW_APP">%s</xliff:g> will be able to place and control all aspects of calls. Only apps that you trust should be set as the default Phone app."</string>
+ <string name="change_default_dialer_warning_message" msgid="8461963987376916114">"<xliff:g id="NEW_APP">%s</xliff:g> will be able to place and control all aspects of calls. Only apps you trust should be set as the default Phone app."</string>
<string name="change_default_call_screening_dialog_title" msgid="5365787219927262408">"Make <xliff:g id="NEW_APP">%s</xliff:g> your default call screening app?"</string>
<string name="change_default_call_screening_warning_message_for_disable_old_app" msgid="2039830033533243164">"<xliff:g id="OLD_APP">%s</xliff:g> will no longer be able to screen calls."</string>
- <string name="change_default_call_screening_warning_message" msgid="9020537562292754269">"<xliff:g id="NEW_APP">%s</xliff:g> will be able to see information about callers not in your contacts and will be able to block these calls. Only apps that you trust should be set as the default call screening app."</string>
+ <string name="change_default_call_screening_warning_message" msgid="9020537562292754269">"<xliff:g id="NEW_APP">%s</xliff:g> will be able to see information about callers not in your contacts and will be able to block these calls. Only apps you trust should be set as the default call screening app."</string>
<string name="change_default_call_screening_dialog_affirmative" msgid="7162433828280058647">"Set Default"</string>
<string name="change_default_call_screening_dialog_negative" msgid="1839266125623106342">"Cancel"</string>
<string name="blocked_numbers" msgid="8322134197039865180">"Blocked numbers"</string>
@@ -73,13 +73,13 @@
<string name="non_primary_user" msgid="315564589279622098">"Only the device owner can view and manage blocked numbers."</string>
<string name="delete_icon_description" msgid="5335959254954774373">"Unblock"</string>
<string name="blocked_numbers_butter_bar_title" msgid="582982373755950791">"Blocking temporarily off"</string>
- <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"When you dial or text an emergency number, blocking is turned off to ensure that emergency services can contact you."</string>
+ <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"After you dial or text an emergency number, blocking is turned off to ensure that emergency services can contact you."</string>
<string name="blocked_numbers_butter_bar_button" msgid="2704456308072489793">"Re-enable now"</string>
<string name="blocked_numbers_number_blocked_message" msgid="4314736791180919167">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> blocked"</string>
<string name="blocked_numbers_number_unblocked_message" msgid="2933071624674945601">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> unblocked"</string>
<string name="blocked_numbers_block_emergency_number_message" msgid="4198550501500893890">"Unable to block emergency number."</string>
<string name="blocked_numbers_number_already_blocked_message" msgid="2301270825735665458">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> is already blocked."</string>
- <string name="toast_personal_call_msg" msgid="5817631570381795610">"Using the personal dialler to make the call"</string>
+ <string name="toast_personal_call_msg" msgid="5817631570381795610">"Using the personal dialer to make the call"</string>
<string name="notification_incoming_call" msgid="1233481138362230894">"<xliff:g id="CALL_VIA">%1$s</xliff:g> call from <xliff:g id="CALL_FROM">%2$s</xliff:g>"</string>
<string name="notification_incoming_video_call" msgid="5795968314037063900">"<xliff:g id="CALL_VIA">%1$s</xliff:g> video call from <xliff:g id="CALL_FROM">%2$s</xliff:g>"</string>
<string name="answering_ends_other_call" msgid="8653544281903986641">"Answering will end your <xliff:g id="CALL_VIA">%1$s</xliff:g> call"</string>
@@ -90,7 +90,7 @@
<string name="answering_ends_other_managed_video_call" msgid="1988508241432031327">"Answering will end your ongoing video call"</string>
<string name="answer_incoming_call" msgid="2045888814782215326">"Answer"</string>
<string name="decline_incoming_call" msgid="922147089348451310">"Decline"</string>
- <string name="cant_call_due_to_no_supported_service" msgid="1635626384149947077">"Call cannot be placed because there are no calling accounts that support calls of this type."</string>
+ <string name="cant_call_due_to_no_supported_service" msgid="1635626384149947077">"Call cannot be placed because there are no calling accounts which support calls of this type."</string>
<string name="cant_call_due_to_ongoing_call" msgid="8004235328451385493">"Call cannot be placed due to your <xliff:g id="OTHER_CALL">%1$s</xliff:g> call."</string>
<string name="cant_call_due_to_ongoing_calls" msgid="6379163795277824868">"Call cannot be placed due to your <xliff:g id="OTHER_CALL">%1$s</xliff:g> calls."</string>
<string name="cant_call_due_to_ongoing_unknown_call" msgid="8243532328969433172">"Call cannot be placed due to a call in another app."</string>
@@ -101,7 +101,7 @@
<string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Disconnected calls"</string>
<string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Crashed phone apps"</string>
<string name="alert_outgoing_call" msgid="5319895109298927431">"Placing this call will end your <xliff:g id="OTHER_APP">%1$s</xliff:g> call."</string>
- <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Choose how to make this call"</string>
+ <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Choose how to place this call"</string>
<string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Redirect call using <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string>
<string name="alert_place_unredirect_outgoing_call" msgid="2467608535225764006">"Call using my phone number"</string>
<string name="alert_redirect_outgoing_call_timeout" msgid="5568101425637373060">"Call can\'t be placed by <xliff:g id="OTHER_APP">%1$s</xliff:g>. Try using a different call redirecting app or contacting the developer for help."</string>
@@ -109,8 +109,8 @@
<string name="phone_settings_number_not_in_contact_txt" msgid="2602249106007265757">"Numbers not in Contacts"</string>
<string name="phone_settings_number_not_in_contact_summary_txt" msgid="963327038085718969">"Block numbers that are not listed in your Contacts"</string>
<string name="phone_settings_private_num_txt" msgid="6339272760338475619">"Private"</string>
- <string name="phone_settings_private_num_summary_txt" msgid="6755758240544021037">"Block callers who do not disclose their number"</string>
- <string name="phone_settings_payphone_txt" msgid="5003987966052543965">"Phonebox"</string>
+ <string name="phone_settings_private_num_summary_txt" msgid="6755758240544021037">"Block callers that do not disclose their number"</string>
+ <string name="phone_settings_payphone_txt" msgid="5003987966052543965">"Pay phone"</string>
<string name="phone_settings_payphone_summary_txt" msgid="3936631076065563665">"Block calls from pay phones"</string>
<string name="phone_settings_unknown_txt" msgid="3577926178354772728">"Unknown"</string>
<string name="phone_settings_unknown_summary_txt" msgid="5446657192535779645">"Block calls from unidentified callers"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom Developer Menu"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Calls can not be taken while in an emergency call."</string>
<string name="cancel" msgid="6733466216239934756">"Cancel"</string>
+ <string name="back" msgid="6915955601805550206">"Back"</string>
</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index cef6db5..2d526cd 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"The call to <xliff:g id="CALLER">%s</xliff:g> has been disconnected due to an emergency call being placed."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Your call has been disconnected due to an emergency call being placed."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Background call"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> has placed a call into the background. This app may be accessing and playing audio over the call."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> is processing a call in the background. This app may be accessing and playing audio over the call."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> stopped responding"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Your call used the phone app that came with your device"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Call muted."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom Developer Menu"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Calls can not be taken while in an emergency call."</string>
<string name="cancel" msgid="6733466216239934756">"Cancel"</string>
+ <string name="back" msgid="6915955601805550206">"Back"</string>
</resources>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index cef6db5..2d526cd 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"The call to <xliff:g id="CALLER">%s</xliff:g> has been disconnected due to an emergency call being placed."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Your call has been disconnected due to an emergency call being placed."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Background call"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> has placed a call into the background. This app may be accessing and playing audio over the call."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> is processing a call in the background. This app may be accessing and playing audio over the call."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> stopped responding"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Your call used the phone app that came with your device"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Call muted."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom Developer Menu"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Calls can not be taken while in an emergency call."</string>
<string name="cancel" msgid="6733466216239934756">"Cancel"</string>
+ <string name="back" msgid="6915955601805550206">"Back"</string>
</resources>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index da9faf3..f5436e0 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"The call to <xliff:g id="CALLER">%s</xliff:g> has been disconnected due to an emergency call being placed."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Your call has been disconnected due to an emergency call being placed."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Background call"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> has placed a call into the background. This app may be accessing and playing audio over the call."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> is processing a call in the background. This app may be accessing and playing audio over the call."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> stopped responding"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Your call used the phone app that came with your device"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Call muted."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom Developer Menu"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Calls can not be taken while in an emergency call."</string>
<string name="cancel" msgid="6733466216239934756">"Cancel"</string>
+ <string name="back" msgid="6915955601805550206">"Back"</string>
</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index ac0b22c..be9c4a1 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -30,11 +30,11 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Se desconectó la llamada a <xliff:g id="CALLER">%s</xliff:g> porque se está realizando una llamada de emergencia."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Se desconectó tu llamada porque se está haciendo una llamada de emergencia."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Llamada en 2.° plano"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> movió una a segundo plano. Es posible que esta app acceda a la llamada y reproduzca audio."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> está procesando una llamada en segundo plano. Es posible que esta app acceda a la llamada y reproduzca audio."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> dejó de responder"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Tu llamada se hizo con la app de teléfono que venía en tu dispositivo"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Llamada silenciada"</string>
- <string name="accessibility_speakerphone_enabled" msgid="555386652061614267">"Altavoz habilitado"</string>
+ <string name="accessibility_speakerphone_enabled" msgid="555386652061614267">"Bocina habilitada"</string>
<string name="respond_via_sms_canned_response_1" msgid="6332561460870382561">"No puedo hablar ahora. ¿Todo bien?"</string>
<string name="respond_via_sms_canned_response_2" msgid="2052951316129952406">"Te llamo enseguida."</string>
<string name="respond_via_sms_canned_response_3" msgid="6656147963478092035">"Te llamo más tarde."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Menú para desarrolladores de Telecom"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"No puedes contestar llamadas mientras estés en una llamada de emergencia."</string>
<string name="cancel" msgid="6733466216239934756">"Cancelar"</string>
+ <string name="back" msgid="6915955601805550206">"Atrás"</string>
</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 1d2aa15..b2e974c 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Se ha interrumpido la llamada a <xliff:g id="CALLER">%s</xliff:g> debido a una llamada de emergencia."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Se ha interrumpido tu llamada debido a una llamada de emergencia."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Llamada en segundo plano"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ha llamado en segundo plano. Puede que esta aplicación acceda al audio y lo reproduzca durante la llamada."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> está procesando una llamada en segundo plano. Puede que esta aplicación acceda al audio y lo reproduzca durante la llamada."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> ha dejado de responder"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"La llamada se utilizó la aplicación para teléfonos que venía con tu dispositivo"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Llamada silenciada"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Menú para desarrolladores de telecomunicaciones"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"No se pueden responder llamadas durante una llamada de emergencia."</string>
<string name="cancel" msgid="6733466216239934756">"Cancelar"</string>
+ <string name="back" msgid="6915955601805550206">"Atrás"</string>
</resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 4075aec..3814356 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Kõne helistajaga <xliff:g id="CALLER">%s</xliff:g> on katkestatud, kuna alustati hädaabikõnet."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Teie kõne katkestati, kuna alustati hädaabikõnet."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Taustal olev kõne"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> lülitas kõne taustale. See rakendus võib helile juurde pääseda ja seda kõne ajal esitada."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> töötleb taustal kõnet. See rakendus võib helile juurde pääseda ja seda kõne ajal esitada."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> lõpetas reageerimise"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Teie kõne kasutas teie seadmega kaasas olnud telefonirakendust"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Kõne on summutatud."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Teenuse Telecom arendaja menüü"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Hädaabikõne ajal ei saa kõnesid vastu võtta."</string>
<string name="cancel" msgid="6733466216239934756">"Tühista"</string>
+ <string name="back" msgid="6915955601805550206">"Tagasi"</string>
</resources>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 92f088c..8001579 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"<xliff:g id="CALLER">%s</xliff:g> deitzaileari egiten ari zinen deia deskonektatu da larrialdi-dei bat egiten ari zarelako."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Deia deskonektatu egin da, larrialdi-dei bat egiten ari zarelako."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Atzeko planoko deia"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> aplikazioak atzeko planoan jarri du deia. Baliteke aplikazioak audioa atzitzea eta erreproduzitzea deian zehar."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> dei bat prozesatzen ari da atzeko planoan. Baliteke aplikazioak audioa atzitzea eta erreproduzitzea deian zehar."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"Erantzuteari utzi dio <xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> aplikazioak"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Gailuaren telefono-aplikazioarekin egin da deia"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Deiaren audioa desaktibatu da."</string>
@@ -70,7 +70,7 @@
<string name="add_blocked_dialog_body" msgid="8599974422407139255">"Blokeatu zenbaki honetatik jasotzen diren deiak eta testu-mezuak:"</string>
<string name="add_blocked_number_hint" msgid="8769422085658041097">"Telefono-zenbakia"</string>
<string name="block_button" msgid="485080149164258770">"Blokeatu"</string>
- <string name="non_primary_user" msgid="315564589279622098">"Gailuaren jabeak soilik ikus eta kudea ditzake blokeatutako zenbakiak."</string>
+ <string name="non_primary_user" msgid="315564589279622098">"Gailuaren jabeak soilik ikusi eta kudea ditzake blokeatutako zenbakiak."</string>
<string name="delete_icon_description" msgid="5335959254954774373">"Desblokeatu"</string>
<string name="blocked_numbers_butter_bar_title" msgid="582982373755950791">"Aldi baterako desgaitu da blokeatzeko aukera"</string>
<string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"Larrialdietarako zenbakia markatu ondoren, edo zenbait horretara testu-mezua bidali ondoren, desaktibatu egingo da blokeatzeko aukera, larrialdi-zerbitzuak zurekin harremanetan jarriko direla ziurtatzeko."</string>
@@ -81,13 +81,13 @@
<string name="blocked_numbers_number_already_blocked_message" msgid="2301270825735665458">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> blokeatuta dago dagoeneko."</string>
<string name="toast_personal_call_msg" msgid="5817631570381795610">"Telefono pertsonala erabiltzen ari zara deia egiteko"</string>
<string name="notification_incoming_call" msgid="1233481138362230894">"<xliff:g id="CALL_VIA">%1$s</xliff:g> deia (deitzailea: <xliff:g id="CALL_FROM">%2$s</xliff:g>)"</string>
- <string name="notification_incoming_video_call" msgid="5795968314037063900">"<xliff:g id="CALL_VIA">%1$s</xliff:g> bideo-deia (deitzailea: <xliff:g id="CALL_FROM">%2$s</xliff:g>)"</string>
+ <string name="notification_incoming_video_call" msgid="5795968314037063900">"<xliff:g id="CALL_VIA">%1$s</xliff:g> bideodeia (deitzailea: <xliff:g id="CALL_FROM">%2$s</xliff:g>)"</string>
<string name="answering_ends_other_call" msgid="8653544281903986641">"Erantzuten baduzu, amaitu egingo da <xliff:g id="CALL_VIA">%1$s</xliff:g> deia"</string>
<string name="answering_ends_other_calls" msgid="3702302838456922535">"Erantzuten baduzu, amaitu egingo dira <xliff:g id="CALL_VIA">%1$s</xliff:g> deiak"</string>
- <string name="answering_ends_other_video_call" msgid="8572022039304239958">"Erantzuten baduzu, amaitu egingo da <xliff:g id="CALL_VIA">%1$s</xliff:g> bideo-deia"</string>
+ <string name="answering_ends_other_video_call" msgid="8572022039304239958">"Erantzuten baduzu, amaitu egingo da <xliff:g id="CALL_VIA">%1$s</xliff:g> bideodeia"</string>
<string name="answering_ends_other_managed_call" msgid="4031778317409881805">"Erantzuten baduzu, amaitu egingo da oraingo deia"</string>
<string name="answering_ends_other_managed_calls" msgid="3974069768615307659">"Erantzuten baduzu, amaitu egingo dira oraingo deiak"</string>
- <string name="answering_ends_other_managed_video_call" msgid="1988508241432031327">"Erantzuten baduzu, amaitu egingo da oraingo bideo-deia"</string>
+ <string name="answering_ends_other_managed_video_call" msgid="1988508241432031327">"Erantzuten baduzu, amaitu egingo da oraingo bideodeia"</string>
<string name="answer_incoming_call" msgid="2045888814782215326">"Erantzun"</string>
<string name="decline_incoming_call" msgid="922147089348451310">"Baztertu"</string>
<string name="cant_call_due_to_no_supported_service" msgid="1635626384149947077">"Ezin da egin deia, ez dagoelako mota honetako deiak onartzen duen deiak egiteko konturik."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telekomunikazioen garatzaileen menua"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Ezin duzu hartu deirik larrialdi-dei bat abian den bitartean."</string>
<string name="cancel" msgid="6733466216239934756">"Utzi"</string>
+ <string name="back" msgid="6915955601805550206">"Atzera"</string>
</resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 7425bfc..322a4b4 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"بهدلیل انجام تماسی اضطراری، تماس با <xliff:g id="CALLER">%s</xliff:g> قطع شده است."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"بهدلیل برقراری تماس اضطراری، تماس شما قطع شده است."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"تماس پسزمینه"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> تماسی را در پسزمینه قرار داد. ممکن است این برنامه درحین تماس به صدا دسترسی پیدا کند و آن را پخش کند."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> درحال پردازش تماس در پسزمینه است. ممکن است این برنامه درحین تماس به صدا دسترسی پیدا کند و آن را پخش کند."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> متوقف شد"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"تماستان بااستفاده از برنامه تلفن ارائهشده در دستگاهتان برقرار شد"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"تماس نادیده گرفته شد."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"منوی برنامهنویس Telecom"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"درحین برقراری تماسی اضطراری، نمیتوان به تماسها پاسخ داد."</string>
<string name="cancel" msgid="6733466216239934756">"لغو"</string>
+ <string name="back" msgid="6915955601805550206">"برگشتن"</string>
</resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index c04c43e..53ad1ac 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Puhelu vastaanottajalle <xliff:g id="CALLER">%s</xliff:g> on katkaistu hätäpuhelun soittamisen vuoksi."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Puhelusi on katkaistu hätäpuhelun soittamisen vuoksi."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Taustapuhelu"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> on asettanut puhelun taustalle. Tämä sovellus voi käyttää ja toistaa ääntä puhelun päällä."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> käsittelee puhelua taustalla. Tämä sovellus voi käyttää ja toistaa audiota puhelun päällä."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> lakkasi vastaamasta"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Puhelu soitettiin laitteen mukana tulleella puhelinsovelluksella"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Puhelu mykistetty."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Televiestinnän kehittäjävalikko"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Puheluita ei voi välittää hätäpuhelun aikana."</string>
<string name="cancel" msgid="6733466216239934756">"Peru"</string>
+ <string name="back" msgid="6915955601805550206">"Takaisin"</string>
</resources>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 0a04f2c..e8d70f6 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"L\'appel à <xliff:g id="CALLER">%s</xliff:g> a été déconnecté en raison d\'un appel d\'urgence qui a été passé."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Votre appel a été déconnecté en raison d\'un appel d\'urgence en cours de lancement."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Appel en arrière-plan"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> a passé un appel en arrière-plan. Cette application peut accéder à l\'audio de l\'appel et faire jouer un contenu audio par l\'intermédiaire de l\'appel."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> traite un appel en arrière-plan. Cette application peut accéder à l\'audio de l\'appel et faire jouer un contenu audio par l\'intermédiaire de l\'appel."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> a arrêté de répondre"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Votre appel a utilisé l\'application Téléphone intégrée à votre appareil"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Son coupé"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Menu Telecom Developer"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Les appels ne peuvent pas être pris pendant un appel d\'urgence."</string>
<string name="cancel" msgid="6733466216239934756">"Annuler"</string>
+ <string name="back" msgid="6915955601805550206">"Retour"</string>
</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 4396bd5..6d2720c 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"L\'appel avec <xliff:g id="CALLER">%s</xliff:g> a été interrompu en raison d\'un appel d\'urgence."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Votre appel a été interrompu en raison d\'un appel d\'urgence."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Appel en arrière-plan"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> a placé un appel en arrière-plan. Il est possible que cette application lise des fichiers audio pendant l\'appel."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> est en train de traiter un appel en arrière-plan. Il est possible que cette application ait accès à l\'audio et le lise pendant l\'appel."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> a cessé de répondre"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"L\'appel s\'est poursuivi dans l\'application d\'appel préinstallée sur votre appareil"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Son coupé"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Menu Telecom Developer"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Impossible de prendre un appel au cours d\'un appel d\'urgence."</string>
<string name="cancel" msgid="6733466216239934756">"Annuler"</string>
+ <string name="back" msgid="6915955601805550206">"Retour"</string>
</resources>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index ef3465d..59b5b10 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Desconectouse a chamada a <xliff:g id="CALLER">%s</xliff:g> porque se realizou unha chamada de emerxencia."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Desconectouse a chamada porque se realizou unha chamada de emerxencia."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Chamada seg. plano"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> chamou en segundo plano. Pode que esta aplicación acceda ao audio e o reproduza durante a chamada."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> está procesando unha chamada en segundo plano. Pode que esta aplicación acceda ao audio e o reproduza durante a chamada."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> deixou de responder"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Usouse a aplicación para teléfonos que ven co teu dispositivo na chamada"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Chamada silenciada"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Menú para programadores de telecomunicacións"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Non se pode responder ás chamadas durante unha chamada de emerxencia."</string>
<string name="cancel" msgid="6733466216239934756">"Cancelar"</string>
+ <string name="back" msgid="6915955601805550206">"Volver"</string>
</resources>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index 2729d22..879c776 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"ઇમર્જન્સી કૉલને કારણે <xliff:g id="CALLER">%s</xliff:g>નો કૉલ ડિસ્કનેક્ટ કરવામાં આવ્યો છે."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"ઇમર્જન્સી કૉલને કારણે તમારો કૉલ ડિસ્કનેક્ટ કરવામાં આવ્યો છે."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"બૅકગ્રાઉન્ડ કૉલ"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>એ કૉલ બેકગ્રાઉન્ડમાં રાખ્યો છે. આ ઍપ કૉલ પરથી ઑડિયો ઍક્સેસ કરીને તેને ચલાવી શકે છે."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"બૅકગ્રાઉન્ડમાં <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> કોઈ કૉલની પ્રક્રિયા કરી રહ્યું છે. આ ઍપ કૉલ પરથી ઑડિયો ઍક્સેસ કરીને તેને વગાડી શકે છે."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> ઍપ પ્રતિસાદ આપી રહી નથી"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"તમારા કૉલ માટે તમારા ડિવાઇસમાં પહેલેથી ઇન્સ્ટૉલ કરેલી ફોન ઍપનો ઉપયોગ કરવામાં આવ્યો"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"કૉલ મ્યૂટ કરેલ છે."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"ટેલિકોમ ડેવલપર મેનૂ"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"ઇમર્જન્સી કૉલ ચાલુ હોય, ત્યારે બીજા કોઈ કૉલ લઈ શકાતા નથી."</string>
<string name="cancel" msgid="6733466216239934756">"રદ કરો"</string>
+ <string name="back" msgid="6915955601805550206">"પાછળ"</string>
</resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 3013ee9..dd645bf 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"<xliff:g id="CALLER">%s</xliff:g> के साथ चल रहे कॉल को डिसकनेक्ट किया गया क्योंकि एक आपातकालीन कॉल किया जा रहा है."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"एक आपातकालीन कॉल किया जा रहा है, इसलिए आपका कॉल डिसकनेक्ट कर दिया गया है."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"बैकग्राउंड कॉल"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ने कॉल को बैकग्राउंड में रखा है हो सकता है कि यह ऐप्लिकेशन आपके कॉल से ऑडियो ऐक्सेस करके उसे चला रहा हो."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>, बैकग्राउंड में कॉल को प्रोसेस कर रहा है. ऐसा हो सकता है कि यह ऐप्लिकेशन आपके कॉल से ऑडियो को ऐक्सेस करके चला रहा हो."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> ऐप्लिकेशन बंद हो गया है"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"कॉल करने के लिए, आपके डिवाइस में पहले से मौजूद फ़ोन ऐप्लिकेशन का इस्तेमाल किया गया"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"कॉल म्यूट की गई."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"टेलीकॉम डेवलपर मेन्यू"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"आपातकालीन कॉल के दौरान कॉल नहीं उठाया जा सकता."</string>
<string name="cancel" msgid="6733466216239934756">"रद्द करें"</string>
+ <string name="back" msgid="6915955601805550206">"वापस जाएं"</string>
</resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index e84fe62..a456b31 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Poziv upućen <xliff:g id="CALLER">%s</xliff:g> prekinut je zbog uspostavljanja hitnog poziva."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Poziv je prekinut zbog hitnog poziva."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Poziv u pozadini"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"Aplikacija <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> prebacila je poziv u pozadinu. Ta aplikacija možda pristupa zvuku i reproducira ga putem poziva."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> obrađuje poziv u pozadini. Ta aplikacija možda pristupa zvuku i reproducira ga putem poziva."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> više ne odgovara"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Vaš je poziv upotrijebio aplikaciju telefona koju ste dobili na uređaju"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Zvuk poziva isključen."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Izbornik Telecom Developer"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Pozivi se ne mogu primiti tijekom hitnog poziva."</string>
<string name="cancel" msgid="6733466216239934756">"Odustani"</string>
+ <string name="back" msgid="6915955601805550206">"Natrag"</string>
</resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 75b8190..2118cf2 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Az Ön és <xliff:g id="CALLER">%s</xliff:g> közötti hívást a szolgáltató egy segélyhívás kezdeményezése miatt bontotta."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Segélyhívást kezdeményeztek, ezért az Ön hívását megszakítottuk."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Háttérbeli hívás"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"A(z) <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> a háttérbe helyezett egy hívást. Ez az alkalmazás hozzáférhet a híváshoz, és hangot játszhat le benne."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"A(z) <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> kezel egy hívást a háttérben. Ez az alkalmazás hozzáférhet a híváshoz, és hangot játszhat le benne."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"A(z) <xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> lefagyott"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"A hívása a készülékhez mellékelt telefonalkalmazást használta"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Hívás némítva."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telekommunikációs fejlesztői menü"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Segélyhívás közben nem lehet hívást fogadni."</string>
<string name="cancel" msgid="6733466216239934756">"Mégse"</string>
+ <string name="back" msgid="6915955601805550206">"Vissza"</string>
</resources>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 43c0568..8f5eea0 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"<xliff:g id="CALLER">%s</xliff:g>-ի հետ ընթացիկ զանգն ընդհատվեց շտապ կանչի պատճառով։"</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Ձեր զանգն ընդհատվեց շտապ կանչի պատճառով։"</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Ֆոնային զանգ"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> հավելվածը տեղափոխեց զանգը ֆոնային ռեժիմ և կարող է զանգի ընթացքում աուդիո ֆայլ նվագարկել:"</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> հավելվածը ֆոնային ռեժիմում զանգ է մշակում և կարող է զանգի ընթացքում աուդիո ֆայլ նվագարկել։"</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> հավելվածը չի արձագանքում"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Զանգն իրականացվեց արտադրողի կողմից ձեր սարքում տեղադրված հեռախոսի հավելվածով։"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Զանգը խլացված է:"</string>
@@ -79,7 +79,7 @@
<string name="blocked_numbers_number_unblocked_message" msgid="2933071624674945601">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> արգելահանվեց"</string>
<string name="blocked_numbers_block_emergency_number_message" msgid="4198550501500893890">"Արտակարգ իրավիճակների հեռախոսահամարը հնարավոր չէ արգելափակել:"</string>
<string name="blocked_numbers_number_already_blocked_message" msgid="2301270825735665458">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> համարն արդեն արգելափակված է:"</string>
- <string name="toast_personal_call_msg" msgid="5817631570381795610">"Զանգելու նպատակով անհատական համարհավաքիչի օգտագործում"</string>
+ <string name="toast_personal_call_msg" msgid="5817631570381795610">"Զանգելու նպատակով անհատական համարահավաքիչի օգտագործում"</string>
<string name="notification_incoming_call" msgid="1233481138362230894">"<xliff:g id="CALL_VIA">%1$s</xliff:g>-ի զանգ՝ <xliff:g id="CALL_FROM">%2$s</xliff:g>-ից"</string>
<string name="notification_incoming_video_call" msgid="5795968314037063900">"<xliff:g id="CALL_VIA">%1$s</xliff:g>-ի տեսազանգ՝ <xliff:g id="CALL_FROM">%2$s</xliff:g>-ից"</string>
<string name="answering_ends_other_call" msgid="8653544281903986641">"Եթե պատասխանեք այս զանգին, <xliff:g id="CALL_VIA">%1$s</xliff:g>-ի ընթացիկ զանգը կընդհատվի"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom-ի մշակողի ընտրացանկ"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Շտապ կանչի ժամանակ այլ զանգեր չեք կարող ընդւնել։"</string>
<string name="cancel" msgid="6733466216239934756">"Չեղարկել"</string>
+ <string name="back" msgid="6915955601805550206">"Հետ"</string>
</resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 2465076..e2077a7 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Panggilan kepada <xliff:g id="CALLER">%s</xliff:g> terputus karena ada panggilan darurat."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Panggilan Anda terputus karena ada panggilan darurat."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Panggilan latar belakang"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> telah menempatkan panggilan telepon ke latar belakang. Aplikasi ini mungkin mengakses dan memutar audio melalui panggilan telepon."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> sedang memproses panggilan di latar belakang. Aplikasi ini mungkin mengakses dan memutar audio dari panggilan telepon."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> berhenti merespons"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Panggilan Anda menggunakan aplikasi telepon bawaan perangkat Anda"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Panggilan disenyapkan."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Menu Developer Telecom"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Panggilan tidak dapat diterima saat sedang melakukan panggilan darurat."</string>
<string name="cancel" msgid="6733466216239934756">"Batal"</string>
+ <string name="back" msgid="6915955601805550206">"Kembali"</string>
</resources>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index fe6cf7f..3065f29 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Símtalið til <xliff:g id="CALLER">%s</xliff:g> hefur verið aftengt vegna þess að neyðarsímtal var hringt."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Símtalið var aftengt vegna þess að neyðarsímtal var hringt."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Bakgrunnssímtal"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> hefur sett símtal í bakgrunn. Hugsanlega fær þetta forrit aðgang að hljóði yfir símtalið og spilar það."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> vinnur úr símtali í bakgrunni. Hugsanlega fær þetta forrit aðgang að hljóði yfir símtalið og spilar það."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> hætti að svara"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Símtalið þitt notaði símaforritið sem fylgdi tækinu"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Símtal þaggað."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Forritaravalmynd fyrir fjarskipti"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Ekki er hægt að svara símtölum meðan á neyðarsímtali stendur."</string>
<string name="cancel" msgid="6733466216239934756">"Hætta við"</string>
+ <string name="back" msgid="6915955601805550206">"Til baka"</string>
</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index dd9ccbe..30d0976 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"La chiamata a <xliff:g id="CALLER">%s</xliff:g> è stata disconnessa per dare priorità a una chiamata di emergenza."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"La tua chiamata è stata disconnessa per dare priorità a una chiamata di emergenza."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"In sottofondo"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ha spostato una chiamata in sottofondo. L\'app potrà accedere all\'audio e riprodurlo in sovrapposizione alla chiamata."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> sta elaborando una chiamata in background. L\'app potrà accedere all\'audio e riprodurlo in sovrapposizione alla chiamata."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> non risponde più"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Per la tua chiamata è stata utilizzata l\'app per telefono integrata nel tuo dispositivo"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Chiamata disattivata."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Menu sviluppatore telecomunicazioni"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Impossibile accettare una chiamata durante una chiamata di emergenza."</string>
<string name="cancel" msgid="6733466216239934756">"Annulla"</string>
+ <string name="back" msgid="6915955601805550206">"Indietro"</string>
</resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 2f37355..0852428 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"השיחה עם <xliff:g id="CALLER">%s</xliff:g> נותקה בגלל שיחת חירום."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"השיחה נותקה בגלל שיחת חירום."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"שיחה ברקע"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"האפליקציה <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> התחילה שיחה ברקע. ייתכן שלאפליקציה יש גישה לאודיו או שהיא משמיעה אודיו בשיחה."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"באפליקציית <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> נערכת שיחה ברקע. יכול להיות שלאפליקציה יש גישה לקול או שהיא משמיעה קול בשיחה."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"אפליקציית <xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> הפסיקה להגיב"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"השיחה הייתה דרך אפליקציית הטלפון המקורית של המכשיר"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"שיחה מושתקת."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"תפריט למפתחי מערכות תקשורת"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"אי אפשר לענות לשיחות אחרות בזמן שיחת חירום."</string>
<string name="cancel" msgid="6733466216239934756">"ביטול"</string>
+ <string name="back" msgid="6915955601805550206">"חזרה"</string>
</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 2b000bb..e701fbf 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -24,13 +24,13 @@
<string name="notification_missedCallsTitle" msgid="3910479625507893809">"不在着信"</string>
<string name="notification_missedCallsMsg" msgid="5055782736170916682">"不在着信<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g>件"</string>
<string name="notification_missedCallTicker" msgid="6731461957487087769">"<xliff:g id="MISSED_CALL_FROM">%s</xliff:g>さんからの不在着信"</string>
- <string name="notification_missedCall_call_back" msgid="7900333283939789732">"コールバック"</string>
+ <string name="notification_missedCall_call_back" msgid="7900333283939789732">"かけ直す"</string>
<string name="notification_missedCall_message" msgid="4054698824390076431">"メッセージ"</string>
<string name="notification_disconnectedCall_title" msgid="1790131923692416928">"通話が切断されました"</string>
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"緊急通報番号宛に発信中のため、<xliff:g id="CALLER">%s</xliff:g> さんとの通話が切断されました。"</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"緊急通報番号宛に発信中のため、通話が切断されました。"</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"バックグラウンド通話"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> が通話をバックグラウンドに切り替えました。これで、このアプリは通話を通じて音声にアクセスして再生できます。"</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> は通話をバックグラウンドで処理しています。このアプリは通話を通じて音声にアクセスして再生できます。"</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> が応答しなくなりました"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"通話には、ご利用のデバイスにプリインストールされていた通話アプリが使用されていました"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"通話がミュートされています。"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom デベロッパー メニュー"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"緊急通報中は、他の電話を受けることができません。"</string>
<string name="cancel" msgid="6733466216239934756">"キャンセル"</string>
+ <string name="back" msgid="6915955601805550206">"戻る"</string>
</resources>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index b6fe683..6aade9d 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"ზარი <xliff:g id="CALLER">%s</xliff:g>-თან გაითიშა გადაუდებელი ზარის განთავსების გამო."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"თქვენი ზარი გაითიშა, რადგან ხორციელდება გადაუდებელი ზარი."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"ზარი ფონში"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>-მა განათავსა ზარი ფონში. ამ აპმა შეიძლება წვდომა იქონიოს აუდიოზე ზარიდან და დაუკრას ის."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ამუშავებს ზარს ფონურ რეჟიმში. ამ აპმა შეიძლება წვდომა იქონიოს აუდიოზე ზარიდან და დაუკრას ის."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g>-მა რეაგირება შეწყვიტა"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"თქვენმა ზარმა გამოიყენა ტელეფონის აპი, რომელიც თქვენს მოწყობილობას მოჰყვა"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"ზარი დადუმებულია."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom-ის დეველოპერის მენიუ"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"გადაუდებელი ზარის დროს ზარების მიღება შეუძლებელია."</string>
<string name="cancel" msgid="6733466216239934756">"გაუქმება"</string>
+ <string name="back" msgid="6915955601805550206">"უკან"</string>
</resources>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index aaa8229..a497d77 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Құтқару қызметіне қоңырау шалғандықтан, сіз бен <xliff:g id="CALLER">%s</xliff:g> арасындағы қоңырау ажыратылды."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Құтқару қызметіне қоңырау шалғандықтан, қоңырауыңыз ажыратылды."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Фондық қоңырау"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> қоңырауды фондық режимге ауыстырды. Бұл қолданба қоңырау барысында аудионы пайдалана және ойната алады."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> қоңырауды фондық режимде өңдеп жатыр. Бұл қолданба қоңырау барысында аудионы пайдалана және ойната алады."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> жауап бермейді"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Қоңырау құрылғының әдепкі телефон қолданбасы арқылы шалынды."</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Қоңырау үнсіздендірілген."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom Developer мәзірі"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Құтқару қызметімен сөйлесіп жатқанда, басқа қоңырауларды қабылдай алмайсыз."</string>
<string name="cancel" msgid="6733466216239934756">"Бас тарту"</string>
+ <string name="back" msgid="6915955601805550206">"Артқа"</string>
</resources>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index 82deb2a..be4f93e 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"ការហៅទូរសព្ទទៅ <xliff:g id="CALLER">%s</xliff:g> ត្រូវបានផ្ដាច់ ដោយសារកំពុងហៅទៅលេខសង្គ្រោះបន្ទាន់។"</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"ការហៅទូរសព្ទរបស់អ្នកត្រូវបានផ្ដាច់ ដោយសារតែកំពុងធ្វើការហៅទៅលេខសង្គ្រោះបន្ទាន់។"</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"ការហៅនៅផ្ទៃខាងក្រោយ"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> បានធ្វើការហៅទូរសព្ទនៅផ្ទៃខាងក្រោយ។ កម្មវិធីនេះអាចកំពុងចូលប្រើប្រាស់ និងចាក់សំឡេងតាមការហៅទូរសព្ទ។"</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> កំពុងដំណើរការការហៅទូរសព្ទនៅផ្ទៃខាងក្រោយ។ កម្មវិធីនេះអាចកំពុងចូលប្រើប្រាស់ និងចាក់សំឡេងតាមការហៅទូរសព្ទ។"</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> បានគាំង"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"ការហៅទូរសព្ទរបស់អ្នកបានប្រើប្រាស់កម្មវិធីទូរសព្ទដែលភ្ជាប់មកជាមួយឧបករណ៍របស់អ្នក"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"ការហៅបិទសំឡេង។"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"ម៉ឺនុយអ្នកអភិវឌ្ឍន៍ទូរគមនាគមន៍"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"មិនអាចទទួលការហៅទូរសព្ទបានទេ ពេលកំពុងហៅទៅលេខសង្គ្រោះបន្ទាន់។"</string>
<string name="cancel" msgid="6733466216239934756">"បោះបង់"</string>
+ <string name="back" msgid="6915955601805550206">"ថយក្រោយ"</string>
</resources>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index bf5ea45..b10aa51 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"ತುರ್ತು ಕರೆಯನ್ನು ಮಾಡುತ್ತಿರುವ ಕಾರಣ <xliff:g id="CALLER">%s</xliff:g> ಗೆ ಕರೆಯ ಕನೆಕ್ಷನ್ ಅನ್ನು ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"ತುರ್ತು ಕರೆಯನ್ನು ಮಾಡುತ್ತಿರುವ ಕಾರಣ ನಿಮ್ಮ ಕರೆಯನ್ನು ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"ಹಿನ್ನೆಲೆ ಕರೆ"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ಆ್ಯಪ್, ಕರೆಯನ್ನು ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಇರಿಸಿದೆ. ಈ ಆ್ಯಪ್ ಕರೆಯ ಮೂಲಕ ಆಡಿಯೊವನ್ನು ಪ್ರವೇಶಿಸಬಹುದು ಮತ್ತು ಪ್ಲೇ ಮಾಡಬಹುದು."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಕರೆಯನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸುತ್ತಿದೆ. ಈ ಆ್ಯಪ್ ಕರೆಯ ಮೂಲಕ ಆಡಿಯೊವನ್ನು ಪ್ರವೇಶಿಸಬಹುದು ಮತ್ತು ಪ್ಲೇ ಮಾಡಬಹುದು."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> ಪ್ರತಿಕ್ರಿಯಿಸುವುದನ್ನು ನಿಲ್ಲಿಸಿದೆ"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"ನಿಮ್ಮ ಕರೆಯು ಸಾಧನದ ಜೊತೆಗೆ ನೀಡಲಾದ ಫೋನ್ ಆ್ಯಪ್ ಅನ್ನು ಬಳಸಿದೆ."</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"ಕರೆಯನ್ನು ಮ್ಯೂಟ್ ಮಾಡಲಾಗಿದೆ."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"ಟೆಲಿಕಾಂ ಡೆವಲಪರ್ ಮೆನು"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"ತುರ್ತು ಕರೆಯಲ್ಲಿರುವಾಗ ಕರೆಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
<string name="cancel" msgid="6733466216239934756">"ರದ್ದುಮಾಡಿ"</string>
+ <string name="back" msgid="6915955601805550206">"ಹಿಂದಕ್ಕೆ"</string>
</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index d51eb1c..acf63ad 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"긴급 전화 연결로 인해 <xliff:g id="CALLER">%s</xliff:g>님에게 건 통화가 연결 해제되었습니다."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"긴급 전화 연결로 인해 통화가 연결 해제되었습니다."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"백그라운드 통화"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>에서 통화를 백그라운드로 전환했습니다. 앱이 통화에 사용되는 오디오에 액세스하거나 재생 중일 수 있습니다."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> 앱이 백그라운드에서 통화를 처리하는 중입니다. 앱이 통화에 사용되는 오디오에 액세스하거나 재생 중일 수 있습니다."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g>의 응답이 중지됨"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"기기의 기본 전화 앱을 사용하여 통화했습니다."</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"통화가 음소거되었습니다."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom 개발자 메뉴"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"긴급 전화 중에는 전화를 받을 수 없습니다."</string>
<string name="cancel" msgid="6733466216239934756">"취소"</string>
+ <string name="back" msgid="6915955601805550206">"뒤로"</string>
</resources>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index ec00c40..651e72a 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Учурда шашылыш чалуудан улам, <xliff:g id="CALLER">%s</xliff:g> чалуу ажыратылган."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Учурда шашылыш чалуудан улам, чалууңуз ажыратылган."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Фондогу чалуу"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> чалууну фонго койгон. Бул колдонмо чалуу аркылуу аудиого кирип, ойното алат."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> чалууну фондо иштетип жатат. Бул колдонмо чалуунун аудиосуна кирип, ойното алат."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> жооп берүүнү токтотту"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Чалууңуз түзмөгүңүз менен келген телефон колдонмосун пайдаланды"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Чалуу үнсүз тартипте."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom иштеп чыгуучусунун менюсу"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Шашылыш учурунда чалуулар кабыл алынбайт."</string>
<string name="cancel" msgid="6733466216239934756">"Жокко чыгаруу"</string>
+ <string name="back" msgid="6915955601805550206">"Артка"</string>
</resources>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 15cdb69..bedbf3a 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"ສາຍໂທຫາ <xliff:g id="CALLER">%s</xliff:g> ຖືກຕັດແລ້ວ ເນື່ອງຈາກກຳລັງມີການໂທສຸກເສີນຢູ່."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"ສາຍໂທຂອງທ່ານໄດ້ຖືກຕັດແລ້ວ ເນື່ອງຈາກກຳລັງມີການໂທສຸກເສີນຢູ່."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"ການໂທໃນພື້ນຫຼັງ"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ວາງການໂທໄວ້ພື້ນຫຼັງແລ້ວ. ແອັບນີ້ອາດເຂົ້າເຖິງ ແລະ ຫຼິ້ນສຽງຜ່ານການໂທໄດ້."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ກຳລັງປະມວນຜົນການໂທຢູ່ພື້ນຫຼັງ. ແອັບນີ້ອາດເຂົ້າເຖິງ ແລະ ຫຼິ້ນສຽງຜ່ານການໂທໄດ້."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> ໄດ້ຢຸດການຕອບສະໜອງແລ້ວ"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"ການໂທຂອງທ່ານໃຊ້ແອັບໂທລະສັບທີ່ມາພ້ອມກັບອຸປະກອນຂອງທ່ານ"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"ປິດສຽງການໂທແລ້ວ."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"ເມນູນັກພັດທະນາໂທລະຄົມ"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"ບໍ່ສາມາດໂທໄດ້ໃນຂະນະທີ່ຢູ່ໃນການໂທສຸກເສີນ."</string>
<string name="cancel" msgid="6733466216239934756">"ຍົກເລີກ"</string>
+ <string name="back" msgid="6915955601805550206">"ກັບຄືນ"</string>
</resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 2549087..b4ce4cd 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Skambutis kontaktui <xliff:g id="CALLER">%s</xliff:g> buvo atjungtas dėl atliekamo skambučio pagalbos numeriu."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Skambutis buvo atjungtas dėl atliekamo skambučio pagalbos numeriu."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Skambutis fone"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"Programa „<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>“ perkėlė skambutį į foną. Ši programa gali pasiekti ir leisti garsą vykstant skambučiui."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"„<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>“ apdoroja skambutį fone. Ši programa gali pasiekti ir leisti garsą vykstant skambučiui."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"Programa „<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g>“ nebereaguoja"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Atliekant skambutį buvo naudojama telefono programa, kuri buvo įrenginyje jį įsigijus"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Skambutis nutildytas."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telekomunikacijų kūrėjų meniu"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Atliekant skambutį pagalbos numeriu negalima atsiliepti į kitus skambučius."</string>
<string name="cancel" msgid="6733466216239934756">"Atšaukti"</string>
+ <string name="back" msgid="6915955601805550206">"Atgal"</string>
</resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index b8d6b51..147bae8 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Zvans lietotājam <xliff:g id="CALLER">%s</xliff:g> ir pārtraukts, jo tiek veikts ārkārtas izsaukums."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Jūsu zvans ir pārtraukts, jo tiek veikts ārkārtas izsaukums."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Saruna fonā"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> pārcēla sarunu uz darbību fonā. Sarunas laikā šī lietotne var piekļūt audio saturam un to atskaņot."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> apstrādā zvanu fonā. Sarunas laikā šī lietotne var piekļūt audio saturam un to atskaņot."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> pārtrauca reaģēt"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Zvanam tika izmantota jūsu ierīcē iebūvētā tālruņa lietotne"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Zvana skaņa ir izslēgta."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom izstrādātāja izvēlne"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Ārkārtas izsaukuma laikā nevar pieņemt zvanus."</string>
<string name="cancel" msgid="6733466216239934756">"Atcelt"</string>
+ <string name="back" msgid="6915955601805550206">"Atpakaļ"</string>
</resources>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index c425177..67a6d76 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Повикот до <xliff:g id="CALLER">%s</xliff:g> се исклучи поради воспоставувањето итен повик."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Повикот ќе се исклучи поради воспоставувањето итен повик."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Повик во заднина"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> воспостави повик во заднината. Апликацијава можеби пристапува до и пушта аудио во повикот."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> обработува повик во заднината. Апликацијава можеби пристапува до и пушта аудио во повикот."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> падна"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Повикот се обави на апликацијата за телефон што дојде со уредот"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Повикот е со исклучен звук"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Програмерско мени за телекомуникации"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Не може да примате повици во тек на итен повик."</string>
<string name="cancel" msgid="6733466216239934756">"Откажи"</string>
+ <string name="back" msgid="6915955601805550206">"Назад"</string>
</resources>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 47b4aa6c..dd5609b 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"ഒരു അടിയന്തര കോൾ നടക്കുന്നതിനാൽ <xliff:g id="CALLER">%s</xliff:g> എന്നയാൾക്ക് ചെയ്യുന്ന കോൾ വിച്ഛേദിക്കപ്പെട്ടിരിക്കുന്നു."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"ഒരു അടിയന്തര കോൾ നടക്കുന്നതിനാൽ നിങ്ങളുടെ കോൾ വിച്ഛേദിക്കപ്പെട്ടിരിക്കുന്നു."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"പശ്ചാത്തല കോൾ"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> കോൾ പശ്ചാത്തലത്തിലേക്ക് മാറ്റി. കോൾ ചെയ്യുമ്പോൾ ഈ ആപ്പിന് ഓഡിയോ ആക്സസ് ചെയ്യാനും പ്ലേ ചെയ്യാനും കഴിഞ്ഞേക്കാം."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> പശ്ചാത്തലത്തിൽ കോൾ പ്രോസസ് ചെയ്യുന്നു. കോൾ ചെയ്യുമ്പോൾ ഈ ആപ്പ് ഓഡിയോ ആക്സസ് ചെയ്ത് പ്ലേ ചെയ്തേക്കാം."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> ആപ്പ് പ്രതികരിക്കുന്നത് നിർത്തി"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"നിങ്ങളുടെ കോൾ, നിങ്ങളുടെ ഉപകരണത്തിനൊപ്പം ലഭ്യമായ ഫോൺ ആപ്പ് ഉപയോഗിച്ചു"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"കോൾ നിശബ്ദമാക്കി."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"ടെലികോം ഡെവലപ്പര് മെനു"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"അടിയന്തര കോളിലായിരിക്കുമ്പോൾ കോളുകൾ എടുക്കാനാവില്ല."</string>
<string name="cancel" msgid="6733466216239934756">"റദ്ദാക്കുക"</string>
+ <string name="back" msgid="6915955601805550206">"മടങ്ങുക"</string>
</resources>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index 4ba44f3..5562aff 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Яаралтай дуудлага ирсэн тул <xliff:g id="CALLER">%s</xliff:g> руу хийсэн дуудлагыг салгалаа."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Яаралтай дуудлага ирсэн тул таны дуудлагыг салгалаа."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Арын дуудлага"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> дуудлагыг ард оруулсан байна. Энэхүү апп нь дуудлагаар аудиод хандаж, тоглуулж байна."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> нь дэвсгэрт дуудлага боловсруулж байна. Энэ апп дуудлагаар аудиод хандаж, мөн аудио тоглуулж байж магадгүй."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> хариу өгөхөө больсон"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Таны дуудлагыг таны төхөөрөмжтэй хамт ирсэн гар утасны аппаар хийсэн"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Дууг хаасан."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Телеком хөгжүүлэгчийн цэс"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Яаралтай дуудлагын үеэр дуудлага авах боломжгүй."</string>
<string name="cancel" msgid="6733466216239934756">"Цуцлах"</string>
+ <string name="back" msgid="6915955601805550206">"Буцах"</string>
</resources>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index d4ddf6d..892db6c 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -30,10 +30,10 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"आणीबाणी कॉल केल्यामुळे <xliff:g id="CALLER">%s</xliff:g> ला केलेला कॉल डिस्कनेक्ट केला गेला."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"आणीबाणी कॉल केल्यामुळे तुमचा कॉल डिस्कनेक्ट केला गेला आहे."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"बॅकग्राउंड कॉल"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> यांनी कॉल बॅकग्राउंडवर ठेवला आहे हे अॅप कदाचित कॉलद्वारे ऑडिओ ॲक्सेस आणि प्ले करत आहे."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> बॅकग्राउंडमध्ये कॉलवर प्रक्रिया करत आहे. हे अॅप कदाचित कॉलमधील ऑडिओ ॲक्सेस आणि प्ले करत आहे."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> ने प्रतिसाद देणे थांबवले आहे"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"तुमच्या कॉलने डिव्हाइससोबत दिलेले फोन अॅप वापरले आहे"</string>
- <string name="accessibility_call_muted" msgid="2968461092554300779">"कॉल नि.शब्द केला."</string>
+ <string name="accessibility_call_muted" msgid="2968461092554300779">"कॉल म्यूट केला."</string>
<string name="accessibility_speakerphone_enabled" msgid="555386652061614267">"स्पीकरफोन सक्षम केला."</string>
<string name="respond_via_sms_canned_response_1" msgid="6332561460870382561">"आत्ता बोलू शकत नाही. कशासाठी कॉल केला होता?"</string>
<string name="respond_via_sms_canned_response_2" msgid="2052951316129952406">"मी तुम्हाला परत कॉल करेन."</string>
@@ -70,15 +70,15 @@
<string name="add_blocked_dialog_body" msgid="8599974422407139255">"यावरील कॉल आणि एसएमएस ब्लॉक करा"</string>
<string name="add_blocked_number_hint" msgid="8769422085658041097">"फोन नंबर"</string>
<string name="block_button" msgid="485080149164258770">"ब्लॉक करा"</string>
- <string name="non_primary_user" msgid="315564589279622098">"फक्त डिव्हाइस मालक अवरोधित केलेले नंबर पाहू आणि व्यवस्थापित करू शकतो."</string>
+ <string name="non_primary_user" msgid="315564589279622098">"फक्त डिव्हाइस मालक ब्लॉक केलेले नंबर पाहू आणि व्यवस्थापित करू शकतो."</string>
<string name="delete_icon_description" msgid="5335959254954774373">"ब्लॉक करा"</string>
- <string name="blocked_numbers_butter_bar_title" msgid="582982373755950791">"अवरोधित करणे तात्पुरते बंद आहे"</string>
- <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"तुम्ही एखादा आणीबाणी नंबर डायल केला किंवा त्यावर मजकूर पाठविल्यानंतर, आणीबाणी सेवा आपल्याशी संपर्क साधू शकतात हे सुनिश्चित करण्यासाठी अवरोधित करणे बंद करते."</string>
+ <string name="blocked_numbers_butter_bar_title" msgid="582982373755950791">"ब्लॉक करणे तात्पुरते बंद आहे"</string>
+ <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"तुम्ही एखादा आणीबाणी नंबर डायल केला किंवा त्यावर मेसेज पाठवल्यानंतर, आणीबाणी सेवा तुमच्याशी संपर्क साधू शकतात याची खात्री करण्यासाठी ब्लॉक करणे बंद केले जाते."</string>
<string name="blocked_numbers_butter_bar_button" msgid="2704456308072489793">"आता पुन्हा-सक्षम करा"</string>
- <string name="blocked_numbers_number_blocked_message" msgid="4314736791180919167">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> अवरोधित केला"</string>
+ <string name="blocked_numbers_number_blocked_message" msgid="4314736791180919167">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> ब्लॉक केला"</string>
<string name="blocked_numbers_number_unblocked_message" msgid="2933071624674945601">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> अनब्लॉक केला"</string>
- <string name="blocked_numbers_block_emergency_number_message" msgid="4198550501500893890">"आणीबाणी नंबर अवरोधित करण्यात अक्षम."</string>
- <string name="blocked_numbers_number_already_blocked_message" msgid="2301270825735665458">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> आधीपासून अवरोधित केला आहे."</string>
+ <string name="blocked_numbers_block_emergency_number_message" msgid="4198550501500893890">"आणीबाणी नंबर ब्लॉक करता आला नाही."</string>
+ <string name="blocked_numbers_number_already_blocked_message" msgid="2301270825735665458">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> आधीपासून ब्लॉक केला आहे."</string>
<string name="toast_personal_call_msg" msgid="5817631570381795610">"कॉल करण्यासाठी वैयक्तिक डायलर वापरणे"</string>
<string name="notification_incoming_call" msgid="1233481138362230894">"<xliff:g id="CALL_FROM">%2$s</xliff:g> कडील <xliff:g id="CALL_VIA">%1$s</xliff:g> मधील कॉल"</string>
<string name="notification_incoming_video_call" msgid="5795968314037063900">"<xliff:g id="CALL_FROM">%2$s</xliff:g> कडील <xliff:g id="CALL_VIA">%1$s</xliff:g> मधील व्हिडिओ कॉल"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"टेलिकॉम डेव्हलपर मेनू"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"आणीबाणी कॉल दरम्यान कॉल घेतला जाऊ शकत नाही."</string>
<string name="cancel" msgid="6733466216239934756">"रद्द करा"</string>
+ <string name="back" msgid="6915955601805550206">"मागे जा"</string>
</resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index c9aff1b..b59e246 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Panggilan kepada <xliff:g id="CALLER">%s</xliff:g> telah diputuskan sambungannya kerana panggilan kecemasan sedang dibuat."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Panggilan anda telah diputuskan sambungan kerana panggilan kecemasan sedang dibuat."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Panggilan latar blkg"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> telah meletakkan panggilan dalam latar belakang Apl ini mungkin mengakses dan memainkan audio mengatasi panggilan."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> sedang memproses panggilan pada latar. Apl ini mungkin mengakses dan memainkan audio mengatasi panggilan."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> telah berhenti memberikan respons"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Panggilan anda telah menggunakan aplikasi telefon yang disertakan bersama peranti anda"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Panggilan diredam."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Menu Pembangun Telekom"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Panggilan tidak boleh dijawab semasa dalam panggilan kecemasan."</string>
<string name="cancel" msgid="6733466216239934756">"Batal"</string>
+ <string name="back" msgid="6915955601805550206">"Kembali"</string>
</resources>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 616bc7c..f46eaed 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"အရေးပေါ်ဖုန်းခေါ်ဆိုမှု ပြုလုပ်နေသောကြောင့် <xliff:g id="CALLER">%s</xliff:g> ထံသို့ ခေါ်ဆိုမှုကို ဖြတ်တောက်လိုက်သည်။"</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"အရေးပေါ်ဖုန်းခေါ်ဆိုမှု ပြုလုပ်နေသောကြောင့် သင်၏ ခေါ်ဆိုမှုကို ဖြတ်တောက်လိုက်သည်။"</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"နောက်ခံမှ ခေါ်ဆိုမှု"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> သည် ခေါ်ဆိုမှုကို နောက်ခံသို့ ထည့်လိုက်ပါသည်။ ဤအက်ပ်သည် ခေါ်ဆိုမှုမှတစ်ဆင့် အသံများကို သုံးခြင်းနှင့် ဖွင့်ခြင်းတို့ ပြုလုပ်နိုင်ပါသည်။"</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> သည် ခေါ်ဆိုမှုကို နောက်ခံတွင် လုပ်ဆောင်နေသည်။ ဤအက်ပ်သည် ခေါ်ဆိုမှုမှတစ်ဆင့် အသံသုံးခြင်းနှင့် ဖွင့်ခြင်းတို့ကို ပြုလုပ်နေခြင်း ဖြစ်နိုင်သည်။"</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> က တုံ့ပြန်ခြင်းကို ရပ်လိုက်သည်"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"သင့်စက်ပစ္စည်းနှင့် အတူပါလာသော ဖုန်းအက်ပ်သုံးပြီး ခေါ်ဆိုမှုကို ပြုလုပ်ထားသည်"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"နားထောင်ရုံသာ (စကားပြောပိတ်ထားသည်)"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom ဆော့ဖ်ဝဲအင်ဂျင်နီယာ မီနူး"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"အရေးပေါ်ခေါ်ဆိုမှု ပြုလုပ်နေစဉ် ဖုန်းမခေါ်နိုင်ပါ။"</string>
<string name="cancel" msgid="6733466216239934756">"မလုပ်တော့"</string>
+ <string name="back" msgid="6915955601805550206">"နောက်သို့"</string>
</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index a981507..f77b60a 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Anropet til <xliff:g id="CALLER">%s</xliff:g> er koblet fra fordi et nødanrop ble utført."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Samtalen din ble brutt fordi et nødanrop ble utført."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Bakgrunnsanrop"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> har flyttet et anrop til bakgrunnen. Det kan hende denne appen bruker og spiller av lyd over anropet."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> behandler et anrop i bakgrunnen. Det kan hende denne appen bruker og spiller av lyd over anropet."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> sluttet å svare"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Anropet ble gjort med telefonappen som fulgte med enheten din"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Samtalelyd er kuttet."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Meny for telekommunikasjonsutviklere"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Du kan ikke besvare anrop mens du har et pågående nødanrop."</string>
<string name="cancel" msgid="6733466216239934756">"Avbryt"</string>
+ <string name="back" msgid="6915955601805550206">"Gå tilbake"</string>
</resources>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 8741730..9856415 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"आपत्कालीन कल गरिएको हुनाले <xliff:g id="CALLER">%s</xliff:g> लाई गरिएको कल विच्छेद गरियो।"</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"आपत्कालीन कल जारी रहेको हुनाले तपाईंको कल विच्छेद गरिएको छ।"</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"पृष्ठभूमिको कल"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ले एउटा कल पृष्ठभूमिमा राखेको छ। कल गरेको बेला यो एपले अडियोमाथि पहुँच राखेर प्ले गरिरहेको हुन सक्छ।"</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ले ब्याकग्राउन्डमा कुनै कल प्रोसेस गर्दै छ। यो एपले तपाईंको कलको अडियो प्रयोग गरिरहेको र सोही अडियो प्ले गरिरहेको हुन सक्छ।"</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> ले काम गर्न छाड्यो"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"कल गर्नका लागि तपाईंको डिभाइसमा पहिल्यैदेखि रहेको फोन एप प्रयोग गरियो"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"कल म्युट भयो।"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"टेलिकमको विकासकर्ताको मेनु"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"आपत्कालीन कल चलिराखेको बेलामा अरु कल स्वीकार गर्न सकिँदैन।"</string>
<string name="cancel" msgid="6733466216239934756">"रद्द गर्नुहोस्"</string>
+ <string name="back" msgid="6915955601805550206">"पछाडि"</string>
</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index be67223..ed3aaea 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Het gesprek met <xliff:g id="CALLER">%s</xliff:g> is beëindigd omdat er een noodoproep is geplaatst."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Je gesprek is beëindigd omdat er een noodoproep is geplaatst."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Achtergrondgesprek"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> heeft een gesprek op de achtergrond geplaatst. Deze app kan audio openen en afspelen over het gesprek."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> verwerkt een gesprek op de achtergrond. Deze app kan audio openen en afspelen over het gesprek."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> reageert niet meer"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Voor je gesprek is de telefoon-app van je apparaat gebruikt"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Gesprek gedempt."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecomontwikkelaarsmenu"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Gesprekken kunnen niet worden aangenomen tijdens een noodoproep."</string>
<string name="cancel" msgid="6733466216239934756">"Annuleren"</string>
+ <string name="back" msgid="6915955601805550206">"Terug"</string>
</resources>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 5c62bb1..7f9aa48 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"ଏକ ଜରୁରୀକାଳୀନ କଲ୍ କରାଯାଇଥିବାରୁ <xliff:g id="CALLER">%s</xliff:g>ଙ୍କୁ କରାଯାଇଥିବା କଲ୍ ବିଚ୍ଛିନ୍ନ କରାଯାଇଛି।"</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"ଏକ ଜରୁରୀକାଳୀନ କଲ୍ କରାଯାଉଥିବା ଯୋଗୁଁ ଆପଣଙ୍କ କଲ୍ ବିଚ୍ଛିନ୍ନ ହୋଇଯାଇଛି।"</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"ବ୍ୟାକ୍ଗ୍ରାଉଣ୍ଡ କଲ୍"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ବ୍ୟାକ୍ଗ୍ରାଉଣ୍ଡରେ ଏକ କଲ୍ କରିଛି। ଏହା ଆପ୍ କଲ୍ ସମୟରେ ଅଡିଓ ଆକ୍ସେସ୍ କରିପାରେ ଏବଂ ଚଲେଇପାରେ।"</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ପୃଷ୍ଠପଟରେ ଏକ କଲ ପ୍ରକ୍ରିୟାନ୍ୱିତ କରୁଛି। ଏହି ଆପ କଲ ସମୟରେ ଅଡିଓ ଆକ୍ସେସ ଏବଂ ପ୍ଲେ କରିପାରେ।"</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> ଉତ୍ତର ଦେଉନାହିଁ"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"ଆପଣଙ୍କ କଲ୍ ପାଇଁ ଆପଣଙ୍କ ଡିଭାଇସରେ ଥିବା ଫୋନ୍ ଆପ୍ ବ୍ୟବହାର କରାଯାଇଥିଲା"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"କଲ୍ ମ୍ୟୁଟ୍ କରାଯାଇଛି।"</string>
@@ -40,7 +40,7 @@
<string name="respond_via_sms_canned_response_3" msgid="6656147963478092035">"ମୁଁ ଆପଣଙ୍କୁ ପରେ କଲ୍ କରିବି।"</string>
<string name="respond_via_sms_canned_response_4" msgid="9141132488345561047">"ବର୍ତ୍ତମାନ କଥା ହୋଇପାରିବ ନାହିଁ। ମୋତେ ପରେ କଲ୍ କରିବେ?"</string>
<string name="respond_via_sms_setting_title" msgid="4762275482898830160">"ଶୀଘ୍ର ଉତ୍ତର"</string>
- <string name="respond_via_sms_setting_title_2" msgid="4914853536609553457">"ଶୀଘ୍ର ଉତ୍ତରକୁ ଏଡିଟ୍ କରନ୍ତୁ"</string>
+ <string name="respond_via_sms_setting_title_2" msgid="4914853536609553457">"ଶୀଘ୍ର ଉତ୍ତରକୁ ଏଡିଟ କରନ୍ତୁ"</string>
<string name="respond_via_sms_setting_summary" msgid="8054571501085436868"></string>
<string name="respond_via_sms_edittext_dialog_title" msgid="6579353156073272157">"ଶୀଘ୍ର ଉତ୍ତର"</string>
<string name="respond_via_sms_confirmation_format" msgid="2932395476561267842">"<xliff:g id="PHONE_NUMBER">%s</xliff:g>କୁ ମେସେଜ୍ ପଠାଗଲା।"</string>
@@ -55,13 +55,13 @@
<string name="add_vm_number_str" msgid="5179510133063168998">"ନମ୍ବର୍ ଯୋଡ଼ନ୍ତୁ"</string>
<string name="change_default_dialer_dialog_title" msgid="5861469279421508060">"<xliff:g id="NEW_APP">%s</xliff:g>କୁ ଆପଣଙ୍କ ଫୋନ୍ର ଡିଫଲ୍ଟ ଆପ୍ କରିବେ?"</string>
<string name="change_default_dialer_dialog_affirmative" msgid="8604665314757739550">"ଡିଫଲ୍ଟ ସେଟ୍ କରନ୍ତୁ"</string>
- <string name="change_default_dialer_dialog_negative" msgid="8648669840052697821">"ବାତିଲ୍ କରନ୍ତୁ"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="8648669840052697821">"ବାତିଲ କରନ୍ତୁ"</string>
<string name="change_default_dialer_warning_message" msgid="8461963987376916114">"<xliff:g id="NEW_APP">%s</xliff:g> କଲ୍ କରିବା ଏବଂ କଲ୍ର ସମସ୍ତ ଦିଗକୁ ନିୟନ୍ତ୍ରଣ କରିବାରେ ସକ୍ଷମ ହେବ। କେବଳ ନିଜର ଭରସାଯୋଗ୍ୟ ଆପ୍କୁ ଡିଫଲ୍ଟ ଫୋନ୍ ଆପ୍ ଭାବେ ସେଟ୍ କରିବା ଉଚିତ୍।"</string>
<string name="change_default_call_screening_dialog_title" msgid="5365787219927262408">"<xliff:g id="NEW_APP">%s</xliff:g>କୁ ଆପଣଙ୍କ ଡିଫଲ୍ଟ କଲ୍ ସ୍କ୍ରିନିଂ ଆପ୍ କରିବେ?"</string>
<string name="change_default_call_screening_warning_message_for_disable_old_app" msgid="2039830033533243164">"<xliff:g id="OLD_APP">%s</xliff:g> କଲ୍ ସ୍କ୍ରିନ୍ କରିପାରିରିବେ ନାହିଁ।"</string>
<string name="change_default_call_screening_warning_message" msgid="9020537562292754269">"ଆପଣଙ୍କ ଯୋଗାଯୋଗରେ ନଥିବା କଲର୍ଙ୍କ ସମ୍ଵନ୍ଧରେ ସୂଚନା ଦେଖିବାକୁ <xliff:g id="NEW_APP">%s</xliff:g> ସକ୍ଷମ ହେବେ। କେବଳ ଆପଣ ବିଶ୍ଵାସ କରୁଥିବା ଆପ୍ସ ଡିଫଲ୍ଟ କଲ୍ ସ୍କ୍ରିନିଂ ଆପ୍ ଭାବରେ ସେଟ୍ ହେବା ଆବଶ୍ୟକ ଅଟେ।"</string>
<string name="change_default_call_screening_dialog_affirmative" msgid="7162433828280058647">"ଡିଫଲ୍ଟ ସେଟ୍ କରନ୍ତୁ"</string>
- <string name="change_default_call_screening_dialog_negative" msgid="1839266125623106342">"ବାତିଲ୍ କରନ୍ତୁ"</string>
+ <string name="change_default_call_screening_dialog_negative" msgid="1839266125623106342">"ବାତିଲ କରନ୍ତୁ"</string>
<string name="blocked_numbers" msgid="8322134197039865180">"ବ୍ଲକ୍ କରାଯାଇଥିବା ନମ୍ବର୍"</string>
<string name="blocked_numbers_msg" msgid="2797422132329662697">"ବ୍ଲକ୍ କରାଯାଇଥିବା ନମ୍ବର୍ରୁ ଆପଣ କଲ୍ କିମ୍ବା ଟେକ୍ସଟ୍ ଗ୍ରହଣ କରିପାରିବେ ନାହିଁ।"</string>
<string name="block_number" msgid="3784343046852802722">"ଗୋଟିଏ ନମ୍ବର୍ ଯୋଡ଼ନ୍ତୁ"</string>
@@ -73,7 +73,7 @@
<string name="non_primary_user" msgid="315564589279622098">"କେବଳ ଡିଭାଇସ୍ର ମାଲିକ ଅବରୋଧ କରାଯାଇଥିବା ନମ୍ବର୍କୁ ଦେଖିପାରିବେ ଓ ପରିଚାଳନା କରିପାରିବେ।"</string>
<string name="delete_icon_description" msgid="5335959254954774373">"ଅନବ୍ଲକ୍ କରନ୍ତୁ"</string>
<string name="blocked_numbers_butter_bar_title" msgid="582982373755950791">"ଅସ୍ଥାୟୀରୂପେ ଅବରୋଧ ଅଫ୍ ଅଛି"</string>
- <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"ଆପଣ ଗୋଟିଏ ଜରୁରିକାଳୀନ ନମ୍ବର୍କୁ ଡାଏଲ୍ କିମ୍ବା ଟେକ୍ସଟ୍ କରିବା ପରେ, ଜରୁରିକାଳୀନ ସେବା ଆପଣଙ୍କୁ ଯୋଗାଯୋଗ କରିବାକୁ ସୁନିଶ୍ଚିତ କରିବା ପାଇଁ ଅବରୋଧକୁ ବନ୍ଦ କରିଦିଆଯାଇଥାଏ।"</string>
+ <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"ଆପଣ ଗୋଟିଏ ଜରୁରିକାଳୀନ ନମ୍ବରକୁ ଡାଏଲ କିମ୍ବା ଟେକ୍ସଟ କରିବା ପରେ, ଜରୁରିକାଳୀନ ସେବା ଆପଣଙ୍କୁ କଣ୍ଟାକ୍ଟ କରିପାରୁଛି କି ନାହିଁ ତାହା ସୁନିଶ୍ଚିତ କରିବା ପାଇଁ ଅବରୋଧକୁ ବନ୍ଦ କରି ଦିଆଯାଇଛି।"</string>
<string name="blocked_numbers_butter_bar_button" msgid="2704456308072489793">"ବର୍ତ୍ତମାନ ପୁନଃସକ୍ଷମ କରନ୍ତୁ"</string>
<string name="blocked_numbers_number_blocked_message" msgid="4314736791180919167">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> ବ୍ଲକ୍ କରାଯାଇଛି"</string>
<string name="blocked_numbers_number_unblocked_message" msgid="2933071624674945601">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> ଅନବ୍ଲକ୍ କରାଯାଇଛି"</string>
@@ -119,8 +119,9 @@
<string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="2895809176537908791">"କଲ୍ ବ୍ଲକିଂ"</string>
<string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="1713632946174016619">"କଲ୍ ବ୍ଲକିଂକୁ ଅକ୍ଷମ କରାଯାଇଛି"</string>
<string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="6629412508584507377">"ଜରୁରିକାଳୀନ କଲ୍ କରାଗଲା"</string>
- <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="3140411733995271126">"ଜରୁରିକାଳୀନ ସହାୟତା କର୍ମଚାରୀମାନେ ଆପଣଙ୍କୁ ଯୋଗଯୋଗ କରିବା ପାଇଁ କଲ୍ ଅବରୋଧକୁ ଅକ୍ଷମ କରାଯାଇଛି।"</string>
+ <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="3140411733995271126">"ଜରୁରିକାଳୀନ ଉତ୍ତରଦାତାମାନେ ଆପଣଙ୍କୁ କଣ୍ଟାକ୍ଟ କରିବା ପାଇଁ କଲ ଅବରୋଧକୁ ଅକ୍ଷମ କରାଯାଇଛି।"</string>
<string name="developer_title" msgid="9146088855661672353">"ଟେଲେକମ୍ ଡେଭେଲପର୍ ମେନୁ"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"ଜରୁରୀକାଳୀନ କଲ୍ ବେଳେ ଅନ୍ୟ କଲ୍ ଉଠାଇ ପାରିବେ ନାହିଁ।"</string>
- <string name="cancel" msgid="6733466216239934756">"ବାତିଲ୍ କରନ୍ତୁ"</string>
+ <string name="cancel" msgid="6733466216239934756">"ବାତିଲ କରନ୍ତୁ"</string>
+ <string name="back" msgid="6915955601805550206">"ପଛକୁ ଫେରନ୍ତୁ"</string>
</resources>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index bc3d7fa..8d5a4c3 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"<xliff:g id="CALLER">%s</xliff:g> ਦੀ ਕਾਲ ਨੂੰ ਕਿਸੇ ਸੰਕਟਕਾਲੀਨ ਕਾਲ ਦੇ ਚਲਦੇ ਕੱਟ ਦਿੱਤਾ ਗਿਆ ਹੈ।"</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"ਕਿਸੇ ਸੰਕਟਕਾਲੀਨ ਕਾਲ ਕਰਕੇ ਤੁਹਾਡੀ ਕਾਲ ਕੱਟ ਦਿੱਤੀ ਗਈ ਹੈ।"</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Background call"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> has placed a call into the background. This app may be accessing and playing audio over the call."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਕਾਲ \'ਤੇ ਪ੍ਰਕਿਰਿਆ ਕਰ ਰਹੀ ਹੈ। ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਇਹ ਐਪ ਕਾਲ \'ਤੇ ਆਡੀਓ ਤੱਕ ਪਹੁੰਚ ਕਰ ਕੇ ਚਲਾ ਰਹੀ ਹੋਵੇ।"</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> ਨੇ ਕੰਮ ਕਰਨਾ ਬੰਦ ਕਰ ਦਿੱਤਾ"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"ਤੁਹਾਡੀ ਕਾਲ ਨੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਪਹਿਲਾਂ ਤੋਂ ਸਥਾਪਤ ਫ਼ੋਨ ਐਪ ਦੀ ਵਰਤੋਂ ਕੀਤੀ"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"ਕਾਲ ਮਿਊਟ ਕੀਤੀ।"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"ਟੈਲੀਕੋਮ ਵਿਕਾਸਕਾਰ ਮੀਨੂ"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"ਕਿਸੇ ਸੰਕਟਕਾਲੀਨ ਕਾਲ ਦੌਰਾਨ ਹੋਰ ਕਾਲਾਂ ਨਹੀਂ ਲਈਆਂ ਜਾ ਸਕਦੀਆਂ।"</string>
<string name="cancel" msgid="6733466216239934756">"ਰੱਦ ਕਰੋ"</string>
+ <string name="back" msgid="6915955601805550206">"ਪਿੱਛੇ"</string>
</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 958412d..eb8943d 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Połączenie z rozmówcą <xliff:g id="CALLER">%s</xliff:g> zostało przerwane z powodu nawiązania połączenia alarmowego."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Połączenie zostało przerwane z powodu nawiązania połączenia alarmowego."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Połączenie w tle"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"Aplikacja <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> umieściła połączenie w tle. Może ona uzyskiwać dostęp do dźwięku i odtwarzać go podczas połączenia."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"Aplikacja <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> przetwarza połączenie w tle. Może ona uzyskiwać dostęp do dźwięku i odtwarzać go podczas połączenia."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"Aplikacja <xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> nie odpowiada"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Połączenie zostało zrealizowane za pomocą aplikacji do obsługi telefonu zainstalowanej na urządzeniu"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Połączenie wyciszone."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Menu programisty Telecom"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Nie można odbierać rozmów przy nawiązanym połączeniu alarmowym."</string>
<string name="cancel" msgid="6733466216239934756">"Anuluj"</string>
+ <string name="back" msgid="6915955601805550206">"Wstecz"</string>
</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 462e6f6..8fe5015 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"A chamada para <xliff:g id="CALLER">%s</xliff:g> foi desligada porque foi efetuada uma chamada de emergência."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"A chamada foi desligada porque foi efetuada uma chamada de emergência."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Cham. segundo plano"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> colocou uma chamada em segundo plano. Esta app pode estar a aceder e a reproduzir áudio sobre a chamada."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> está a processar uma chamada em segundo plano. Esta app pode estar a aceder e a reproduzir áudio sobre a chamada."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> deixou de responder."</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"A chamada utilizou a app de telefone incluída com o dispositivo."</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Chamada sem som."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Menu do programador de telecomunicações"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Não é possível atender chamadas durante uma chamada de emergência."</string>
<string name="cancel" msgid="6733466216239934756">"Cancelar"</string>
+ <string name="back" msgid="6915955601805550206">"Voltar atrás"</string>
</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 9e9fb32..07521f4 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"A chamada para <xliff:g id="CALLER">%s</xliff:g> foi desconectada porque uma chamada de emergência está sendo realizada."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Sua chamada foi desconectada porque uma chamada de emergência está sendo feita."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Chamada em 2º plano"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"O app <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> colocou uma chamada em segundo plano. Talvez ele esteja acessando e tocando o áudio durante a chamada."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> está processando uma chamada em segundo plano. Talvez ele esteja acessando e tocando o áudio durante a chamada."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"O app <xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> parou de responder"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"A chamada usou o aplicativo de telefone que veio com seu dispositivo"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Chamada sem áudio."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Menu do desenvolvedor de telecomunicação"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Durante uma chamada de emergência, não é possível transferir chamadas para o dispositivo."</string>
<string name="cancel" msgid="6733466216239934756">"Cancelar"</string>
+ <string name="back" msgid="6915955601805550206">"Voltar"</string>
</resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index d0b56f4..0c23d14 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -24,15 +24,15 @@
<string name="notification_missedCallsTitle" msgid="3910479625507893809">"Apeluri nepreluate"</string>
<string name="notification_missedCallsMsg" msgid="5055782736170916682">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> apeluri nepreluate"</string>
<string name="notification_missedCallTicker" msgid="6731461957487087769">"Apel nepreluat de la <xliff:g id="MISSED_CALL_FROM">%s</xliff:g>"</string>
- <string name="notification_missedCall_call_back" msgid="7900333283939789732">"Sunați"</string>
+ <string name="notification_missedCall_call_back" msgid="7900333283939789732">"Sună"</string>
<string name="notification_missedCall_message" msgid="4054698824390076431">"Mesaj"</string>
<string name="notification_disconnectedCall_title" msgid="1790131923692416928">"Apel deconectat"</string>
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Apelul către <xliff:g id="CALLER">%s</xliff:g> a fost deconectat deoarece a fost inițiat un apel de urgență."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Apelul a fost deconectat deoarece a fost inițiat un apel de urgență."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Apel în fundal"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> a inițiat un apel în fundal. Este posibil ca această aplicație să acceseze și să redea mesaje audio peste apel."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> procesează un apel în fundal. Se poate ca aplicația să acceseze și să redea mesaje audio peste apel."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> nu mai răspunde"</string>
- <string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Apelul dvs. a folosit aplicația Telefon instalată pe dispozitiv"</string>
+ <string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Apelul tău a folosit aplicația Telefon instalată pe dispozitiv"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Apel cu sunet dezactivat."</string>
<string name="accessibility_speakerphone_enabled" msgid="555386652061614267">"Difuzor activat."</string>
<string name="respond_via_sms_canned_response_1" msgid="6332561460870382561">"Nu pot acum. Despre ce e vorba?"</string>
@@ -40,7 +40,7 @@
<string name="respond_via_sms_canned_response_3" msgid="6656147963478092035">"Sun eu mai târziu."</string>
<string name="respond_via_sms_canned_response_4" msgid="9141132488345561047">"Nu pot acum. Vorbim mai târziu?"</string>
<string name="respond_via_sms_setting_title" msgid="4762275482898830160">"Răspunsuri rapide"</string>
- <string name="respond_via_sms_setting_title_2" msgid="4914853536609553457">"Editați răspunsurile rapide"</string>
+ <string name="respond_via_sms_setting_title_2" msgid="4914853536609553457">"Editează răspunsurile rapide"</string>
<string name="respond_via_sms_setting_summary" msgid="8054571501085436868"></string>
<string name="respond_via_sms_edittext_dialog_title" msgid="6579353156073272157">"Răspuns rapid"</string>
<string name="respond_via_sms_confirmation_format" msgid="2932395476561267842">"Mesajul a fost trimis la <xliff:g id="PHONE_NUMBER">%s</xliff:g>."</string>
@@ -48,33 +48,33 @@
<string name="enable_account_preference_title" msgid="6949224486748457976">"Conturi pentru apelare"</string>
<string name="outgoing_call_not_allowed_user_restriction" msgid="3424338207838851646">"Sunt permise doar apelurile de urgență."</string>
<string name="outgoing_call_not_allowed_no_permission" msgid="8590468836581488679">"Această aplicație nu poate efectua apeluri fără permisiunea Telefon."</string>
- <string name="outgoing_call_error_no_phone_number_supplied" msgid="7665135102566099778">"Pentru a apela, introduceți un număr valid."</string>
+ <string name="outgoing_call_error_no_phone_number_supplied" msgid="7665135102566099778">"Pentru a apela, introdu un număr valid."</string>
<string name="duplicate_video_call_not_allowed" msgid="5754746140185781159">"Apelul nu poate fi adăugat în acest moment."</string>
<string name="no_vm_number" msgid="2179959110602180844">"Lipsește numărul mesageriei vocale"</string>
<string name="no_vm_number_msg" msgid="1339245731058529388">"Niciun număr de mesagerie vocală nu este stocat pe cardul SIM."</string>
- <string name="add_vm_number_str" msgid="5179510133063168998">"Adăugați numărul"</string>
- <string name="change_default_dialer_dialog_title" msgid="5861469279421508060">"Setați <xliff:g id="NEW_APP">%s</xliff:g> ca aplicație prestabilită a telefonului?"</string>
- <string name="change_default_dialer_dialog_affirmative" msgid="8604665314757739550">"Setați ca prestabilită"</string>
- <string name="change_default_dialer_dialog_negative" msgid="8648669840052697821">"Anulați"</string>
- <string name="change_default_dialer_warning_message" msgid="8461963987376916114">"<xliff:g id="NEW_APP">%s</xliff:g> va putea iniția apeluri și va putea controla toate aspectele acestora. E recomandat să setați ca aplicație prestabilită a telefonului numai aplicații în care aveți încredere."</string>
- <string name="change_default_call_screening_dialog_title" msgid="5365787219927262408">"Setați <xliff:g id="NEW_APP">%s</xliff:g> ca aplicație prestabilită de filtrare apeluri?"</string>
+ <string name="add_vm_number_str" msgid="5179510133063168998">"Adaugă numărul"</string>
+ <string name="change_default_dialer_dialog_title" msgid="5861469279421508060">"Setezi <xliff:g id="NEW_APP">%s</xliff:g> ca aplicație prestabilită a telefonului?"</string>
+ <string name="change_default_dialer_dialog_affirmative" msgid="8604665314757739550">"Setează ca prestabilită"</string>
+ <string name="change_default_dialer_dialog_negative" msgid="8648669840052697821">"Anulează"</string>
+ <string name="change_default_dialer_warning_message" msgid="8461963987376916114">"<xliff:g id="NEW_APP">%s</xliff:g> va putea iniția apeluri și va putea controla toate aspectele acestora. E recomandat să setezi ca aplicație prestabilită a telefonului numai aplicații în care ai încredere."</string>
+ <string name="change_default_call_screening_dialog_title" msgid="5365787219927262408">"Setezi <xliff:g id="NEW_APP">%s</xliff:g> ca aplicație prestabilită de filtrare apeluri?"</string>
<string name="change_default_call_screening_warning_message_for_disable_old_app" msgid="2039830033533243164">"<xliff:g id="OLD_APP">%s</xliff:g> nu va mai putea să filtreze apelurile."</string>
- <string name="change_default_call_screening_warning_message" msgid="9020537562292754269">"<xliff:g id="NEW_APP">%s</xliff:g> va putea să vadă informațiile despre apelanții care nu sunt în agenda dvs. și va putea să blocheze apelurile respective. E recomandat să setați ca aplicație prestabilită de filtrare a apelurilor numai aplicații în care aveți încredere."</string>
+ <string name="change_default_call_screening_warning_message" msgid="9020537562292754269">"<xliff:g id="NEW_APP">%s</xliff:g> va putea să vadă informațiile despre apelanții care nu sunt în agenda ta și va putea să blocheze apelurile respective. E recomandat să setezi ca aplicație prestabilită de filtrare a apelurilor numai aplicații în care ai încredere."</string>
<string name="change_default_call_screening_dialog_affirmative" msgid="7162433828280058647">"Setați ca prestabilită"</string>
- <string name="change_default_call_screening_dialog_negative" msgid="1839266125623106342">"Anulați"</string>
+ <string name="change_default_call_screening_dialog_negative" msgid="1839266125623106342">"Anulează"</string>
<string name="blocked_numbers" msgid="8322134197039865180">"Numere blocate"</string>
- <string name="blocked_numbers_msg" msgid="2797422132329662697">"Nu veți primi apeluri sau mesaje text de la numerele blocate."</string>
- <string name="block_number" msgid="3784343046852802722">"Adăugați un număr"</string>
- <string name="unblock_dialog_body" msgid="2723393535797217261">"Deblocați <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>?"</string>
- <string name="unblock_button" msgid="8732021675729981781">"Deblocați"</string>
- <string name="add_blocked_dialog_body" msgid="8599974422407139255">"Blocați apelurile și mesajele text de la"</string>
+ <string name="blocked_numbers_msg" msgid="2797422132329662697">"Nu vei primi apeluri sau mesaje text de la numerele blocate."</string>
+ <string name="block_number" msgid="3784343046852802722">"Adaugă un număr"</string>
+ <string name="unblock_dialog_body" msgid="2723393535797217261">"Deblochezi <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>?"</string>
+ <string name="unblock_button" msgid="8732021675729981781">"Deblochează"</string>
+ <string name="add_blocked_dialog_body" msgid="8599974422407139255">"Blochează apelurile și mesajele text de la"</string>
<string name="add_blocked_number_hint" msgid="8769422085658041097">"Număr de telefon"</string>
- <string name="block_button" msgid="485080149164258770">"Blocați"</string>
+ <string name="block_button" msgid="485080149164258770">"Blochează"</string>
<string name="non_primary_user" msgid="315564589279622098">"Numai proprietarul dispozitivului poate vedea și gestiona numerele blocate."</string>
- <string name="delete_icon_description" msgid="5335959254954774373">"Deblocați"</string>
+ <string name="delete_icon_description" msgid="5335959254954774373">"Deblochează"</string>
<string name="blocked_numbers_butter_bar_title" msgid="582982373755950791">"Blocarea este dezactivată temporar"</string>
- <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"După ce formați un număr de urgență sau trimiteți un mesaj la acesta, blocarea este dezactivată pentru ca serviciile de urgență să vă poată contacta."</string>
- <string name="blocked_numbers_butter_bar_button" msgid="2704456308072489793">"Reactivați acum"</string>
+ <string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"După ce formezi un număr de urgență sau trimiți un mesaj la acesta, blocarea este dezactivată pentru ca serviciile de urgență să te poată contacta."</string>
+ <string name="blocked_numbers_butter_bar_button" msgid="2704456308072489793">"Reactivează acum"</string>
<string name="blocked_numbers_number_blocked_message" msgid="4314736791180919167">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> este blocat"</string>
<string name="blocked_numbers_number_unblocked_message" msgid="2933071624674945601">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> este deblocat"</string>
<string name="blocked_numbers_block_emergency_number_message" msgid="4198550501500893890">"Numărul de urgență nu poate fi blocat."</string>
@@ -82,14 +82,14 @@
<string name="toast_personal_call_msg" msgid="5817631570381795610">"Utilizarea telefonului personal pentru a apela"</string>
<string name="notification_incoming_call" msgid="1233481138362230894">"Apel <xliff:g id="CALL_VIA">%1$s</xliff:g> de la <xliff:g id="CALL_FROM">%2$s</xliff:g>"</string>
<string name="notification_incoming_video_call" msgid="5795968314037063900">"Apel video <xliff:g id="CALL_VIA">%1$s</xliff:g> de la <xliff:g id="CALL_FROM">%2$s</xliff:g>"</string>
- <string name="answering_ends_other_call" msgid="8653544281903986641">"Dacă răspundeți, apelul dvs. <xliff:g id="CALL_VIA">%1$s</xliff:g> va fi încheiat."</string>
- <string name="answering_ends_other_calls" msgid="3702302838456922535">"Dacă răspundeți, apelurile dvs. <xliff:g id="CALL_VIA">%1$s</xliff:g> vor fi încheiate."</string>
- <string name="answering_ends_other_video_call" msgid="8572022039304239958">"Dacă răspundeți, apelul video <xliff:g id="CALL_VIA">%1$s</xliff:g> va fi încheiat."</string>
- <string name="answering_ends_other_managed_call" msgid="4031778317409881805">"Dacă răspundeți, apelul în curs va fi încheiat."</string>
- <string name="answering_ends_other_managed_calls" msgid="3974069768615307659">"Dacă răspundeți, apelurile în curs vor fi încheiate."</string>
- <string name="answering_ends_other_managed_video_call" msgid="1988508241432031327">"Dacă răspundeți, apelul video în curs va fi încheiat."</string>
- <string name="answer_incoming_call" msgid="2045888814782215326">"Răspundeți"</string>
- <string name="decline_incoming_call" msgid="922147089348451310">"Respingeți"</string>
+ <string name="answering_ends_other_call" msgid="8653544281903986641">"Dacă răspunzi, apelul tău <xliff:g id="CALL_VIA">%1$s</xliff:g> va fi încheiat."</string>
+ <string name="answering_ends_other_calls" msgid="3702302838456922535">"Dacă răspunzi, apelurile tale <xliff:g id="CALL_VIA">%1$s</xliff:g> vor fi încheiate."</string>
+ <string name="answering_ends_other_video_call" msgid="8572022039304239958">"Dacă răspunzi, apelul video <xliff:g id="CALL_VIA">%1$s</xliff:g> va fi încheiat."</string>
+ <string name="answering_ends_other_managed_call" msgid="4031778317409881805">"Dacă răspunzi, apelul în curs va fi încheiat."</string>
+ <string name="answering_ends_other_managed_calls" msgid="3974069768615307659">"Dacă răspunzi, apelurile în curs vor fi încheiate."</string>
+ <string name="answering_ends_other_managed_video_call" msgid="1988508241432031327">"Dacă răspunzi, apelul video în curs va fi încheiat."</string>
+ <string name="answer_incoming_call" msgid="2045888814782215326">"Răspunde"</string>
+ <string name="decline_incoming_call" msgid="922147089348451310">"Respinge"</string>
<string name="cant_call_due_to_no_supported_service" msgid="1635626384149947077">"Apelul nu poate fi inițiat deoarece nu există conturi pentru apelare compatibile cu apeluri de acest tip."</string>
<string name="cant_call_due_to_ongoing_call" msgid="8004235328451385493">"Apelul nu poate fi inițiat din cauza apelului <xliff:g id="OTHER_CALL">%1$s</xliff:g>."</string>
<string name="cant_call_due_to_ongoing_calls" msgid="6379163795277824868">"Apelul nu poate fi inițiat din cauza apelurilor <xliff:g id="OTHER_CALL">%1$s</xliff:g>."</string>
@@ -100,27 +100,28 @@
<string name="notification_channel_background_calls" msgid="7785659903711350506">"Apeluri în fundal"</string>
<string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Apeluri deconectate"</string>
<string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Aplicații pentru telefon blocate"</string>
- <string name="alert_outgoing_call" msgid="5319895109298927431">"Dacă inițiați acest apel, cel din <xliff:g id="OTHER_APP">%1$s</xliff:g> va fi încheiat."</string>
- <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Alegeți cum vreți să inițiați apelul"</string>
- <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Redirecționați apelul folosind <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string>
+ <string name="alert_outgoing_call" msgid="5319895109298927431">"Dacă inițiezi acest apel, cel din <xliff:g id="OTHER_APP">%1$s</xliff:g> va fi încheiat."</string>
+ <string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Alege cum vrei să inițiezi apelul"</string>
+ <string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Redirecționezi apelul folosind <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string>
<string name="alert_place_unredirect_outgoing_call" msgid="2467608535225764006">"Apelează folosind numărul meu"</string>
- <string name="alert_redirect_outgoing_call_timeout" msgid="5568101425637373060">"Apelul nu poate fi inițiat de <xliff:g id="OTHER_APP">%1$s</xliff:g>. Încercați să folosiți o aplicație de redirecționare a apelurilor sau să contactați dezvoltatorul pentru a solicita ajutorul."</string>
+ <string name="alert_redirect_outgoing_call_timeout" msgid="5568101425637373060">"Apelul nu poate fi inițiat de <xliff:g id="OTHER_APP">%1$s</xliff:g>. Încearcă să folosești o aplicație de redirecționare a apelurilor sau să contactezi dezvoltatorul pentru a solicita ajutorul."</string>
<string name="phone_settings_call_blocking_txt" msgid="7311523114822507178">"Blocarea apelurilor"</string>
<string name="phone_settings_number_not_in_contact_txt" msgid="2602249106007265757">"Numere care nu sunt în Agendă"</string>
- <string name="phone_settings_number_not_in_contact_summary_txt" msgid="963327038085718969">"Blocați numerele care nu sunt înregistrate în Agendă"</string>
+ <string name="phone_settings_number_not_in_contact_summary_txt" msgid="963327038085718969">"Blochează numerele care nu sunt înregistrate în Agendă"</string>
<string name="phone_settings_private_num_txt" msgid="6339272760338475619">"Privat"</string>
- <string name="phone_settings_private_num_summary_txt" msgid="6755758240544021037">"Blocați apelanții care nu își afișează numărul"</string>
+ <string name="phone_settings_private_num_summary_txt" msgid="6755758240544021037">"Blochează apelanții care nu își afișează numărul"</string>
<string name="phone_settings_payphone_txt" msgid="5003987966052543965">"Telefon public"</string>
- <string name="phone_settings_payphone_summary_txt" msgid="3936631076065563665">"Blocați apelurile de la telefoane publice"</string>
+ <string name="phone_settings_payphone_summary_txt" msgid="3936631076065563665">"Blochează apelurile de la telefoane publice"</string>
<string name="phone_settings_unknown_txt" msgid="3577926178354772728">"Necunoscut"</string>
- <string name="phone_settings_unknown_summary_txt" msgid="5446657192535779645">"Blocați apelurile de la apelanți neidentificați"</string>
+ <string name="phone_settings_unknown_summary_txt" msgid="5446657192535779645">"Blochează apelurile de la apelanți neidentificați"</string>
<string name="phone_settings_unavailable_txt" msgid="825918186053980858">"Indisponibil"</string>
- <string name="phone_settings_unavailable_summary_txt" msgid="8221686031038282633">"Blocați apelurile unde numărul de telefon este indisponibil"</string>
+ <string name="phone_settings_unavailable_summary_txt" msgid="8221686031038282633">"Blochează apelurile unde numărul de telefon este indisponibil"</string>
<string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="2895809176537908791">"Blocarea apelurilor"</string>
<string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="1713632946174016619">"Blocarea apelurilor este dezactivată."</string>
<string name="phone_strings_emergency_call_made_dialog_title_txt" msgid="6629412508584507377">"S-a efectuat un apel de urgență."</string>
- <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="3140411733995271126">"Blocarea apelurilor a fost dezactivată pentru a permite serviciilor de urgență să vă contacteze."</string>
+ <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt" msgid="3140411733995271126">"Blocarea apelurilor a fost dezactivată pentru a permite serviciilor de urgență să te contacteze."</string>
<string name="developer_title" msgid="9146088855661672353">"Meniu pentru dezvoltatori de telecomunicații"</string>
- <string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Nu puteți răspunde la apeluri în timpul unui apel de urgență."</string>
- <string name="cancel" msgid="6733466216239934756">"Anulați"</string>
+ <string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Nu poți răspunde la apeluri în timpul unui apel de urgență."</string>
+ <string name="cancel" msgid="6733466216239934756">"Anulează"</string>
+ <string name="back" msgid="6915955601805550206">"Înapoi"</string>
</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 6382c7b..76deddb 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Вызов абонента <xliff:g id="CALLER">%s</xliff:g> был прекращен, так как осуществляется экстренный вызов."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Ваш вызов прекращен, так как осуществляется экстренный вызов."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Фоновый вызов"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"Приложение <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> перевело вызов в фоновый режим. Это приложение может получать доступ к аудио вызова или воспроизводить в нем свое аудио."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> обрабатывает звонок в фоновом режиме. Это приложение может получать доступ к аудио вызова или воспроизводить в нем свое аудио."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> не отвечает"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Вызов был сделан с использованием приложения, которое установлено на ваше устройство производителем."</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Звук выключен."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Меню разработчика Telecom"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Невозможно принять вызов, когда уже выполняется экстренный вызов."</string>
<string name="cancel" msgid="6733466216239934756">"Отмена"</string>
+ <string name="back" msgid="6915955601805550206">"Назад"</string>
</resources>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index 6cbaaa5..8f9674c 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"<xliff:g id="CALLER">%s</xliff:g> වෙත ඇමතුම හදිසි ඇමතුමක් ගනිමින් ඇති නිසා විසන්ධි කර ඇත."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"හදිසි ඇමතුමක් ගනිමින් පැවතීම හේතුවෙන් ඔබේ ඇමතුම විසන්ධි කර ඇත."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"පසුබිම් ඇමතුම"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> පසුබිම තුළට ඇමතුමක් ගෙන ඇත. මෙම යෙදුම ඇමතුම හරහා ඕඩියෝ වෙත ප්රවේශ වෙමින් සහ වාදනය කරමින් සිටිය හැකිය."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> පසුබිමේ ඇමතුමක් සකසමින් සිටී. මෙම යෙදුම ඇමතුම හරහා ඕඩියෝ වෙත ප්රවේශ වෙමින් සහ වාදනය කරමින් සිටිය හැක."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> ප්රතිචාර දැක්වීම නතර කළේය"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"ඔබේ ඇමතුම ඔබේ උපාංගය සමග පැමිණි දුරකථන යෙදුම භාවිත කළේය"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"ඇමතුම නිශ්ශබ්දයි."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"ටෙලිකොම් සංවර්ධක මෙනුව"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"හදිසි ඇමතුමක් අතරතුර ඇමතුම් ගත නොහැකිය."</string>
<string name="cancel" msgid="6733466216239934756">"අවලංගු කරන්න"</string>
+ <string name="back" msgid="6915955601805550206">"ආපසු"</string>
</resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index c49ffc5..af94613 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Hovor kontaktu <xliff:g id="CALLER">%s</xliff:g> bol zrušený, aby mohlo prebehnúť tiesňové volanie."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Váš hovor bol zrušený, aby mohlo prebehnúť tiesňové volanie."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Hovor na pozadí"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"Aplikácia <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> umiestnila hovor do pozadia. Táto aplikácia môže mať počas hovoru prístup k zvuku a prehrávať ho."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> spracúva hovor na pozadí. Táto aplikácia môže mať počas hovoru prístup k zvuku a prehrávať ho."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"Aplikácia <xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> prestala reagovať"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Na hovor bola použitá telefónna aplikácia, ktorá bola vopred nainštalovaná vo vašom zariadení"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Zvuk hovoru bol vypnutý."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Ponuka pre vývojárov Telecomu"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Počas tiesňového volania nie je možné prijímať hovory."</string>
<string name="cancel" msgid="6733466216239934756">"Zrušiť"</string>
+ <string name="back" msgid="6915955601805550206">"Späť"</string>
</resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 5bc9d83..8a26451 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Klic za stik <xliff:g id="CALLER">%s</xliff:g> je prekinjen zaradi vzpostavljanja klica v sili."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Klic je prekinjen zaradi vzpostavljanja klica v sili."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Klic v ozadju"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"Aplikacija <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> je klic premaknila v ozadje. Ta aplikacija morda dostopa do zvoka in ga predvaja prek klica."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> obdeluje klic v ozadju. Ta aplikacija morda dostopa do zvoka in ga predvaja prek klica."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"Aplikacija <xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> se ne odziva več"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Klic je bil opravljen prek aplikacije za klicanje, ki jo je v napravo namestil proizvajalec"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Klic izključen."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Meni za razvijalce Telecom"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Med klicem v sili ni mogoče sprejeti klicev."</string>
<string name="cancel" msgid="6733466216239934756">"Prekliči"</string>
+ <string name="back" msgid="6915955601805550206">"Nazaj"</string>
</resources>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index db3eda3..dd0b1a1 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Telefonata me <xliff:g id="CALLER">%s</xliff:g> është shkëputur sepse është kryer një telefonatë urgjence."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Telefonata jote është shkëputur sepse është kryer një telefonatë urgjence."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Telefonatë në sfond"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> e ka vendosur një telefonatë në sfond. Ky aplikacion mund të ketë qasje dhe të luajë audio mbi telefonatë."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> po përpunon një telefonatë në sfond. Ky aplikacion mund të ketë qasje dhe të luajë audio mbi telefonatë."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> nuk përgjigjet më"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Telefonata jote ka përdorur aplikacionin e telefonit që ke marrë me pajisjen tënde"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Telefonata kaloi në heshtje."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Menyja e zhvilluesit të telekomunikimit"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Nuk mund të marrësh telefonata kur je në një telefonatë urgjence."</string>
<string name="cancel" msgid="6733466216239934756">"Anulo"</string>
+ <string name="back" msgid="6915955601805550206">"Pas"</string>
</resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 36bf352..e9cc96f 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Позив са <xliff:g id="CALLER">%s</xliff:g> је прекинут јер се упућује хитни позив."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Позив је прекинут јер се упућује хитни позив."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Позив у позадини"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"Апликација <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> је упутила позив у позадини. Она може да приступа звуку и пушта га током позива."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"Апликација <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> обрађује позив у позадини. Она може да приступа звуку и да га пушта током позива."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> више не реагује"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Позив је користио апликацију за телефонирање коју сте добили уз уређај"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Звук позива је искључен."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Мени за програмере Telecom-а"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"За време хитног позива није могуће преузимати друге позиве."</string>
<string name="cancel" msgid="6733466216239934756">"Откажи"</string>
+ <string name="back" msgid="6915955601805550206">"Назад"</string>
</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 34a3b6d..67e7735 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Samtalet <xliff:g id="CALLER">%s</xliff:g> kopplades från eftersom ett nödsamtal ringdes."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Samtalets kopplades bort på grund av ett nödsamtal."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Bakgrundssamtal"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> har ringt ett samtal i bakgrunden. Denna app kan få åtkomst till och spela upp ljud från samtalet."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> bearbetar ett samtal i bakgrunden. Den här appen kan få åtkomst till och spela upp ljud från samtalet."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> slutade svara"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Samtalet använde telefonappen som medföljer enheten"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Samtalets ljud avstängt."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Meny för telekomutvecklare"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Det går inte att besvara samtal medan ett nödsamtal pågår."</string>
<string name="cancel" msgid="6733466216239934756">"Avbryt"</string>
+ <string name="back" msgid="6915955601805550206">"Tillbaka"</string>
</resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 1eb5293..9f6d570 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Simu uliyompigia <xliff:g id="CALLER">%s</xliff:g> imekatwa kwa sababu kuna simu ya dharura inayopigwa."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Simu yako imekatwa kwa sababu kuna simu ya dharura inayopigwa."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Simu ya chinichini"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> inapiga simu chinichini. Huenda programu hii inafikia na kucheza sauti huku simu ikiendelea."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> inachakata simu fulani chinichini. Huenda programu hii inafikia na kucheza sauti huku simu ikiendelea."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> imeacha kufanya kazi"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Ulipiga simu kwa kutumia Programu ya simu iliyokuja na kifaa chako"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Simu imezimwa."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Menyu ya Msanidi programu wa Telecom"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Huwezi kupokea simu nyingine wakati unashiriki katika simu ya dharura."</string>
<string name="cancel" msgid="6733466216239934756">"Ghairi"</string>
+ <string name="back" msgid="6915955601805550206">"Rudi nyuma"</string>
</resources>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index 90a33a7..39f199a 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"அவசர அழைப்பு மேற்கொள்ளப்பட்டதால் <xliff:g id="CALLER">%s</xliff:g> உடனான அழைப்பு துண்டிக்கப்பட்டது."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"அவசர அழைப்பு மேற்கொள்ளப்படுவதால் உங்கள் அழைப்பு துண்டிக்கப்பட்டுள்ளது."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"பின்னணி அழைப்பு"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"அழைப்பை பின்னணியில் செயல்படும் வகையில் <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> மாற்றியுள்ளது. அழைப்பின் மூலமாக இந்த ஆப்ஸ் ஆடியோவை அணுகி இயக்கக்கூடும்."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> அழைப்பைப் பின்னணியில் செயலாக்குகிறது. அழைப்பின்போதே இந்த ஆப்ஸ் ஆடியோவை அணுகி அதைச் செயலாக்கக்கூடும்."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> செயலிழந்துவிட்டது"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"உங்கள் சாதனத்துடன் கிடைக்கும் மொபைல் ஆப்ஸ் மூலம் அழைப்பு மேற்கொள்ளப்பட்டது"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"அழைப்பு முடக்கப்பட்டது."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"டெலிகாம் டெவெலப்பர் மெனு"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"அவசர அழைப்பின்போது அழைப்புகளை ஏற்க முடியாது."</string>
<string name="cancel" msgid="6733466216239934756">"ரத்துசெய்"</string>
+ <string name="back" msgid="6915955601805550206">"பின்செல்"</string>
</resources>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index b904115..86a09a8 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"అత్యవసర కాల్ చేయబడినందున <xliff:g id="CALLER">%s</xliff:g>తో కాల్ డిస్కనెక్ట్ చేయబడింది."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"అత్యవసర కాల్ చేయబడినందున మీ కాల్ డిస్కనెక్ట్ చేయబడింది."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"నేపథ్యం కాల్"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> కాల్ను నేపథ్యంలోకి పంపింది. కాల్ ద్వారా ఈ యాప్, ఆడియోను యాక్సెస్ ఇంకా ప్లే చేస్తుండవచ్చు."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> బ్యాక్గ్రౌండ్లో కాల్ను ప్రాసెస్ చేస్తోంది. ఈ యాప్ కాల్ ద్వారా ఆడియోను యాక్సెస్ చేసి ప్లే చేస్తుండవచ్చు."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> స్పందించడం ఆగిపోయింది"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"మీ కాల్, మీ పరికరంతో వచ్చిన ఫోన్ యాప్ను ఉపయోగించింది"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"కాల్ మ్యూట్ చేయబడింది."</string>
@@ -52,7 +52,7 @@
<string name="duplicate_video_call_not_allowed" msgid="5754746140185781159">"ఈ సమయంలో కాల్ను జోడించడం సాధ్యపడదు."</string>
<string name="no_vm_number" msgid="2179959110602180844">"వాయిస్ మెయిల్ నంబర్ లేదు"</string>
<string name="no_vm_number_msg" msgid="1339245731058529388">"సిమ్ కార్డులో వాయిస్ మెయిల్ నంబర్ ఏదీ నిల్వ చేయబడలేదు."</string>
- <string name="add_vm_number_str" msgid="5179510133063168998">"నంబర్ను జోడించు"</string>
+ <string name="add_vm_number_str" msgid="5179510133063168998">"నంబర్ను జోడించండి"</string>
<string name="change_default_dialer_dialog_title" msgid="5861469279421508060">"<xliff:g id="NEW_APP">%s</xliff:g>ను మీ ఆటోమేటిక్ ఫోన్ యాప్గా చేయాలా?"</string>
<string name="change_default_dialer_dialog_affirmative" msgid="8604665314757739550">"ఆటోమేటిక్గా సెట్ చేయండి"</string>
<string name="change_default_dialer_dialog_negative" msgid="8648669840052697821">"రద్దు చేయి"</string>
@@ -69,12 +69,12 @@
<string name="unblock_button" msgid="8732021675729981781">"అన్బ్లాక్ చేయి"</string>
<string name="add_blocked_dialog_body" msgid="8599974422407139255">"దీని నుండి కాల్స్ మరియు మెసేజ్లను బ్లాక్ చేయండి"</string>
<string name="add_blocked_number_hint" msgid="8769422085658041097">"ఫోన్ నంబర్"</string>
- <string name="block_button" msgid="485080149164258770">"బ్లాక్ చేయి"</string>
- <string name="non_primary_user" msgid="315564589279622098">"కేవలం పరికర యజమాని మాత్రమే బ్లాక్ చేసిన నంబర్లను వీక్షించగలరు మరియు నిర్వహించగలరు."</string>
+ <string name="block_button" msgid="485080149164258770">"బ్లాక్ చేయండి"</string>
+ <string name="non_primary_user" msgid="315564589279622098">"కేవలం పరికర యజమాని మాత్రమే బ్లాక్ చేసిన నంబర్లను చూడగలరు మరియు నిర్వహించగలరు."</string>
<string name="delete_icon_description" msgid="5335959254954774373">"అన్బ్లాక్ చేస్తుంది"</string>
<string name="blocked_numbers_butter_bar_title" msgid="582982373755950791">"బ్లాకింగ్ తాత్కాలికంగా ఆఫ్ చేయబడింది"</string>
<string name="blocked_numbers_butter_bar_body" msgid="1261213114919301485">"మీరు అత్యవసర నంబర్కి డయల్ చేసాక లేదా వచన మెసేజ్ పంపాక, అత్యవసర సేవలు తిరిగి మిమ్మల్ని సంప్రదించగలిగేలా చేయడానికి బ్లాకింగ్ ఆఫ్ చేయబడుతుంది."</string>
- <string name="blocked_numbers_butter_bar_button" msgid="2704456308072489793">"ఇప్పుడే మళ్లీ ప్రారంభించు"</string>
+ <string name="blocked_numbers_butter_bar_button" msgid="2704456308072489793">"ఇప్పుడే మళ్లీ ప్రారంభించండి"</string>
<string name="blocked_numbers_number_blocked_message" msgid="4314736791180919167">"<xliff:g id="BLOCKED_NUMBER">%1$s</xliff:g> బ్లాక్ చేయబడింది"</string>
<string name="blocked_numbers_number_unblocked_message" msgid="2933071624674945601">"<xliff:g id="UNBLOCKED_NUMBER">%1$s</xliff:g> అన్బ్లాక్ చేయబడింది"</string>
<string name="blocked_numbers_block_emergency_number_message" msgid="4198550501500893890">"అత్యవసర నంబర్ను బ్లాక్ చేయడం సాధ్యపడలేదు."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"టెలికామ్ డెవలపర్ మెనూ"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"అత్యవసర కాల్లో వున్నప్పుడు కాల్స్ను స్వీకరించడానికి వీలుపడదు."</string>
<string name="cancel" msgid="6733466216239934756">"రద్దు చేయండి"</string>
+ <string name="back" msgid="6915955601805550206">"వెనుకకు"</string>
</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 4f1c825..8244436 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"สายที่โทรหา <xliff:g id="CALLER">%s</xliff:g> ถูกตัดเนื่องจากมีการโทรหาหมายเลขฉุกเฉิน"</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"สายของคุณถูกตัดเพราะมีการโทรหาหมายเลขฉุกเฉิน"</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"การโทรในเบื้องหลัง"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ได้ทำการโทรในเบื้องหลัง แอปนี้อาจกำลังเข้าถึงและเล่นเสียงผ่านการโทร"</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> กำลังประมวลผลการโทรในเบื้องหลัง โดยแอปนี้อาจเข้าถึงและเล่นเสียงผ่านการโทร"</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> หยุดตอบสนอง"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"สายของคุณใช้แอปโทรศัพท์ที่มาพร้อมกับอุปกรณ์"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"ปิดเสียงการโทร"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"เมนูนักพัฒนาโทรคมนาคม"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"การโทรนั้นจะทำขณะอยู่ในการโทรฉุกเฉินไม่ได้"</string>
<string name="cancel" msgid="6733466216239934756">"ยกเลิก"</string>
+ <string name="back" msgid="6915955601805550206">"กลับ"</string>
</resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 85c1b3f..9bb9dfb 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Nadiskonekta ang tawag kay <xliff:g id="CALLER">%s</xliff:g> dahil sa ginagawang pang-emergency na tawag."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Nadiskonekta ang iyong tawag dahil sa ginagawang pang-emergency na tawag."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Tawag sa background"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"Naglagay ng tawag ang <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> sa background. Posibleng ina-access at pine-play ng app na ito ang audio sa tawag."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"Pinoproseso ng <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ang isang tawag sa background. Posibleng ina-access at pine-play ng app na ito ang audio sa tawag."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"Huminto ang <xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> sa pagtugon"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Ginamit ng tawag mo ang app na telepono na kasama sa iyong device"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Naka-mute ang tawag."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Menu ng Telecom Developer"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Hindi puwedeng sumagot ng mga tawag habang nasa emergency na tawag."</string>
<string name="cancel" msgid="6733466216239934756">"Kanselahin"</string>
+ <string name="back" msgid="6915955601805550206">"Bumalik"</string>
</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 66da8ab..b31076b 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Bir acil durum araması yapıldığı için <xliff:g id="CALLER">%s</xliff:g> ile olan görüşmenin bağlantısı kesildi."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Bir acil durum araması yapıldığı için görüşmenizin bağlantısı kesildi."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Arka plandaki arama"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> arka plana bir arama yerleştirdi. Bu uygulama arama üzerinden sese erişiyor ve ses çalıyor olabilir."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>, bir aramayı arka planda işliyor. Bu uygulama, arama üzerinden sese erişiyor ve bu sesi çalıyor olabilir."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> yanıt vermeyi durdurdu"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Görüşmeniz için, cihazınızla gelen telefon uygulaması kullanıldı"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Çağrı sesi kapatıldı."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telekomünikasyon Geliştirici Menüsü"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Acil durum araması sırasında arama alınamaz."</string>
<string name="cancel" msgid="6733466216239934756">"İptal"</string>
+ <string name="back" msgid="6915955601805550206">"Geri"</string>
</resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 6eddc79..c09756b 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Виклик абонента <xliff:g id="CALLER">%s</xliff:g> припинено, оскільки здійснюється екстрений виклик."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Виклик перервано, оскільки здійснюється екстрений виклик."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"У фоновий режим"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"Додаток <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> перевів виклик у фоновий режим і може відтворювати аудіо під час виклику."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"Додаток <xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> обробляє виклик у фоновому режимі. Він може отримувати доступ до аудіо виклику та відтворювати під час нього своє аудіо."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"Додаток <xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> не відповідає"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Поточний дзвінок було перенаправлено в додаток, що постачається разом із пристроєм"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Звук виклику вимкнено."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Меню розробника Telecom"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Під час екстрених викликів не можна приймати інші."</string>
<string name="cancel" msgid="6733466216239934756">"Скасувати"</string>
+ <string name="back" msgid="6915955601805550206">"Назад"</string>
</resources>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index c42f5d9..b2739aa 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"ہنگامی کال کی وجہ سے <xliff:g id="CALLER">%s</xliff:g> کی کال کو غیر منسلک کر دیا گیا ہے۔"</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"ہنگامی کال لگائے جانے کی وجہ سے آپ کی کال غیر منسلک ہوگئی ہے۔"</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"پس منظر کی کال"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> نے پس منظر میں کال لگا دیا ہے۔ یہ ایپ کال کے دوران آواز تک رسائی حاصل اور چلا سکتی ہے۔"</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> پس منظر میں کال پر کارروائی کر رہی ہے۔ یہ ایپ کال کے دوران آواز تک رسائی حاصل اور چلا سکتی ہے۔"</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> نے جواب دینا بند کر دیا"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"آپ کی کال نے آپ کے آلہ کے ساتھ آئی ہوئی فون ایپ کا استعمال کیا"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"کال خاموش کر دی گئی۔"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"ٹیلی کام ڈویلپر مینو"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"ہنگامی کال کے دوران کالز نہیں لی جائیں گی۔"</string>
<string name="cancel" msgid="6733466216239934756">"منسوخ کریں"</string>
+ <string name="back" msgid="6915955601805550206">"پیچھے"</string>
</resources>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index c3ae499..b7e6c14 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Favqulodda chaqiruv amalga oshirilayotgani uchun <xliff:g id="CALLER">%s</xliff:g> bilan suhbatingiz tugatildi."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Favqulodda chaqiruv amalga oshirilayotgani uchun joriy chaqiruvingiz to‘xtatildi."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Orqa fondagi chaqiruv"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> ilovasi chaqiruvni orqa fonga joyladi. Bu ilova ovozli chaqiruvga kirishi yoki unda audio ijro etishi mumkin."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> chaqiruvni fonda qayta ishlamoqda. Bu ilova ovozli chaqiruvga kirishi yoki unda audio ijro etishi mumkin."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> javob bermayapti"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Chaqiruv qurilmangizga avvaldan o‘rnatilgan ilova orqali amalga oshirildi"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Qo‘ng‘iroq ovozi o‘chirildi."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Telecom dasturchisi menyusi"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Favqulodda chaqiruv vaqtida boshqa chaqiruvlarni qabul qilish imkonsiz."</string>
<string name="cancel" msgid="6733466216239934756">"Bekor qilish"</string>
+ <string name="back" msgid="6915955601805550206">"Orqaga"</string>
</resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index dfe6b7b..f7addde 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Cuộc gọi đến <xliff:g id="CALLER">%s</xliff:g> đã bị ngắt kết nối do một cuộc gọi khẩn cấp được thực hiện."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Cuộc gọi của bạn đã bị ngắt kết nối do một cuộc gọi khẩn cấp đang được thực hiện."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Cuộc gọi trong nền"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> đã gọi điện ở chế độ nền. Ứng dụng này có thể đang truy cập và phát âm thanh qua cuộc gọi."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> đang xử lý cuộc gọi ở chế độ nền. Ứng dụng này có thể đang truy cập và phát âm thanh qua cuộc gọi."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> đã dừng phản hồi"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Cuộc gọi của bạn đã dùng ứng dụng dành cho điện thoại đi kèm với thiết bị"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Đã tắt tiếng cuộc gọi."</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Menu nhà phát triển dịch vụ viễn thông"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Bạn không thể gọi điện trong khi thực hiện cuộc gọi khẩn cấp."</string>
<string name="cancel" msgid="6733466216239934756">"Hủy"</string>
+ <string name="back" msgid="6915955601805550206">"Quay lại"</string>
</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index d91c260..de9376c 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"由于要进行紧急呼叫,与 <xliff:g id="CALLER">%s</xliff:g> 的通话已中断。"</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"由于要进行紧急呼叫,您的通话已中断。"</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"后台通话"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> 已将通话切换到后台进行。此应用可以接入通话,并播放通话音频。"</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"“<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>”正在后台处理通话。此应用可在通话期间获取和播放音频。"</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g>已停止响应"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"系统使用您设备自带的电话应用拨打了电话"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"通话已静音。"</string>
@@ -89,7 +89,7 @@
<string name="answering_ends_other_managed_calls" msgid="3974069768615307659">"如果接听此来电,您当前的通话会中断。"</string>
<string name="answering_ends_other_managed_video_call" msgid="1988508241432031327">"如果接听此来电,您当前的视频通话会中断。"</string>
<string name="answer_incoming_call" msgid="2045888814782215326">"接听"</string>
- <string name="decline_incoming_call" msgid="922147089348451310">"拒绝"</string>
+ <string name="decline_incoming_call" msgid="922147089348451310">"拒接"</string>
<string name="cant_call_due_to_no_supported_service" msgid="1635626384149947077">"无法拨出电话,因为没有通话帐号支持拨打这类电话。"</string>
<string name="cant_call_due_to_ongoing_call" msgid="8004235328451385493">"由于当前正在进行 <xliff:g id="OTHER_CALL">%1$s</xliff:g> 通话,因此无法拨打电话。"</string>
<string name="cant_call_due_to_ongoing_calls" msgid="6379163795277824868">"由于当前正在进行 <xliff:g id="OTHER_CALL">%1$s</xliff:g> 通话,因此无法拨打电话。"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"电信开发者菜单"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"紧急呼叫时无法接听来电。"</string>
<string name="cancel" msgid="6733466216239934756">"取消"</string>
+ <string name="back" msgid="6915955601805550206">"返回"</string>
</resources>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index df1a850..1085f1b 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"因撥打緊急電話緣故,與<xliff:g id="CALLER">%s</xliff:g>的通話已中斷。"</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"因撥打緊急電話緣故,您的通話已中斷。"</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"背景通話"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"「<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>」已將通話放到背景。這個應用程式可以存取該通話,並透過該通話播放音訊。"</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"「<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>」正在處理背景中的通話。這個應用程式或會存取通話,或是在通話中播放音訊。"</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g>已停止回應"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"您使用了裝置隨付的手機應用程式來通話"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"通話已靜音。"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"電信開發商選單"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"使用緊急電話期間無法接聽電話。"</string>
<string name="cancel" msgid="6733466216239934756">"取消"</string>
+ <string name="back" msgid="6915955601805550206">"返回"</string>
</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 39359b3..cad9bdf 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"由於你正在撥打緊急電話,因此你與<xliff:g id="CALLER">%s</xliff:g>的通話已中斷。"</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"你撥出了緊急電話,因此目前的通話已中斷。"</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"背景通話"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"「<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>」已將通話切換到在背景進行。這個應用程式可能會在通話期間存取及播放音訊。"</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"「<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g>」正在背景處理通話,因此可能會在通話期間存取及播放音訊。"</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"「<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g>」已停止回應"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"目前是透過裝置內建的電話應用程式進行通話"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"通話已靜音。"</string>
@@ -39,7 +39,7 @@
<string name="respond_via_sms_canned_response_2" msgid="2052951316129952406">"我待會就回電。"</string>
<string name="respond_via_sms_canned_response_3" msgid="6656147963478092035">"我晚點回電。"</string>
<string name="respond_via_sms_canned_response_4" msgid="9141132488345561047">"我現在不方便講話,晚點再打來好嗎?"</string>
- <string name="respond_via_sms_setting_title" msgid="4762275482898830160">"快速回應"</string>
+ <string name="respond_via_sms_setting_title" msgid="4762275482898830160">"應答短訊"</string>
<string name="respond_via_sms_setting_title_2" msgid="4914853536609553457">"編輯快速回應"</string>
<string name="respond_via_sms_setting_summary" msgid="8054571501085436868"></string>
<string name="respond_via_sms_edittext_dialog_title" msgid="6579353156073272157">"快速回應"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"電信開發人員選單"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"如果裝置已撥打緊急電話,就無法進行其他通話。"</string>
<string name="cancel" msgid="6733466216239934756">"取消"</string>
+ <string name="back" msgid="6915955601805550206">"返回"</string>
</resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index a98e4f0..cea9f28 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -30,7 +30,7 @@
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"Ikholi eya ku-<xliff:g id="CALLER">%s</xliff:g> inqanyuliwe ngenxa yekholi yesimo esiphuthumayo efakwayo."</string>
<string name="notification_disconnectedCall_generic_body" msgid="5282765206349184853">"Ikholi yakho inqanyuliwe ngenxa yekholi yesimo esiphuthumayo eyenziwe."</string>
<string name="notification_audioProcessing_title" msgid="1619035039880584575">"Ikholi engemuva"</string>
- <string name="notification_audioProcessing_body" msgid="6397005913770420388">"<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> yenze ikholi ngemuva. Kungenzeka ukuthi lolu hlelo lokusebenza lufinyelela futhi ludlala okulalelwayo ngaphezu kwekholi."</string>
+ <string name="notification_audioProcessing_body" msgid="8811420157964118913">"I-<xliff:g id="AUDIO_PROCESSING_APP_NAME">%s</xliff:g> icubungula ikholi ngemuva. Kungenzeka ukuthi le app ifinyelela futhi idlala okulalelwayo ngaphezu kwekholi."</string>
<string name="notification_incallservice_not_responding_title" msgid="5347557574288598548">"<xliff:g id="IN_CALL_SERVICE_APP_NAME">%s</xliff:g> iyeke ukuphendula"</string>
<string name="notification_incallservice_not_responding_body" msgid="9209308270131968623">"Ikholi yakho isebenzise uhlelo lokusebenza lefoni elize nedivayisi yakho"</string>
<string name="accessibility_call_muted" msgid="2968461092554300779">"Ikholu ithulisiwe"</string>
@@ -123,4 +123,5 @@
<string name="developer_title" msgid="9146088855661672353">"Imenyu yonjiniyela we-Telecom"</string>
<string name="toast_emergency_can_not_pull_call" msgid="9074229465338410869">"Amakholi awakwazi ukuthathwa ngesikhathi ukukholi yesimo esiphuthumayo."</string>
<string name="cancel" msgid="6733466216239934756">"Khansela"</string>
+ <string name="back" msgid="6915955601805550206">"Emuva"</string>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index bf5abca..d3196b9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -381,4 +381,6 @@
<string name="developer_enhanced_call_blocking" translatable="false">Enhanced Call Blocking</string>
<!-- Button label for generic cancel action [CHAR LIMIT=20] -->
<string name="cancel">Cancel</string>
+ <!-- Button label for generic back action [CHAR LIMIT=20] -->
+ <string name="back">Back</string>
</resources>
diff --git a/src/com/android/server/telecom/Analytics.java b/src/com/android/server/telecom/Analytics.java
index 145e9b4..bbcf858 100644
--- a/src/com/android/server/telecom/Analytics.java
+++ b/src/com/android/server/telecom/Analytics.java
@@ -72,96 +72,101 @@
private static final String CLEAR_ANALYTICS_ARG = "clear";
public static final Map<String, Integer> sLogEventToAnalyticsEvent = Map.ofEntries(
- entry(LogUtils.Events.SET_SELECT_PHONE_ACCOUNT,
- AnalyticsEvent.SET_SELECT_PHONE_ACCOUNT),
- entry(LogUtils.Events.REQUEST_HOLD, AnalyticsEvent.REQUEST_HOLD),
- entry(LogUtils.Events.REQUEST_UNHOLD, AnalyticsEvent.REQUEST_UNHOLD),
- entry(LogUtils.Events.SWAP, AnalyticsEvent.SWAP),
- entry(LogUtils.Events.SKIP_RINGING, AnalyticsEvent.SKIP_RINGING),
- entry(LogUtils.Events.CONFERENCE_WITH, AnalyticsEvent.CONFERENCE_WITH),
- entry(LogUtils.Events.SPLIT_FROM_CONFERENCE, AnalyticsEvent.SPLIT_CONFERENCE),
- entry(LogUtils.Events.SET_PARENT, AnalyticsEvent.SET_PARENT),
- entry(LogUtils.Events.MUTE, AnalyticsEvent.MUTE),
- entry(LogUtils.Events.UNMUTE, AnalyticsEvent.UNMUTE),
- entry(LogUtils.Events.AUDIO_ROUTE_BT, AnalyticsEvent.AUDIO_ROUTE_BT),
- entry(LogUtils.Events.AUDIO_ROUTE_EARPIECE, AnalyticsEvent.AUDIO_ROUTE_EARPIECE),
- entry(LogUtils.Events.AUDIO_ROUTE_HEADSET, AnalyticsEvent.AUDIO_ROUTE_HEADSET),
- entry(LogUtils.Events.AUDIO_ROUTE_SPEAKER, AnalyticsEvent.AUDIO_ROUTE_SPEAKER),
- entry(LogUtils.Events.SILENCE, AnalyticsEvent.SILENCE),
- entry(LogUtils.Events.SCREENING_COMPLETED, AnalyticsEvent.SCREENING_COMPLETED),
- entry(LogUtils.Events.BLOCK_CHECK_FINISHED, AnalyticsEvent.BLOCK_CHECK_FINISHED),
- entry(LogUtils.Events.DIRECT_TO_VM_FINISHED, AnalyticsEvent.DIRECT_TO_VM_FINISHED),
- entry(LogUtils.Events.REMOTELY_HELD, AnalyticsEvent.REMOTELY_HELD),
- entry(LogUtils.Events.REMOTELY_UNHELD, AnalyticsEvent.REMOTELY_UNHELD),
- entry(LogUtils.Events.REQUEST_PULL, AnalyticsEvent.REQUEST_PULL),
- entry(LogUtils.Events.REQUEST_ACCEPT, AnalyticsEvent.REQUEST_ACCEPT),
- entry(LogUtils.Events.REQUEST_REJECT, AnalyticsEvent.REQUEST_REJECT),
- entry(LogUtils.Events.SET_ACTIVE, AnalyticsEvent.SET_ACTIVE),
- entry(LogUtils.Events.SET_DISCONNECTED, AnalyticsEvent.SET_DISCONNECTED),
- entry(LogUtils.Events.SET_HOLD, AnalyticsEvent.SET_HOLD),
- entry(LogUtils.Events.SET_DIALING, AnalyticsEvent.SET_DIALING),
- entry(LogUtils.Events.START_CONNECTION, AnalyticsEvent.START_CONNECTION),
- entry(LogUtils.Events.BIND_CS, AnalyticsEvent.BIND_CS),
- entry(LogUtils.Events.CS_BOUND, AnalyticsEvent.CS_BOUND),
- entry(LogUtils.Events.SCREENING_SENT, AnalyticsEvent.SCREENING_SENT),
- entry(LogUtils.Events.DIRECT_TO_VM_INITIATED,
- AnalyticsEvent.DIRECT_TO_VM_INITIATED),
- entry(LogUtils.Events.BLOCK_CHECK_INITIATED, AnalyticsEvent.BLOCK_CHECK_INITIATED),
- entry(LogUtils.Events.FILTERING_INITIATED, AnalyticsEvent.FILTERING_INITIATED),
- entry(LogUtils.Events.FILTERING_COMPLETED, AnalyticsEvent.FILTERING_COMPLETED),
- entry(LogUtils.Events.FILTERING_TIMED_OUT, AnalyticsEvent.FILTERING_TIMED_OUT));
+ entry(LogUtils.Events.SET_SELECT_PHONE_ACCOUNT,
+ AnalyticsEvent.SET_SELECT_PHONE_ACCOUNT),
+ entry(LogUtils.Events.REQUEST_HOLD, AnalyticsEvent.REQUEST_HOLD),
+ entry(LogUtils.Events.REQUEST_UNHOLD, AnalyticsEvent.REQUEST_UNHOLD),
+ entry(LogUtils.Events.SWAP, AnalyticsEvent.SWAP),
+ entry(LogUtils.Events.SKIP_RINGING, AnalyticsEvent.SKIP_RINGING),
+ entry(LogUtils.Events.CONFERENCE_WITH, AnalyticsEvent.CONFERENCE_WITH),
+ entry(LogUtils.Events.SPLIT_FROM_CONFERENCE, AnalyticsEvent.SPLIT_CONFERENCE),
+ entry(LogUtils.Events.SET_PARENT, AnalyticsEvent.SET_PARENT),
+ entry(LogUtils.Events.MUTE, AnalyticsEvent.MUTE),
+ entry(LogUtils.Events.UNMUTE, AnalyticsEvent.UNMUTE),
+ entry(LogUtils.Events.AUDIO_ROUTE_BT, AnalyticsEvent.AUDIO_ROUTE_BT),
+ entry(LogUtils.Events.AUDIO_ROUTE_EARPIECE, AnalyticsEvent.AUDIO_ROUTE_EARPIECE),
+ entry(LogUtils.Events.AUDIO_ROUTE_HEADSET, AnalyticsEvent.AUDIO_ROUTE_HEADSET),
+ entry(LogUtils.Events.AUDIO_ROUTE_SPEAKER, AnalyticsEvent.AUDIO_ROUTE_SPEAKER),
+ entry(LogUtils.Events.SILENCE, AnalyticsEvent.SILENCE),
+ entry(LogUtils.Events.SCREENING_COMPLETED, AnalyticsEvent.SCREENING_COMPLETED),
+ entry(LogUtils.Events.BLOCK_CHECK_FINISHED, AnalyticsEvent.BLOCK_CHECK_FINISHED),
+ entry(LogUtils.Events.DIRECT_TO_VM_FINISHED, AnalyticsEvent.DIRECT_TO_VM_FINISHED),
+ entry(LogUtils.Events.REMOTELY_HELD, AnalyticsEvent.REMOTELY_HELD),
+ entry(LogUtils.Events.REMOTELY_UNHELD, AnalyticsEvent.REMOTELY_UNHELD),
+ entry(LogUtils.Events.REQUEST_PULL, AnalyticsEvent.REQUEST_PULL),
+ entry(LogUtils.Events.REQUEST_ACCEPT, AnalyticsEvent.REQUEST_ACCEPT),
+ entry(LogUtils.Events.REQUEST_REJECT, AnalyticsEvent.REQUEST_REJECT),
+ entry(LogUtils.Events.SET_ACTIVE, AnalyticsEvent.SET_ACTIVE),
+ entry(LogUtils.Events.SET_DISCONNECTED, AnalyticsEvent.SET_DISCONNECTED),
+ entry(LogUtils.Events.SET_HOLD, AnalyticsEvent.SET_HOLD),
+ entry(LogUtils.Events.SET_DIALING, AnalyticsEvent.SET_DIALING),
+ entry(LogUtils.Events.START_CONNECTION, AnalyticsEvent.START_CONNECTION),
+ entry(LogUtils.Events.BIND_CS, AnalyticsEvent.BIND_CS),
+ entry(LogUtils.Events.CS_BOUND, AnalyticsEvent.CS_BOUND),
+ entry(LogUtils.Events.SCREENING_SENT, AnalyticsEvent.SCREENING_SENT),
+ entry(LogUtils.Events.DIRECT_TO_VM_INITIATED,
+ AnalyticsEvent.DIRECT_TO_VM_INITIATED),
+ entry(LogUtils.Events.BLOCK_CHECK_INITIATED, AnalyticsEvent.BLOCK_CHECK_INITIATED),
+ entry(LogUtils.Events.FILTERING_INITIATED, AnalyticsEvent.FILTERING_INITIATED),
+ entry(LogUtils.Events.FILTERING_COMPLETED, AnalyticsEvent.FILTERING_COMPLETED),
+ entry(LogUtils.Events.FILTERING_TIMED_OUT, AnalyticsEvent.FILTERING_TIMED_OUT),
+ entry(LogUtils.Events.DND_PRE_CHECK_INITIATED, AnalyticsEvent.DND_CHECK_INITIATED),
+ entry(LogUtils.Events.DND_PRE_CHECK_COMPLETED, AnalyticsEvent.DND_CHECK_COMPLETED));
public static final Map<String, Integer> sLogSessionToSessionId = Map.ofEntries(
- entry(LogUtils.Sessions.ICA_ANSWER_CALL, SessionTiming.ICA_ANSWER_CALL),
- entry(LogUtils.Sessions.ICA_REJECT_CALL, SessionTiming.ICA_REJECT_CALL),
- entry(LogUtils.Sessions.ICA_DISCONNECT_CALL, SessionTiming.ICA_DISCONNECT_CALL),
- entry(LogUtils.Sessions.ICA_HOLD_CALL, SessionTiming.ICA_HOLD_CALL),
- entry(LogUtils.Sessions.ICA_UNHOLD_CALL, SessionTiming.ICA_UNHOLD_CALL),
- entry(LogUtils.Sessions.ICA_MUTE, SessionTiming.ICA_MUTE),
- entry(LogUtils.Sessions.ICA_SET_AUDIO_ROUTE, SessionTiming.ICA_SET_AUDIO_ROUTE),
- entry(LogUtils.Sessions.ICA_CONFERENCE, SessionTiming.ICA_CONFERENCE),
- entry(LogUtils.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE,
- SessionTiming.CSW_HANDLE_CREATE_CONNECTION_COMPLETE),
- entry(LogUtils.Sessions.CSW_SET_ACTIVE, SessionTiming.CSW_SET_ACTIVE),
- entry(LogUtils.Sessions.CSW_SET_RINGING, SessionTiming.CSW_SET_RINGING),
- entry(LogUtils.Sessions.CSW_SET_DIALING, SessionTiming.CSW_SET_DIALING),
- entry(LogUtils.Sessions.CSW_SET_DISCONNECTED, SessionTiming.CSW_SET_DISCONNECTED),
- entry(LogUtils.Sessions.CSW_SET_ON_HOLD, SessionTiming.CSW_SET_ON_HOLD),
- entry(LogUtils.Sessions.CSW_REMOVE_CALL, SessionTiming.CSW_REMOVE_CALL),
- entry(LogUtils.Sessions.CSW_SET_IS_CONFERENCED, SessionTiming.CSW_SET_IS_CONFERENCED),
- entry(LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL,
- SessionTiming.CSW_ADD_CONFERENCE_CALL));
+ entry(LogUtils.Sessions.ICA_ANSWER_CALL, SessionTiming.ICA_ANSWER_CALL),
+ entry(LogUtils.Sessions.ICA_REJECT_CALL, SessionTiming.ICA_REJECT_CALL),
+ entry(LogUtils.Sessions.ICA_DISCONNECT_CALL, SessionTiming.ICA_DISCONNECT_CALL),
+ entry(LogUtils.Sessions.ICA_HOLD_CALL, SessionTiming.ICA_HOLD_CALL),
+ entry(LogUtils.Sessions.ICA_UNHOLD_CALL, SessionTiming.ICA_UNHOLD_CALL),
+ entry(LogUtils.Sessions.ICA_MUTE, SessionTiming.ICA_MUTE),
+ entry(LogUtils.Sessions.ICA_SET_AUDIO_ROUTE, SessionTiming.ICA_SET_AUDIO_ROUTE),
+ entry(LogUtils.Sessions.ICA_CONFERENCE, SessionTiming.ICA_CONFERENCE),
+ entry(LogUtils.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE,
+ SessionTiming.CSW_HANDLE_CREATE_CONNECTION_COMPLETE),
+ entry(LogUtils.Sessions.CSW_SET_ACTIVE, SessionTiming.CSW_SET_ACTIVE),
+ entry(LogUtils.Sessions.CSW_SET_RINGING, SessionTiming.CSW_SET_RINGING),
+ entry(LogUtils.Sessions.CSW_SET_DIALING, SessionTiming.CSW_SET_DIALING),
+ entry(LogUtils.Sessions.CSW_SET_DISCONNECTED, SessionTiming.CSW_SET_DISCONNECTED),
+ entry(LogUtils.Sessions.CSW_SET_ON_HOLD, SessionTiming.CSW_SET_ON_HOLD),
+ entry(LogUtils.Sessions.CSW_REMOVE_CALL, SessionTiming.CSW_REMOVE_CALL),
+ entry(LogUtils.Sessions.CSW_SET_IS_CONFERENCED, SessionTiming.CSW_SET_IS_CONFERENCED),
+ entry(LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL,
+ SessionTiming.CSW_ADD_CONFERENCE_CALL));
public static final Map<String, Integer> sLogEventTimingToAnalyticsEventTiming = Map.ofEntries(
- entry(LogUtils.Events.Timings.ACCEPT_TIMING,
- ParcelableCallAnalytics.EventTiming.ACCEPT_TIMING),
- entry(LogUtils.Events.Timings.REJECT_TIMING,
- ParcelableCallAnalytics.EventTiming.REJECT_TIMING),
- entry(LogUtils.Events.Timings.DISCONNECT_TIMING,
- ParcelableCallAnalytics.EventTiming.DISCONNECT_TIMING),
- entry(LogUtils.Events.Timings.HOLD_TIMING,
- ParcelableCallAnalytics.EventTiming.HOLD_TIMING),
- entry(LogUtils.Events.Timings.UNHOLD_TIMING,
- ParcelableCallAnalytics.EventTiming.UNHOLD_TIMING),
- entry(LogUtils.Events.Timings.OUTGOING_TIME_TO_DIALING_TIMING,
- ParcelableCallAnalytics.EventTiming.OUTGOING_TIME_TO_DIALING_TIMING),
- entry(LogUtils.Events.Timings.BIND_CS_TIMING,
- ParcelableCallAnalytics.EventTiming.BIND_CS_TIMING),
- entry(LogUtils.Events.Timings.SCREENING_COMPLETED_TIMING,
- ParcelableCallAnalytics.EventTiming.SCREENING_COMPLETED_TIMING),
- entry(LogUtils.Events.Timings.DIRECT_TO_VM_FINISHED_TIMING,
- ParcelableCallAnalytics.EventTiming.DIRECT_TO_VM_FINISHED_TIMING),
- entry(LogUtils.Events.Timings.BLOCK_CHECK_FINISHED_TIMING,
- ParcelableCallAnalytics.EventTiming.BLOCK_CHECK_FINISHED_TIMING),
- entry(LogUtils.Events.Timings.FILTERING_COMPLETED_TIMING,
- ParcelableCallAnalytics.EventTiming.FILTERING_COMPLETED_TIMING),
- entry(LogUtils.Events.Timings.FILTERING_TIMED_OUT_TIMING,
- ParcelableCallAnalytics.EventTiming.FILTERING_TIMED_OUT_TIMING),
- entry(LogUtils.Events.Timings.START_CONNECTION_TO_REQUEST_DISCONNECT_TIMING,
- ParcelableCallAnalytics.EventTiming.
- START_CONNECTION_TO_REQUEST_DISCONNECT_TIMING));
+ entry(LogUtils.Events.Timings.ACCEPT_TIMING,
+ ParcelableCallAnalytics.EventTiming.ACCEPT_TIMING),
+ entry(LogUtils.Events.Timings.REJECT_TIMING,
+ ParcelableCallAnalytics.EventTiming.REJECT_TIMING),
+ entry(LogUtils.Events.Timings.DISCONNECT_TIMING,
+ ParcelableCallAnalytics.EventTiming.DISCONNECT_TIMING),
+ entry(LogUtils.Events.Timings.HOLD_TIMING,
+ ParcelableCallAnalytics.EventTiming.HOLD_TIMING),
+ entry(LogUtils.Events.Timings.UNHOLD_TIMING,
+ ParcelableCallAnalytics.EventTiming.UNHOLD_TIMING),
+ entry(LogUtils.Events.Timings.OUTGOING_TIME_TO_DIALING_TIMING,
+ ParcelableCallAnalytics.EventTiming.OUTGOING_TIME_TO_DIALING_TIMING),
+ entry(LogUtils.Events.Timings.BIND_CS_TIMING,
+ ParcelableCallAnalytics.EventTiming.BIND_CS_TIMING),
+ entry(LogUtils.Events.Timings.SCREENING_COMPLETED_TIMING,
+ ParcelableCallAnalytics.EventTiming.SCREENING_COMPLETED_TIMING),
+ entry(LogUtils.Events.Timings.DIRECT_TO_VM_FINISHED_TIMING,
+ ParcelableCallAnalytics.EventTiming.DIRECT_TO_VM_FINISHED_TIMING),
+ entry(LogUtils.Events.Timings.BLOCK_CHECK_FINISHED_TIMING,
+ ParcelableCallAnalytics.EventTiming.BLOCK_CHECK_FINISHED_TIMING),
+ entry(LogUtils.Events.Timings.FILTERING_COMPLETED_TIMING,
+ ParcelableCallAnalytics.EventTiming.FILTERING_COMPLETED_TIMING),
+ entry(LogUtils.Events.Timings.FILTERING_TIMED_OUT_TIMING,
+ ParcelableCallAnalytics.EventTiming.FILTERING_TIMED_OUT_TIMING),
+ entry(LogUtils.Events.Timings.START_CONNECTION_TO_REQUEST_DISCONNECT_TIMING,
+ ParcelableCallAnalytics.EventTiming.
+ START_CONNECTION_TO_REQUEST_DISCONNECT_TIMING),
+ entry(LogUtils.Events.Timings.DND_PRE_CHECK_COMPLETED_TIMING,
+ ParcelableCallAnalytics.EventTiming.DND_PRE_CALL_PRE_CHECK_TIMING));
public static final Map<Integer, String> sSessionIdToLogSession = new HashMap<>();
+
static {
for (Map.Entry<String, Integer> e : sLogSessionToSessionId.entrySet()) {
sSessionIdToLogSession.put(e.getValue(), e.getKey());
@@ -228,12 +233,12 @@
public long startTime; // start time in milliseconds since the epoch. 0 if not yet set.
public long endTime; // end time in milliseconds since the epoch. 0 if not yet set.
public int callDirection; // one of UNKNOWN_DIRECTION, INCOMING_DIRECTION,
- // or OUTGOING_DIRECTION.
+ // or OUTGOING_DIRECTION.
public boolean isAdditionalCall = false; // true if the call came in while another call was
- // in progress or if the user dialed this call
- // while in the middle of another call.
+ // in progress or if the user dialed this call
+ // while in the middle of another call.
public boolean isInterrupted = false; // true if the call was interrupted by an incoming
- // or outgoing call.
+ // or outgoing call.
public int callTechnologies; // bitmask denoting which technologies a call used.
// true if the Telecom Call object was created from an existing connection via
@@ -432,17 +437,17 @@
TelecomLogClass.CallLog analyticsProto = toProto();
List<ParcelableCallAnalytics.AnalyticsEvent> events =
Arrays.stream(analyticsProto.callEvents)
- .map(callEventProto -> new ParcelableCallAnalytics.AnalyticsEvent(
- callEventProto.getEventName(),
- callEventProto.getTimeSinceLastEventMillis())
- ).collect(Collectors.toList());
+ .map(callEventProto -> new ParcelableCallAnalytics.AnalyticsEvent(
+ callEventProto.getEventName(),
+ callEventProto.getTimeSinceLastEventMillis())
+ ).collect(Collectors.toList());
List<ParcelableCallAnalytics.EventTiming> timings =
Arrays.stream(analyticsProto.callTimings)
- .map(callTimingProto -> new ParcelableCallAnalytics.EventTiming(
- callTimingProto.getTimingName(),
- callTimingProto.getTimeMillis())
- ).collect(Collectors.toList());
+ .map(callTimingProto -> new ParcelableCallAnalytics.EventTiming(
+ callTimingProto.getTimingName(),
+ callTimingProto.getTimeMillis())
+ ).collect(Collectors.toList());
ParcelableCallAnalytics result = new ParcelableCallAnalytics(
// rounds down to nearest 5 minute mark
@@ -498,7 +503,7 @@
.setConnectionProperties(callProperties)
.setCallSource(callSource);
- result.connectionService = new String[] {connectionService};
+ result.connectionService = new String[]{connectionService};
if (callEvents != null) {
result.callEvents = convertLogEventsToProtoEvents(callEvents.getEvents());
result.callTimings = callEvents.extractEventTimings().stream()
@@ -547,7 +552,6 @@
}
private String getMissedReasonString() {
- //TODO: Implement this
StringBuilder s = new StringBuilder();
s.append('[');
if ((missedReason & AUTO_MISSED_EMERGENCY_CALL) != 0) {
@@ -608,6 +612,7 @@
}
}
}
+
public static final String TAG = "TelecomAnalytics";
// Constants for call direction
@@ -842,13 +847,13 @@
}
@VisibleForTesting
- public static long roundToOneSigFig(long val) {
+ public static long roundToOneSigFig(long val) {
if (val == 0) {
return val;
}
int logVal = (int) Math.floor(Math.log10(val < 0 ? -val : val));
double s = Math.pow(10, logVal);
- double dec = val / s;
+ double dec = val / s;
return (long) (Math.round(dec) * s);
}
}
diff --git a/src/com/android/server/telecom/AsyncRingtonePlayer.java b/src/com/android/server/telecom/AsyncRingtonePlayer.java
index 7f51f1b..24a65b7 100644
--- a/src/com/android/server/telecom/AsyncRingtonePlayer.java
+++ b/src/com/android/server/telecom/AsyncRingtonePlayer.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.media.AudioAttributes;
import android.media.Ringtone;
+import android.media.RingtoneManager;
import android.media.VolumeShaper;
import android.net.Uri;
import android.os.Handler;
@@ -27,13 +28,10 @@
import android.os.Message;
import android.telecom.Log;
import android.telecom.Logging.Session;
-
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.Preconditions;
-import java.util.concurrent.CompletableFuture;
-
/**
* Plays the default ringtone. Uses {@link Ringtone} in a separate thread so that this class can be
* used from the main thread.
@@ -50,12 +48,6 @@
/** The current ringtone. Only used by the ringtone thread. */
private Ringtone mRingtone;
- /**
- * CompletableFuture which signals a caller when we know whether a ringtone will play haptics
- * or not.
- */
- private CompletableFuture<Boolean> mHapticsFuture = null;
-
public AsyncRingtonePlayer() {
// Empty
}
@@ -65,35 +57,14 @@
* If {@link VolumeShaper.Configuration} is specified, it is applied to the ringtone to change
* the volume of the ringtone as it plays.
*
- * @param factory The {@link RingtoneFactory}.
- * @param incomingCall The ringing {@link Call}.
- * @param volumeShaperConfig An optional {@link VolumeShaper.Configuration} which is applied to
- * the ringtone to change its volume while it rings.
- * @param isVibrationEnabled {@code true} if the settings and DND configuration of the device
- * is such that the vibrator should be used, {@code false} otherwise.
- * @return A {@link CompletableFuture} which on completion indicates whether or not the ringtone
- * has a haptic track. {@code True} indicates that a haptic track is present on the
- * ringtone; in this case the default vibration in {@link Ringer} should not be played.
- * {@code False} indicates that a haptic track is NOT present on the ringtone;
- * in this case the default vibration in {@link Ringer} should be trigger if needed.
+ * @param ringtone The {@link Ringtone}.
*/
- public @NonNull
- CompletableFuture<Boolean> play(RingtoneFactory factory, Call incomingCall,
- @Nullable VolumeShaper.Configuration volumeShaperConfig, boolean isRingerAudible,
- boolean isVibrationEnabled) {
+ public void play(@NonNull Ringtone ringtone) {
Log.d(this, "Posting play.");
- if (mHapticsFuture == null) {
- mHapticsFuture = new CompletableFuture<>();
- }
SomeArgs args = SomeArgs.obtain();
- args.arg1 = factory;
- args.arg2 = incomingCall;
- args.arg3 = volumeShaperConfig;
- args.arg4 = isVibrationEnabled;
- args.arg5 = isRingerAudible;
- args.arg6 = Log.createSubsession();
+ args.arg1 = ringtone;
+ args.arg2 = Log.createSubsession();
postMessage(EVENT_PLAY, true /* shouldCreateHandler */, args);
- return mHapticsFuture;
}
/** Stops playing the ringtone. */
@@ -151,76 +122,23 @@
* Starts the actual playback of the ringtone. Executes on ringtone-thread.
*/
private void handlePlay(SomeArgs args) {
- RingtoneFactory factory = (RingtoneFactory) args.arg1;
- Call incomingCall = (Call) args.arg2;
- VolumeShaper.Configuration volumeShaperConfig = (VolumeShaper.Configuration) args.arg3;
- boolean isVibrationEnabled = (boolean) args.arg4;
- boolean isRingerAudible = (boolean) args.arg5;
- Session session = (Session) args.arg6;
+ Ringtone ringtone = (Ringtone) args.arg1;
+ Session session = (Session) args.arg2;
args.recycle();
Log.continueSession(session, "ARP.hP");
try {
// don't bother with any of this if there is an EVENT_STOP waiting.
if (mHandler.hasMessages(EVENT_STOP)) {
- completeHapticFuture(false /* ringtoneHasHaptics */);
return;
}
- // If the Ringtone Uri is EMPTY, then the "None" Ringtone has been selected.
- // If ringer is not audible for this call, then the phone is in "Vibrate" mode.
- // Use haptic-only ringtone or do not play anything.
- if (!isRingerAudible || Uri.EMPTY.equals(incomingCall.getRingtone())) {
- if (isVibrationEnabled) {
- setRingtone(factory.getHapticOnlyRingtone());
- if (mRingtone == null) {
- completeHapticFuture(false /* ringtoneHasHaptics */);
- return;
- }
- } else {
- setRingtone(null);
- completeHapticFuture(false /* ringtoneHasHaptics */);
- return;
- }
- }
-
ThreadUtil.checkNotOnMainThread();
- Log.i(this, "handlePlay: Play ringtone.");
- if (mRingtone == null) {
- setRingtone(factory.getRingtone(incomingCall, volumeShaperConfig));
- if (mRingtone == null) {
- Uri ringtoneUri = incomingCall.getRingtone();
- String ringtoneUriString = (ringtoneUri == null) ? "null" :
- ringtoneUri.toSafeString();
- Log.addEvent(null, LogUtils.Events.ERROR_LOG, "Failed to get ringtone from " +
- "factory. Skipping ringing. Uri was: " + ringtoneUriString);
- completeHapticFuture(false /* ringtoneHasHaptics */);
- return;
- }
- }
-
- // With the ringtone to play now known, we can determine if it has haptic channels or
- // not; we will complete the haptics future so the default vibration code in Ringer can
- // know whether to trigger the vibrator.
- if (mHapticsFuture != null && !mHapticsFuture.isDone()) {
- boolean hasHaptics = factory.hasHapticChannels(mRingtone);
- Log.i(this, "handlePlay: hasHaptics=%b, isVibrationEnabled=%b", hasHaptics,
- isVibrationEnabled);
- SystemSettingsUtil systemSettingsUtil = new SystemSettingsUtil();
- if (hasHaptics && (volumeShaperConfig == null
- || systemSettingsUtil.isAudioCoupledVibrationForRampingRingerEnabled())) {
- AudioAttributes attributes = mRingtone.getAudioAttributes();
- Log.d(this, "handlePlay: %s haptic channel",
- (isVibrationEnabled ? "unmuting" : "muting"));
- mRingtone.setAudioAttributes(
- new AudioAttributes.Builder(attributes)
- .setHapticChannelsMuted(!isVibrationEnabled)
- .build());
- }
- completeHapticFuture(hasHaptics);
- }
-
+ setRingtone(ringtone);
+ Uri uri = mRingtone.getUri();
+ String uriString = (uri != null ? uri.toSafeString() : "");
+ Log.i(this, "handlePlay: Play ringtone. Uri: " + uriString);
mRingtone.setLooping(true);
if (mRingtone.isPlaying()) {
Log.d(this, "Ringtone already playing.");
@@ -268,11 +186,4 @@
}
mRingtone = ringtone;
}
-
- private void completeHapticFuture(boolean ringtoneHasHaptics) {
- if (mHapticsFuture != null) {
- mHapticsFuture.complete(ringtoneHasHaptics);
- mHapticsFuture = null;
- }
- }
}
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 60016fd..b88711e 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -1279,6 +1279,27 @@
return mSilentRingingRequested;
}
+ public void setCallIsSuppressedByDoNotDisturb(boolean isCallSuppressed) {
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(android.telecom.Call.EXTRA_IS_SUPPRESSED_BY_DO_NOT_DISTURB,
+ isCallSuppressed);
+ putExtras(SOURCE_CONNECTION_SERVICE, bundle);
+ }
+
+ public boolean isCallSuppressedByDoNotDisturb() {
+ if (getExtras() == null) {
+ return false;
+ }
+ return getExtras().getBoolean(android.telecom.Call.EXTRA_IS_SUPPRESSED_BY_DO_NOT_DISTURB);
+ }
+
+ public boolean wasDndCheckComputedForCall() {
+ if (getExtras() == null) {
+ return false;
+ }
+ return getExtras().containsKey(android.telecom.Call.EXTRA_IS_SUPPRESSED_BY_DO_NOT_DISTURB);
+ }
+
@VisibleForTesting
public boolean isConference() {
return mIsConference;
@@ -1401,6 +1422,10 @@
}
}
+ public Uri getContactPhotoUri() {
+ return mCallerInfo != null ? mCallerInfo.getContactDisplayPhotoUri() : null;
+ }
+
public String getCallerDisplayName() {
return mCallerDisplayName;
}
@@ -1420,6 +1445,12 @@
}
}
+ void setContactPhotoUri(Uri contactPhotoUri) {
+ if (mCallerInfo != null) {
+ mCallerInfo.SetContactDisplayPhotoUri(contactPhotoUri);
+ }
+ }
+
public String getName() {
return mCallerInfo == null ? null : mCallerInfo.getName();
}
@@ -1586,6 +1617,26 @@
checkIfRttCapable();
}
+ public UserHandle getUserHandleFromTargetPhoneAccount() {
+ return mTargetPhoneAccountHandle == null
+ ? mCallsManager.getCurrentUserHandle() :
+ mTargetPhoneAccountHandle.getUserHandle();
+ }
+
+ public PhoneAccount getPhoneAccountFromHandle() {
+ if (getTargetPhoneAccount() == null) {
+ return null;
+ }
+ PhoneAccount phoneAccount = mCallsManager.getPhoneAccountRegistrar()
+ .getPhoneAccountUnchecked(getTargetPhoneAccount());
+
+ if (phoneAccount == null) {
+ return null;
+ }
+
+ return phoneAccount;
+ }
+
public CharSequence getTargetPhoneAccountLabel() {
if (getTargetPhoneAccount() == null) {
return null;
@@ -2227,9 +2278,9 @@
Log.v(this, "handleCreateConnectionSuccessful %s", connection);
setTargetPhoneAccount(connection.getPhoneAccount());
setHandle(connection.getHandle(), connection.getHandlePresentation());
+
setCallerDisplayName(
connection.getCallerDisplayName(), connection.getCallerDisplayNamePresentation());
-
setConnectionCapabilities(connection.getConnectionCapabilities());
setConnectionProperties(connection.getConnectionProperties());
setIsVoipAudioMode(connection.getIsVoipAudioMode());
@@ -3373,11 +3424,14 @@
return;
}
+ String newName = callerInfo.getName();
+ boolean contactNameChanged = mCallerInfo == null || !mCallerInfo.getName().equals(newName);
+
mCallerInfo = callerInfo;
Log.i(this, "CallerInfo received for %s: %s", Log.piiHandle(mHandle), callerInfo);
- if (mCallerInfo.getContactDisplayPhotoUri() == null ||
- mCallerInfo.cachedPhotoIcon != null || mCallerInfo.cachedPhoto != null) {
+ if (mCallerInfo.getContactDisplayPhotoUri() == null || mCallerInfo.cachedPhotoIcon != null
+ || mCallerInfo.cachedPhoto != null || contactNameChanged) {
for (Listener l : mListeners) {
l.onCallerInfoChanged(this);
}
@@ -3654,6 +3708,12 @@
}
public void setIsVoipAudioMode(boolean audioModeIsVoip) {
+ if (isSelfManaged() && !audioModeIsVoip) {
+ Log.i(this,
+ "setIsVoipAudioMode: ignoring request to set self-managed audio to "
+ + "non-voip mode");
+ return;
+ }
if (mIsVoipAudioMode != audioModeIsVoip) {
Log.addEvent(this, LogUtils.Events.SET_VOIP_MODE, audioModeIsVoip ? "Y" : "N");
}
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index 1863cde..672ee3b 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -17,10 +17,13 @@
package com.android.server.telecom;
import android.annotation.NonNull;
+import android.content.Context;
import android.media.IAudioService;
import android.media.ToneGenerator;
+import android.os.UserHandle;
import android.telecom.CallAudioState;
import android.telecom.Log;
+import android.telecom.PhoneAccount;
import android.telecom.VideoProfile;
import android.util.SparseArray;
@@ -450,15 +453,33 @@
CallAudioRouteStateMachine.INCLUDE_BLUETOOTH_IN_BASELINE);
}
- void silenceRingers() {
+ Set<UserHandle> silenceRingers(Context context, UserHandle callingUser) {
+ // Store all users from calls that were silenced so that we can silence the
+ // InCallServices which are associated with those users.
+ Set<UserHandle> userHandles = new HashSet<>();
+ boolean allCallSilenced = true;
synchronized (mCallsManager.getLock()) {
for (Call call : mRingingCalls) {
+ PhoneAccount targetPhoneAccount = call.getPhoneAccountFromHandle();
+ UserHandle userFromCall = call.getUserHandleFromTargetPhoneAccount();
+ // Do not try to silence calls when calling user is different from the phone account
+ // user and the account does not have CAPABILITY_MULTI_USER enabled.
+ if (!callingUser.equals(userFromCall) && !targetPhoneAccount.
+ hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
+ allCallSilenced = false;
+ continue;
+ }
+ userHandles.add(userFromCall);
call.silence();
}
- mRinger.stopRinging();
- mRinger.stopCallWaiting();
+ // If all the calls were silenced, we can stop the ringer.
+ if (allCallSilenced) {
+ mRinger.stopRinging();
+ mRinger.stopCallWaiting();
+ }
}
+ return userHandles;
}
public boolean isRingtonePlaying() {
diff --git a/src/com/android/server/telecom/CallAudioModeStateMachine.java b/src/com/android/server/telecom/CallAudioModeStateMachine.java
index a1c5f4b..838dc8f 100644
--- a/src/com/android/server/telecom/CallAudioModeStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioModeStateMachine.java
@@ -19,12 +19,12 @@
import android.media.AudioManager;
import android.os.Looper;
import android.os.Message;
+import android.os.Trace;
import android.telecom.Log;
import android.telecom.Logging.Runnable;
import android.telecom.Logging.Session;
import android.util.LocalLog;
import android.util.SparseArray;
-
import com.android.internal.util.IState;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.State;
@@ -370,26 +370,33 @@
private boolean mHasFocus = false;
private void tryStartRinging() {
- if (mHasFocus && mCallAudioManager.isRingtonePlaying()) {
- Log.i(LOG_TAG, "RingingFocusState#tryStartRinging -- audio focus previously"
- + " acquired and ringtone already playing -- skipping.");
- return;
- }
-
- if (mCallAudioManager.startRinging()) {
- mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_RING,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
- // Do not set MODE_RINGTONE if we were previously in the CALL_SCREENING mode -- this
- // trips up the audio system.
- if (mAudioManager.getMode() != AudioManager.MODE_CALL_SCREENING) {
- mAudioManager.setMode(AudioManager.MODE_RINGTONE);
- mLocalLog.log("Mode MODE_RINGTONE");
+ Trace.traceBegin(Trace.TRACE_TAG_AUDIO, "CallAudioMode.tryStartRinging");
+ try {
+ if (mHasFocus && mCallAudioManager.isRingtonePlaying()) {
+ Log.i(LOG_TAG,
+ "RingingFocusState#tryStartRinging -- audio focus previously"
+ + " acquired and ringtone already playing -- skipping.");
+ return;
}
- mCallAudioManager.setCallAudioRouteFocusState(
+
+ if (mCallAudioManager.startRinging()) {
+ mAudioManager.requestAudioFocusForCall(
+ AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+ // Do not set MODE_RINGTONE if we were previously in the CALL_SCREENING mode --
+ // this trips up the audio system.
+ if (mAudioManager.getMode() != AudioManager.MODE_CALL_SCREENING) {
+ mAudioManager.setMode(AudioManager.MODE_RINGTONE);
+ mLocalLog.log("Mode MODE_RINGTONE");
+ }
+ mCallAudioManager.setCallAudioRouteFocusState(
CallAudioRouteStateMachine.RINGING_FOCUS);
- mHasFocus = true;
- } else {
- Log.i(LOG_TAG, "RINGING state, try start ringing but not acquiring audio focus");
+ mHasFocus = true;
+ } else {
+ Log.i(
+ LOG_TAG, "RINGING state, try start ringing but not acquiring audio focus");
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_AUDIO);
}
}
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index 2ed7d95..bf81cc9 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -48,6 +48,7 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.Objects;
+import java.util.Set;
/**
* This class describes the available routes of a call as a state machine.
@@ -1764,16 +1765,18 @@
if (force || !newCallAudioState.equals(mLastKnownCallAudioState)) {
mStatusBarNotifier.notifyMute(newCallAudioState.isMuted());
mCallsManager.onCallAudioStateChanged(mLastKnownCallAudioState, newCallAudioState);
- updateAudioForForegroundCall(newCallAudioState);
+ updateAudioStateForTrackedCalls(newCallAudioState);
mLastKnownCallAudioState = newCallAudioState;
}
}
}
- private void updateAudioForForegroundCall(CallAudioState newCallAudioState) {
- Call call = mCallsManager.getForegroundCall();
- if (call != null && call.getConnectionService() != null) {
- call.getConnectionService().onCallAudioStateChanged(call, newCallAudioState);
+ private void updateAudioStateForTrackedCalls(CallAudioState newCallAudioState) {
+ Set<Call> calls = mCallsManager.getTrackedCalls();
+ for (Call call : calls) {
+ if (call != null && call.getConnectionService() != null) {
+ call.getConnectionService().onCallAudioStateChanged(call, newCallAudioState);
+ }
}
}
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 3fce799..d3c374b 100755
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -43,6 +43,7 @@
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.KeyguardManager;
+import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -113,6 +114,7 @@
import com.android.server.telecom.callfiltering.CallFilteringResult.Builder;
import com.android.server.telecom.callfiltering.CallScreeningServiceFilter;
import com.android.server.telecom.callfiltering.DirectToVoicemailFilter;
+import com.android.server.telecom.callfiltering.DndCallFilter;
import com.android.server.telecom.callfiltering.IncomingCallFilterGraph;
import com.android.server.telecom.callredirection.CallRedirectionProcessor;
import com.android.server.telecom.components.ErrorDialogActivity;
@@ -532,7 +534,6 @@
bluetoothManager,
wiredHeadsetManager,
mDockManager);
-
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
InCallTonePlayer.MediaPlayerFactory mediaPlayerFactory =
(resourceId, attributes) ->
@@ -553,7 +554,8 @@
mCallDiagnosticServiceController.setInCallTonePlayerFactory(playerFactory);
mRinger = new Ringer(playerFactory, context, systemSettingsUtil, asyncRingtonePlayer,
ringtoneFactory, systemVibrator,
- new Ringer.VibrationEffectProxy(), mInCallController);
+ new Ringer.VibrationEffectProxy(), mInCallController,
+ mContext.getSystemService(NotificationManager.class));
mCallRecordingTonePlayer = new CallRecordingTonePlayer(mContext, audioManager,
mTimeoutsAdapter, mLock);
mCallAudioManager = new CallAudioManager(callAudioRouteStateMachine,
@@ -673,12 +675,19 @@
phoneAccount == null || phoneAccount.getExtras() == null
? new Bundle()
: phoneAccount.getExtras();
+ TelephonyManager telephonyManager = getTelephonyManager();
if (incomingCall.hasProperty(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE) ||
+ incomingCall.hasProperty(Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL) ||
+ telephonyManager.isInEmergencySmsMode() ||
incomingCall.isSelfManaged() ||
extras.getBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING)) {
- Log.i(this, "Skipping call filtering for %s (ecm=%b, selfMgd=%b, skipExtra=%b)",
+ Log.i(this, "Skipping call filtering for %s (ecm=%b, "
+ + "networkIdentifiedEmergencyCall = %b, emergencySmsMode = %b, "
+ + "selfMgd=%b, skipExtra=%b)",
incomingCall.getId(),
incomingCall.hasProperty(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE),
+ incomingCall.hasProperty(Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL),
+ telephonyManager.isInEmergencySmsMode(),
incomingCall.isSelfManaged(),
extras.getBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING));
onCallFilteringComplete(incomingCall, new Builder()
@@ -710,6 +719,7 @@
mCallerInfoLookupHelper);
BlockCheckerFilter blockCheckerFilter = new BlockCheckerFilter(mContext, incomingCall,
mCallerInfoLookupHelper, new BlockCheckerAdapter());
+ DndCallFilter dndCallFilter = new DndCallFilter(incomingCall, getRinger());
CallScreeningServiceFilter carrierCallScreeningServiceFilter =
new CallScreeningServiceFilter(incomingCall, carrierPackageName,
CallScreeningServiceFilter.PACKAGE_TYPE_CARRIER, mContext, this,
@@ -727,6 +737,7 @@
mContext, this, appLabelProxy, converter);
}
graph.addFilter(voicemailFilter);
+ graph.addFilter(dndCallFilter);
graph.addFilter(blockCheckerFilter);
graph.addFilter(carrierCallScreeningServiceFilter);
graph.addFilter(callScreeningServiceFilter);
@@ -861,7 +872,8 @@
}
mCallLogManager.logCall(incomingCall, Calls.BLOCKED_TYPE,
result.shouldShowNotification, result);
- } else if (result.shouldShowNotification) {
+ }
+ if (result.shouldShowNotification) {
Log.i(this, "onCallScreeningCompleted: blocked call, showing notification.");
mMissedCallNotifier.showMissedCallNotification(
new MissedCallNotifier.CallInfo(incomingCall));
@@ -1137,6 +1149,15 @@
return mCallAudioManager.getForegroundCall();
}
+ @VisibleForTesting
+ public Set<Call> getTrackedCalls() {
+ if (mCallAudioManager == null) {
+ // Happens when getTrackedCalls is called before full initialization.
+ return null;
+ }
+ return mCallAudioManager.getTrackedCalls();
+ }
+
@Override
public void onCallHoldFailed(Call call) {
markAllAnsweredCallAsRinging(call, "hold");
@@ -1631,6 +1652,9 @@
// retrieved.
CompletableFuture<List<PhoneAccountHandle>> setAccountHandle =
accountsForCall.whenCompleteAsync((potentialPhoneAccounts, exception) -> {
+ if (exception != null){
+ Log.e(TAG, exception, "Error retrieving list of potential phone accounts.");
+ }
Log.i(CallsManager.this, "set outgoing call phone acct; potentialAccts=%s",
potentialPhoneAccounts);
PhoneAccountHandle phoneAccountHandle;
@@ -2097,20 +2121,20 @@
&& !phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
// Check if the phoneAccountHandle belongs to the current user
if (phoneAccountHandle != null &&
- !phoneAccountHandle.getUserHandle().equals(call.getInitiatingUser())) {
+ !phoneAccountHandle.getUserHandle().equals(mCurrentUserHandle)) {
phoneAccountHandle = null;
}
}
- boolean isPotentialEmergencyNumber;
+ boolean isEmergencyNumber;
try {
- isPotentialEmergencyNumber =
- handle != null && getTelephonyManager().isPotentialEmergencyNumber(
+ isEmergencyNumber =
+ handle != null && getTelephonyManager().isEmergencyNumber(
handle.getSchemeSpecificPart());
} catch (IllegalStateException ise) {
- isPotentialEmergencyNumber = false;
+ isEmergencyNumber = false;
} catch (RuntimeException r) {
- isPotentialEmergencyNumber = false;
+ isEmergencyNumber = false;
}
if (shouldCancelCall) {
@@ -2138,7 +2162,7 @@
Log.w(this, "onCallRedirectionComplete: phoneAccountHandle is unavailable");
endEarly = true;
disconnectReason = "Unavailable phoneAccountHandle from Call Redirection Service";
- } else if (isPotentialEmergencyNumber) {
+ } else if (isEmergencyNumber) {
Log.w(this, "onCallRedirectionComplete: emergency number %s is redirected from Call"
+ " Redirection Service", handle.getSchemeSpecificPart());
endEarly = true;
@@ -2420,12 +2444,21 @@
// Drop any ongoing self-managed calls to make way for an emergency call.
disconnectSelfManagedCalls("place emerg call" /* reason */);
}
+ try {
+ call.startCreateConnection(mPhoneAccountRegistrar);
+ } catch (Exception exception) {
+ // If an exceptions is thrown while creating the connection, disconnect.
+ Log.e(TAG, exception, "Exception thrown while establishing connection.");
+ markCallAsDisconnected(call,
+ new DisconnectCause(DisconnectCause.ERROR,
+ "Failed to create the connection."));
+ markCallAsRemoved(call);
+ }
- call.startCreateConnection(mPhoneAccountRegistrar);
}
} else if (mPhoneAccountRegistrar.getCallCapablePhoneAccounts(
requireCallCapableAccountByHandle ? callHandleScheme : null, false,
- call.getInitiatingUser()).isEmpty()) {
+ call.getInitiatingUser(), false).isEmpty()) {
// If there are no call capable accounts, disconnect the call.
markCallAsDisconnected(call, new DisconnectCause(DisconnectCause.CANCELED,
"No registered PhoneAccounts"));
@@ -2891,7 +2924,8 @@
List<PhoneAccountHandle> allAccounts =
mPhoneAccountRegistrar.getCallCapablePhoneAccounts(handle.getScheme(), false, user,
capabilities,
- isEmergency ? 0 : PhoneAccount.CAPABILITY_EMERGENCY_CALLS_ONLY);
+ isEmergency ? 0 : PhoneAccount.CAPABILITY_EMERGENCY_CALLS_ONLY,
+ isEmergency);
if (mMaxNumberOfSimultaneouslyActiveSims < 0) {
mMaxNumberOfSimultaneouslyActiveSims =
getTelephonyManager().getMaxNumberOfSimultaneouslyActiveSims();
@@ -4966,8 +5000,9 @@
if (call.getState() == CallState.DISCONNECTED && (isPotentialMMICode(call.getHandle())
|| isPotentialInCallMMICode(call.getHandle())) && !mCalls.contains(call)) {
DisconnectCause disconnectCause = call.getDisconnectCause();
- if (!TextUtils.isEmpty(disconnectCause.getDescription()) && (disconnectCause.getCode()
- == DisconnectCause.ERROR)) {
+ if (!TextUtils.isEmpty(disconnectCause.getDescription()) && ((disconnectCause.getCode()
+ == DisconnectCause.ERROR) || (disconnectCause.getCode()
+ == DisconnectCause.RESTRICTED))) {
Intent errorIntent = new Intent(mContext, ErrorDialogActivity.class);
errorIntent.putExtra(ErrorDialogActivity.ERROR_MESSAGE_STRING_EXTRA,
disconnectCause.getDescription());
@@ -5435,8 +5470,12 @@
@Override
public void performAction() {
synchronized (mLock) {
- Log.d(this, "perform set call state for %s, state = %s", mCall, mState);
- setCallState(mCall, mState, mTag);
+ Log.d(this, "performAction: current call state %s", mCall);
+ if (mCall.getState() != CallState.DISCONNECTED
+ && mCall.getState() != CallState.DISCONNECTING) {
+ Log.d(this, "performAction: setting to new state = %s", mState);
+ setCallState(mCall, mState, mTag);
+ }
}
}
}
@@ -5665,4 +5704,14 @@
public Ringer getRinger() {
return mRinger;
}
+
+
+ /**
+ * This method should only be used for testing.
+ */
+ @VisibleForTesting
+ public void createActionSetCallStateAndPerformAction(Call call, int state, String tag) {
+ ActionSetCallState actionSetCallState = new ActionSetCallState(call, state, tag);
+ actionSetCallState.performAction();
+ }
}
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 5bb1dbe..0243b67 100755
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -358,9 +358,8 @@
if (call.isAlive() && !call.isDisconnectHandledViaFuture()) {
mCallsManager.markCallAsDisconnected(
call, new DisconnectCause(DisconnectCause.REMOTE));
- } else {
- mCallsManager.markCallAsRemoved(call);
}
+ mCallsManager.markCallAsRemoved(call);
}
}
} catch (Throwable t) {
@@ -888,7 +887,7 @@
// an emergency call.
mPhoneAccountRegistrar.getCallCapablePhoneAccounts(null /*uriScheme*/,
false /*includeDisabledAccounts*/, userHandle, 0 /*capabilities*/,
- 0 /*excludedCapabilities*/);
+ 0 /*excludedCapabilities*/, false);
PhoneAccountHandle phoneAccountHandle = null;
for (PhoneAccountHandle accountHandle : accountHandles) {
if(accountHandle.equals(callingPhoneAccountHandle)) {
diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java
index 3561211..331c32b 100644
--- a/src/com/android/server/telecom/CreateConnectionProcessor.java
+++ b/src/com/android/server/telecom/CreateConnectionProcessor.java
@@ -16,8 +16,10 @@
package com.android.server.telecom;
+import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.os.UserHandle;
import android.telecom.DisconnectCause;
import android.telecom.Log;
import android.telecom.ParcelableConference;
@@ -389,12 +391,23 @@
// current user.
// ONLY include phone accounts which are NOT self-managed; we will never consider a self
// managed phone account for placing an emergency call.
+ UserHandle userFromCall = mCall.getUserHandleFromTargetPhoneAccount();
List<PhoneAccount> allAccounts = mPhoneAccountRegistrar
- .getAllPhoneAccountsOfCurrentUser()
+ .getAllPhoneAccounts(userFromCall, false)
.stream()
.filter(act -> !act.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED))
.collect(Collectors.toList());
+ if (allAccounts.isEmpty()) {
+ // Try using phone accounts from other users to place the call (i.e. using an
+ // available work sim) given that the current user has the INTERACT_ACROSS_USERS
+ // permission.
+ allAccounts = mPhoneAccountRegistrar.getAllPhoneAccounts(userFromCall, true)
+ .stream()
+ .filter(act -> !act.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED))
+ .collect(Collectors.toList());
+ }
+
if (allAccounts.isEmpty() && mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY)) {
// If the list of phone accounts is empty at this point, it means Telephony hasn't
diff --git a/src/com/android/server/telecom/EmergencyCallHelper.java b/src/com/android/server/telecom/EmergencyCallHelper.java
index 5de4e5a..a213e26 100644
--- a/src/com/android/server/telecom/EmergencyCallHelper.java
+++ b/src/com/android/server/telecom/EmergencyCallHelper.java
@@ -34,8 +34,17 @@
private final DefaultDialerCache mDefaultDialerCache;
private final Timeouts.Adapter mTimeoutsAdapter;
private UserHandle mLocationPermissionGrantedToUser;
+
+ //stores the original state of permissions that dialer had
private boolean mHadFineLocation = false;
private boolean mHadBackgroundLocation = false;
+
+ //stores whether we successfully granted the runtime permission
+ //This is stored so we don't unnecessarily revoke if the grant had failed with an exception.
+ //Else we will get an exception
+ private boolean mFineLocationGranted= false;
+ private boolean mBackgroundLocationGranted = false;
+
private long mLastEmergencyCallTimestampMillis;
@VisibleForTesting
@@ -48,7 +57,8 @@
mTimeoutsAdapter = timeoutsAdapter;
}
- void maybeGrantTemporaryLocationPermission(Call call, UserHandle userHandle) {
+ @VisibleForTesting
+ public void maybeGrantTemporaryLocationPermission(Call call, UserHandle userHandle) {
if (shouldGrantTemporaryLocationPermission(call)) {
grantLocationPermission(userHandle);
}
@@ -57,7 +67,8 @@
}
}
- void maybeRevokeTemporaryLocationPermission() {
+ @VisibleForTesting
+ public void maybeRevokeTemporaryLocationPermission() {
if (wasGrantedTemporaryLocationPermission()) {
revokeLocationPermission();
}
@@ -95,51 +106,65 @@
private void grantLocationPermission(UserHandle userHandle) {
String systemDialerPackage = mDefaultDialerCache.getSystemDialerApplication();
- Log.i(this, "Granting temporary location permission to " + systemDialerPackage
- + ", user: " + userHandle);
- try {
- boolean hadBackgroundLocation = hasBackgroundLocationPermission();
- boolean hadFineLocation = hasFineLocationPermission();
- if (hadBackgroundLocation && hadFineLocation) {
- Log.i(this, "Skipping location grant because the system dialer already"
- + " holds sufficient permissions");
- return;
- }
- if (!hadFineLocation) {
+ Log.i(this, "Attempting to grant temporary location permission to " + systemDialerPackage
+ + ", user: " + userHandle);
+
+ boolean hadBackgroundLocation = hasBackgroundLocationPermission();
+ boolean hadFineLocation = hasFineLocationPermission();
+ if (hadBackgroundLocation && hadFineLocation) {
+ Log.i(this, "Skipping location grant because the system dialer already"
+ + " holds sufficient permissions");
+ return;
+ }
+ mHadFineLocation = hadFineLocation;
+ mHadBackgroundLocation = hadBackgroundLocation;
+
+ if (!hadFineLocation) {
+ try {
mContext.getPackageManager().grantRuntimePermission(systemDialerPackage,
- Manifest.permission.ACCESS_FINE_LOCATION, userHandle);
+ Manifest.permission.ACCESS_FINE_LOCATION, userHandle);
+ recordFineLocationPermissionGrant(userHandle);
+ } catch (Exception e) {
+ Log.i(this, "Failed to grant ACCESS_FINE_LOCATION");
}
- if (!hadBackgroundLocation) {
+ }
+ if (!hadBackgroundLocation) {
+ try {
mContext.getPackageManager().grantRuntimePermission(systemDialerPackage,
- Manifest.permission.ACCESS_BACKGROUND_LOCATION, userHandle);
+ Manifest.permission.ACCESS_BACKGROUND_LOCATION, userHandle);
+ recordBackgroundLocationPermissionGrant(userHandle);
+ } catch (Exception e) {
+ Log.i(this, "Failed to grant ACCESS_BACKGROUND_LOCATION");
}
- mHadFineLocation = hadFineLocation;
- mHadBackgroundLocation = hadBackgroundLocation;
- recordPermissionGrant(userHandle);
- } catch (Exception e) {
- Log.e(this, e, "Failed to grant location permissions to " + systemDialerPackage
- + ", user: " + userHandle);
}
}
private void revokeLocationPermission() {
String systemDialerPackage = mDefaultDialerCache.getSystemDialerApplication();
Log.i(this, "Revoking temporary location permission from " + systemDialerPackage
- + ", user: " + mLocationPermissionGrantedToUser);
+ + ", user: " + mLocationPermissionGrantedToUser);
UserHandle userHandle = mLocationPermissionGrantedToUser;
+
try {
- if (!mHadFineLocation) {
+ if (!mHadFineLocation && mFineLocationGranted) {
mContext.getPackageManager().revokeRuntimePermission(systemDialerPackage,
- Manifest.permission.ACCESS_FINE_LOCATION, userHandle);
- }
- if (!mHadBackgroundLocation) {
- mContext.getPackageManager().revokeRuntimePermission(systemDialerPackage,
- Manifest.permission.ACCESS_BACKGROUND_LOCATION, userHandle);
+ Manifest.permission.ACCESS_FINE_LOCATION, userHandle);
}
} catch (Exception e) {
Log.e(this, e, "Failed to revoke location permission from " + systemDialerPackage
- + ", user: " + userHandle);
+ + ", user: " + userHandle);
}
+
+ try {
+ if (!mHadBackgroundLocation && mBackgroundLocationGranted) {
+ mContext.getPackageManager().revokeRuntimePermission(systemDialerPackage,
+ Manifest.permission.ACCESS_BACKGROUND_LOCATION, userHandle);
+ }
+ } catch (Exception e) {
+ Log.e(this, e, "Failed to revoke location permission from " + systemDialerPackage
+ + ", user: " + userHandle);
+ }
+
clearPermissionGrant();
}
@@ -157,8 +182,14 @@
== PackageManager.PERMISSION_GRANTED;
}
- private void recordPermissionGrant(UserHandle userHandle) {
+ private void recordBackgroundLocationPermissionGrant(UserHandle userHandle) {
mLocationPermissionGrantedToUser = userHandle;
+ mBackgroundLocationGranted = true;
+ }
+
+ private void recordFineLocationPermissionGrant(UserHandle userHandle) {
+ mLocationPermissionGrantedToUser = userHandle;
+ mFineLocationGranted = true;
}
private boolean wasGrantedTemporaryLocationPermission() {
@@ -169,5 +200,7 @@
mLocationPermissionGrantedToUser = null;
mHadBackgroundLocation = false;
mHadFineLocation = false;
+ mBackgroundLocationGranted = false;
+ mFineLocationGranted = false;
}
}
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index 9a53575..d830dfc 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -285,6 +285,8 @@
@Override
public int connect(Call call) {
+ UserHandle userFromCall = getUserFromCall(call);
+
if (mIsConnected) {
Log.addEvent(call, LogUtils.Events.INFO, "Already connected, ignoring request: "
+ mInCallServiceInfo);
@@ -294,7 +296,7 @@
// Notify this new added call
sendCallToService(call, mInCallServiceInfo,
- mInCallServices.get(mInCallServiceInfo));
+ mInCallServices.get(userFromCall).get(mInCallServiceInfo));
}
return CONNECTION_SUCCEEDED;
}
@@ -320,11 +322,11 @@
Log.i(this, "Attempting to bind to InCall %s, with %s", mInCallServiceInfo, intent);
mIsConnected = true;
mInCallServiceInfo.setBindingStartTime(mClockProxy.elapsedRealtime());
+ UserHandle userToBind = getUserFromCall(call);
if (!mContext.bindServiceAsUser(intent, mServiceConnection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
| Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS
- | Context.BIND_SCHEDULE_LIKE_TOP_APP,
- UserHandle.CURRENT)) {
+ | Context.BIND_SCHEDULE_LIKE_TOP_APP, userToBind)) {
Log.w(this, "Failed to connect.");
mIsConnected = false;
}
@@ -345,6 +347,7 @@
@Override
public void disconnect() {
if (mIsConnected) {
+ UserHandle userFromCall = getUserFromCall(mCall);
mInCallServiceInfo.setDisconnectTime(mClockProxy.elapsedRealtime());
Log.i(InCallController.this, "ICSBC#disconnect: unbinding after %s ms;"
+ "%s. isCrashed: %s", mInCallServiceInfo.mDisconnectTime
@@ -357,7 +360,7 @@
// Non-UI InCallServices are allowed to return null from onBind if they don't
// want to handle calls at the moment, so don't report them to the user as
// crashed.
- sendCrashedInCallServiceNotification(packageName);
+ sendCrashedInCallServiceNotification(packageName, userFromCall);
}
if (mCall != null) {
mCall.getAnalytics().addInCallService(
@@ -368,7 +371,7 @@
updateCallTracking(mCall, mInCallServiceInfo, false /* isAdd */);
}
- InCallController.this.onDisconnected(mInCallServiceInfo);
+ InCallController.this.onDisconnected(mInCallServiceInfo, userFromCall);
} else {
Log.i(InCallController.this, "ICSBC#disconnect: already disconnected; %s",
mInCallServiceInfo);
@@ -394,7 +397,8 @@
protected void onConnected(IBinder service) {
boolean shouldRemainConnected =
- InCallController.this.onConnected(mInCallServiceInfo, service);
+ InCallController.this.onConnected(mInCallServiceInfo, service,
+ getUserFromCall(mCall));
if (!shouldRemainConnected) {
// Sometimes we can opt to disconnect for certain reasons, like if the
// InCallService rejected our initialization step, or the calls went away
@@ -405,11 +409,25 @@
}
protected void onDisconnected() {
- InCallController.this.onDisconnected(mInCallServiceInfo);
+ boolean shouldReconnect = mIsConnected;
+ InCallController.this.onDisconnected(mInCallServiceInfo, getUserFromCall(mCall));
disconnect(); // Unbind explicitly if we get disconnected.
if (mListener != null) {
mListener.onDisconnect(InCallServiceBindingConnection.this, mCall);
}
+ // Check if we are expected to reconnect
+ if (shouldReconnect && shouldHandleReconnect()) {
+ connect(mCall); // reconnect
+ }
+ }
+
+ private boolean shouldHandleReconnect() {
+ int serviceType = mInCallServiceInfo.getType();
+ boolean nonUI = (serviceType == IN_CALL_SERVICE_TYPE_NON_UI)
+ || (serviceType == IN_CALL_SERVICE_TYPE_COMPANION);
+ boolean carModeUI = (serviceType == IN_CALL_SERVICE_TYPE_CAR_MODE_UI);
+
+ return carModeUI || (nonUI && !mIsNullBinding);
}
}
@@ -462,9 +480,9 @@
// Could not connect to child, stop proxying.
mIsProxying = false;
}
-
+ UserHandle userFromCall = getUserFromCall(call);
mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(call,
- mCallsManager.getCurrentUserHandle());
+ userFromCall);
if (call != null && call.isIncoming()
&& mEmergencyCallHelper.getLastEmergencyCallTimeMillis() > 0) {
@@ -612,13 +630,13 @@
*
* @param packageName The package name of the car mode app.
*/
- public synchronized void changeCarModeApp(String packageName) {
+ public synchronized void changeCarModeApp(String packageName, UserHandle userHandle) {
Log.i(this, "changeCarModeApp: isCarModeNow=" + mIsCarMode);
InCallServiceInfo currentConnectionInfo = mCurrentConnection == null ? null
: mCurrentConnection.getInfo();
InCallServiceInfo carModeConnectionInfo =
- getInCallServiceComponent(packageName,
+ getInCallServiceComponent(userHandle, packageName,
IN_CALL_SERVICE_TYPE_CAR_MODE_UI, true /* ignoreDisabed */);
if (!Objects.equals(currentConnectionInfo, carModeConnectionInfo)
@@ -805,6 +823,11 @@
updateCall(call);
}
+ @Override
+ public void onCallerInfoChanged(Call call) {
+ updateCall(call);
+ }
+
/**
* Listens for changes to extras reported by a Telecom {@link Call}.
*
@@ -917,6 +940,8 @@
if (Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())) {
synchronized (mLock) {
String changedPackage = intent.getData().getSchemeSpecificPart();
+ int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
+ UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
List<InCallServiceBindingConnection> componentsToBind =
Arrays.stream(intent.getStringArrayExtra(
Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST))
@@ -925,13 +950,14 @@
className))
.filter(mKnownNonUiInCallServices::contains)
.flatMap(componentName -> getInCallServiceComponents(
- componentName,
+ userHandle, componentName,
IN_CALL_SERVICE_TYPE_NON_UI).stream())
.map(InCallServiceBindingConnection::new)
.collect(Collectors.toList());
- if (mNonUIInCallServiceConnections != null) {
- mNonUIInCallServiceConnections.addConnections(componentsToBind);
+ if (mNonUIInCallServiceConnections.containsKey(userHandle)) {
+ mNonUIInCallServiceConnections.get(userHandle).
+ addConnections(componentsToBind);
}
// If the current car mode app become enabled from disabled, update
@@ -988,7 +1014,8 @@
CallState.DISCONNECTING };
/** The in-call app implementations, see {@link IInCallService}. */
- private final Map<InCallServiceInfo, IInCallService> mInCallServices = new ArrayMap<>();
+ private final Map<UserHandle, Map<InCallServiceInfo, IInCallService>>
+ mInCallServices = new ArrayMap<>();
private final CallIdMapper mCallIdMapper = new CallIdMapper(Call::getId);
@@ -1002,8 +1029,10 @@
private final DefaultDialerCache mDefaultDialerCache;
private final EmergencyCallHelper mEmergencyCallHelper;
private final Handler mHandler = new Handler(Looper.getMainLooper());
- private CarSwappingInCallServiceConnection mInCallServiceConnection;
- private NonUIInCallServiceConnectionCollection mNonUIInCallServiceConnections;
+ private final Map<UserHandle, CarSwappingInCallServiceConnection>
+ mInCallServiceConnections = new ArrayMap<>();
+ private final Map<UserHandle, NonUIInCallServiceConnectionCollection>
+ mNonUIInCallServiceConnections = new ArrayMap<>();
private final ClockProxy mClockProxy;
private final IBinder mToken = new Binder();
@@ -1136,59 +1165,70 @@
@Override
public void onCallAdded(Call call) {
- if (!isBoundAndConnectedToServices()) {
+ UserHandle userFromCall = getUserFromCall(call);
+ if (!isBoundAndConnectedToServices(userFromCall)) {
Log.i(this, "onCallAdded: %s; not bound or connected.", call);
// We are not bound, or we're not connected.
bindToServices(call);
} else {
+ InCallServiceConnection inCallServiceConnection =
+ mInCallServiceConnections.get(userFromCall);
+
// We are bound, and we are connected.
- adjustServiceBindingsForEmergency();
+ adjustServiceBindingsForEmergency(userFromCall);
// This is in case an emergency call is added while there is an existing call.
mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(call,
- mCallsManager.getCurrentUserHandle());
+ userFromCall);
Log.i(this, "onCallAdded: %s", call);
// Track the call if we don't already know about it.
addCall(call);
- Log.i(this, "mInCallServiceConnection isConnected=%b",
- mInCallServiceConnection.isConnected());
+ if (inCallServiceConnection != null) {
+ Log.i(this, "mInCallServiceConnection isConnected=%b",
+ inCallServiceConnection.isConnected());
+ }
List<ComponentName> componentsUpdated = new ArrayList<>();
- for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.entrySet()) {
- InCallServiceInfo info = entry.getKey();
+ if (mInCallServices.containsKey(userFromCall)) {
+ for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.
+ get(userFromCall).entrySet()) {
+ InCallServiceInfo info = entry.getKey();
- if (call.isExternalCall() && !info.isExternalCallsSupported()) {
- continue;
+ if (call.isExternalCall() && !info.isExternalCallsSupported()) {
+ continue;
+ }
+
+ if (call.isSelfManaged() && (!call.visibleToInCallService()
+ || !info.isSelfManagedCallsSupported())) {
+ continue;
+ }
+
+ // Only send the RTT call if it's a UI in-call service
+ boolean includeRttCall = false;
+ if (inCallServiceConnection != null) {
+ includeRttCall = info.equals(inCallServiceConnection.getInfo());
+ }
+
+ componentsUpdated.add(info.getComponentName());
+ IInCallService inCallService = entry.getValue();
+
+ ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(call,
+ true /* includeVideoProvider */,
+ mCallsManager.getPhoneAccountRegistrar(),
+ info.isExternalCallsSupported(), includeRttCall,
+ info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI ||
+ info.getType() == IN_CALL_SERVICE_TYPE_NON_UI);
+ try {
+ inCallService.addCall(
+ sanitizeParcelableCallForService(info, parcelableCall));
+ updateCallTracking(call, info, true /* isAdd */);
+ } catch (RemoteException ignored) {
+ }
}
-
- if (call.isSelfManaged() && (!call.visibleToInCallService()
- || !info.isSelfManagedCallsSupported())) {
- continue;
- }
-
- // Only send the RTT call if it's a UI in-call service
- boolean includeRttCall = false;
- if (mInCallServiceConnection != null) {
- includeRttCall = info.equals(mInCallServiceConnection.getInfo());
- }
-
- componentsUpdated.add(info.getComponentName());
- IInCallService inCallService = entry.getValue();
-
- ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(call,
- true /* includeVideoProvider */, mCallsManager.getPhoneAccountRegistrar(),
- info.isExternalCallsSupported(), includeRttCall,
- info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI ||
- info.getType() == IN_CALL_SERVICE_TYPE_NON_UI);
- try {
- inCallService.addCall(sanitizeParcelableCallForService(info, parcelableCall));
- updateCallTracking(call, info, true /* isAdd */);
- } catch (RemoteException ignored) {
- }
+ Log.i(this, "Call added to components: %s", componentsUpdated);
}
- Log.i(this, "Call added to components: %s", componentsUpdated);
}
}
@@ -1204,7 +1244,7 @@
public void loggedRun() {
// Check again to make sure there are no active calls.
if (mCallsManager.getCalls().isEmpty()) {
- unbindFromServices();
+ unbindFromServices(getUserFromCall(call));
mEmergencyCallHelper.maybeRevokeTemporaryLocationPermission();
}
@@ -1227,10 +1267,12 @@
Log.i(this, "onExternalCallChanged: %s -> %b", call, isExternalCall);
List<ComponentName> componentsUpdated = new ArrayList<>();
- if (!isExternalCall) {
+ UserHandle userFromCall = getUserFromCall(call);
+ if (!isExternalCall && mInCallServices.containsKey(userFromCall)) {
// The call was external but it is no longer external. We must now add it to any
// InCallServices which do not support external calls.
- for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.entrySet()) {
+ for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.
+ get(userFromCall).entrySet()) {
InCallServiceInfo info = entry.getKey();
if (info.isExternalCallsSupported()) {
@@ -1248,7 +1290,8 @@
IInCallService inCallService = entry.getValue();
// Only send the RTT call if it's a UI in-call service
- boolean includeRttCall = info.equals(mInCallServiceConnection.getInfo());
+ boolean includeRttCall = info.equals(mInCallServiceConnections.
+ get(userFromCall).getInfo());
ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(call,
true /* includeVideoProvider */, mCallsManager.getPhoneAccountRegistrar(),
@@ -1267,35 +1310,38 @@
// InCallServices which do not support external calls.
// Remove the call by sending a call update indicating the call was disconnected.
Log.i(this, "Removing external call %s", call);
- for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.entrySet()) {
- InCallServiceInfo info = entry.getKey();
- if (info.isExternalCallsSupported()) {
- // For InCallServices which support external calls, we do not need to remove
- // the call.
- continue;
+ if (mInCallServices.containsKey(userFromCall)) {
+ for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.
+ get(userFromCall).entrySet()) {
+ InCallServiceInfo info = entry.getKey();
+ if (info.isExternalCallsSupported()) {
+ // For InCallServices which support external calls, we do not need to remove
+ // the call.
+ continue;
+ }
+
+ componentsUpdated.add(info.getComponentName());
+ IInCallService inCallService = entry.getValue();
+
+ ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(
+ call,
+ false /* includeVideoProvider */,
+ mCallsManager.getPhoneAccountRegistrar(),
+ false /* supportsExternalCalls */,
+ android.telecom.Call.STATE_DISCONNECTED /* overrideState */,
+ false /* includeRttCall */,
+ info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI
+ || info.getType() == IN_CALL_SERVICE_TYPE_NON_UI
+ );
+
+ try {
+ inCallService.updateCall(
+ sanitizeParcelableCallForService(info, parcelableCall));
+ } catch (RemoteException ignored) {
+ }
}
-
- componentsUpdated.add(info.getComponentName());
- IInCallService inCallService = entry.getValue();
-
- ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(
- call,
- false /* includeVideoProvider */,
- mCallsManager.getPhoneAccountRegistrar(),
- false /* supportsExternalCalls */,
- android.telecom.Call.STATE_DISCONNECTED /* overrideState */,
- false /* includeRttCall */,
- info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI
- || info.getType() == IN_CALL_SERVICE_TYPE_NON_UI
- );
-
- try {
- inCallService.updateCall(
- sanitizeParcelableCallForService(info, parcelableCall));
- } catch (RemoteException ignored) {
- }
+ Log.i(this, "External call removed from components: %s", componentsUpdated);
}
- Log.i(this, "External call removed from components: %s", componentsUpdated);
}
maybeTrackMicrophoneUse(isMuted());
}
@@ -1321,12 +1367,14 @@
Log.i(this, "Calling onAudioStateChanged, audioState: %s -> %s", oldCallAudioState,
newCallAudioState);
maybeTrackMicrophoneUse(newCallAudioState.isMuted());
- for (IInCallService inCallService : mInCallServices.values()) {
- try {
- inCallService.onCallAudioStateChanged(newCallAudioState);
- } catch (RemoteException ignored) {
+ mInCallServices.values().forEach(inCallServices -> {
+ for (IInCallService inCallService : inCallServices.values()) {
+ try {
+ inCallService.onCallAudioStateChanged(newCallAudioState);
+ } catch (RemoteException ignored) {
+ }
}
- }
+ });
}
}
@@ -1334,19 +1382,22 @@
public void onCanAddCallChanged(boolean canAddCall) {
if (!mInCallServices.isEmpty()) {
Log.i(this, "onCanAddCallChanged : %b", canAddCall);
- for (IInCallService inCallService : mInCallServices.values()) {
- try {
- inCallService.onCanAddCallChanged(canAddCall);
- } catch (RemoteException ignored) {
+ mInCallServices.values().forEach(inCallServices -> {
+ for (IInCallService inCallService : inCallServices.values()) {
+ try {
+ inCallService.onCanAddCallChanged(canAddCall);
+ } catch (RemoteException ignored) {
+ }
}
- }
+ });
}
}
void onPostDialWait(Call call, String remaining) {
- if (!mInCallServices.isEmpty()) {
+ UserHandle userFromCall = getUserFromCall(call);
+ if (mInCallServices.containsKey(userFromCall)) {
Log.i(this, "Calling onPostDialWait, remaining = %s", remaining);
- for (IInCallService inCallService : mInCallServices.values()) {
+ for (IInCallService inCallService : mInCallServices.get(userFromCall).values()) {
try {
inCallService.setPostDialWait(mCallIdMapper.getCallId(call), remaining);
} catch (RemoteException ignored) {
@@ -1420,9 +1471,10 @@
}
}
- void bringToForeground(boolean showDialpad) {
- if (!mInCallServices.isEmpty()) {
- for (IInCallService inCallService : mInCallServices.values()) {
+ @VisibleForTesting
+ public void bringToForeground(boolean showDialpad, UserHandle callingUser) {
+ if (mInCallServices.containsKey(callingUser)) {
+ for (IInCallService inCallService : mInCallServices.get(callingUser).values()) {
try {
inCallService.bringToForeground(showDialpad);
} catch (RemoteException ignored) {
@@ -1433,20 +1485,28 @@
}
}
- void silenceRinger() {
- if (!mInCallServices.isEmpty()) {
- for (IInCallService inCallService : mInCallServices.values()) {
- try {
- inCallService.silenceRinger();
- } catch (RemoteException ignored) {
+ @VisibleForTesting
+ public Map<UserHandle, Map<InCallServiceInfo, IInCallService>> getInCallServices() {
+ return mInCallServices;
+ }
+
+ void silenceRinger(Set<UserHandle> userHandles) {
+ userHandles.forEach(userHandle -> {
+ if (mInCallServices.containsKey(userHandle)) {
+ for (IInCallService inCallService : mInCallServices.get(userHandle).values()) {
+ try {
+ inCallService.silenceRinger();
+ } catch (RemoteException ignored) {
+ }
}
}
- }
+ });
}
private void notifyConnectionEvent(Call call, String event, Bundle extras) {
- if (!mInCallServices.isEmpty()) {
- for (IInCallService inCallService : mInCallServices.values()) {
+ UserHandle userFromCall = getUserFromCall(call);
+ if (mInCallServices.containsKey(userFromCall)) {
+ for (IInCallService inCallService : mInCallServices.get(userFromCall).values()) {
try {
Log.i(this, "notifyConnectionEvent {Call: %s, Event: %s, Extras:[%s]}",
(call != null ? call.toString() : "null"),
@@ -1460,9 +1520,11 @@
}
private void notifyRttInitiationFailure(Call call, int reason) {
- if (!mInCallServices.isEmpty()) {
- mInCallServices.entrySet().stream()
- .filter((entry) -> entry.getKey().equals(mInCallServiceConnection.getInfo()))
+ UserHandle userFromCall = getUserFromCall(call);
+ if (mInCallServices.containsKey(userFromCall)) {
+ mInCallServices.get(userFromCall).entrySet().stream()
+ .filter((entry) -> entry.getKey().equals(mInCallServiceConnections.
+ get(userFromCall).getInfo()))
.forEach((entry) -> {
try {
Log.i(this, "notifyRttFailure, call %s, incall %s",
@@ -1476,9 +1538,11 @@
}
private void notifyRemoteRttRequest(Call call, int requestId) {
- if (!mInCallServices.isEmpty()) {
- mInCallServices.entrySet().stream()
- .filter((entry) -> entry.getKey().equals(mInCallServiceConnection.getInfo()))
+ UserHandle userFromCall = getUserFromCall(call);
+ if (mInCallServices.containsKey(userFromCall)) {
+ mInCallServices.get(userFromCall).entrySet().stream()
+ .filter((entry) -> entry.getKey().equals(mInCallServiceConnections.
+ get(userFromCall).getInfo()))
.forEach((entry) -> {
try {
Log.i(this, "notifyRemoteRttRequest, call %s, incall %s",
@@ -1492,8 +1556,9 @@
}
private void notifyHandoverFailed(Call call, int error) {
- if (!mInCallServices.isEmpty()) {
- for (IInCallService inCallService : mInCallServices.values()) {
+ UserHandle userFromCall = getUserFromCall(call);
+ if (mInCallServices.containsKey(userFromCall)) {
+ for (IInCallService inCallService : mInCallServices.get(userFromCall).values()) {
try {
inCallService.onHandoverFailed(mCallIdMapper.getCallId(call), error);
} catch (RemoteException ignored) {
@@ -1503,8 +1568,9 @@
}
private void notifyHandoverComplete(Call call) {
- if (!mInCallServices.isEmpty()) {
- for (IInCallService inCallService : mInCallServices.values()) {
+ UserHandle userFromCall = getUserFromCall(call);
+ if (mInCallServices.containsKey(userFromCall)) {
+ for (IInCallService inCallService : mInCallServices.get(userFromCall).values()) {
try {
inCallService.onHandoverComplete(mCallIdMapper.getCallId(call));
} catch (RemoteException ignored) {
@@ -1516,22 +1582,22 @@
/**
* Unbinds an existing bound connection to the in-call app.
*/
- public void unbindFromServices() {
+ public void unbindFromServices(UserHandle userHandle) {
try {
mContext.unregisterReceiver(mPackageChangedReceiver);
} catch (IllegalArgumentException e) {
// Ignore this -- we may or may not have registered it, but when we bind, we want to
// unregister no matter what.
}
- if (mInCallServiceConnection != null) {
- mInCallServiceConnection.disconnect();
- mInCallServiceConnection = null;
+ if (mInCallServiceConnections.containsKey(userHandle)) {
+ mInCallServiceConnections.get(userHandle).disconnect();
+ mInCallServiceConnections.remove(userHandle);
}
- if (mNonUIInCallServiceConnections != null) {
- mNonUIInCallServiceConnections.disconnect();
- mNonUIInCallServiceConnections = null;
+ if (mNonUIInCallServiceConnections.containsKey(userHandle)) {
+ mNonUIInCallServiceConnections.get(userHandle).disconnect();
+ mNonUIInCallServiceConnections.remove(userHandle);
}
- mInCallServices.clear();
+ mInCallServices.remove(userHandle);
}
/**
@@ -1543,9 +1609,10 @@
*/
@VisibleForTesting
public void bindToServices(Call call) {
- if (mInCallServiceConnection == null) {
+ UserHandle userFromCall = getUserFromCall(call);
+ if (!mInCallServiceConnections.containsKey(userFromCall)) {
InCallServiceConnection dialerInCall = null;
- InCallServiceInfo defaultDialerComponentInfo = getDefaultDialerComponent();
+ InCallServiceInfo defaultDialerComponentInfo = getDefaultDialerComponent(userFromCall);
Log.i(this, "defaultDialer: " + defaultDialerComponentInfo);
if (defaultDialerComponentInfo != null &&
!defaultDialerComponentInfo.getComponentName().equals(
@@ -1554,28 +1621,30 @@
}
Log.i(this, "defaultDialer: " + dialerInCall);
- InCallServiceInfo systemInCallInfo = getInCallServiceComponent(
+ InCallServiceInfo systemInCallInfo = getInCallServiceComponent(userFromCall,
mDefaultDialerCache.getSystemDialerComponent(), IN_CALL_SERVICE_TYPE_SYSTEM_UI);
EmergencyInCallServiceConnection systemInCall =
new EmergencyInCallServiceConnection(systemInCallInfo, dialerInCall);
systemInCall.setHasEmergency(mCallsManager.isInEmergencyCall());
InCallServiceConnection carModeInCall = null;
- InCallServiceInfo carModeComponentInfo = getCurrentCarModeComponent();
+ InCallServiceInfo carModeComponentInfo = getCurrentCarModeComponent(userFromCall);
if (carModeComponentInfo != null &&
!carModeComponentInfo.getComponentName().equals(
mDefaultDialerCache.getSystemDialerComponent())) {
carModeInCall = new InCallServiceBindingConnection(carModeComponentInfo);
}
- mInCallServiceConnection =
- new CarSwappingInCallServiceConnection(systemInCall, carModeInCall);
+ mInCallServiceConnections.put(userFromCall,
+ new CarSwappingInCallServiceConnection(systemInCall, carModeInCall));
}
- mInCallServiceConnection.chooseInitialInCallService(shouldUseCarModeUI());
+ CarSwappingInCallServiceConnection inCallServiceConnection =
+ mInCallServiceConnections.get(userFromCall);
+ inCallServiceConnection.chooseInitialInCallService(shouldUseCarModeUI());
// Actually try binding to the UI InCallService.
- if (mInCallServiceConnection.connect(call) ==
+ if (inCallServiceConnection.connect(call) ==
InCallServiceConnection.CONNECTION_SUCCEEDED || call.isSelfManaged()) {
// Only connect to the non-ui InCallServices if we actually connected to the main UI
// one, or if the call is self-managed (in which case we'd still want to keep Wear, BT,
@@ -1594,9 +1663,10 @@
mContext.registerReceiver(mPackageChangedReceiver, packageChangedFilter);
}
- private void updateNonUiInCallServices() {
+ private void updateNonUiInCallServices(Call call) {
+ UserHandle userFromCall = getUserFromCall(call);
List<InCallServiceInfo> nonUIInCallComponents =
- getInCallServiceComponents(IN_CALL_SERVICE_TYPE_NON_UI);
+ getInCallServiceComponents(userFromCall, IN_CALL_SERVICE_TYPE_NON_UI);
List<InCallServiceBindingConnection> nonUIInCalls = new LinkedList<>();
for (InCallServiceInfo serviceInfo : nonUIInCallComponents) {
nonUIInCalls.add(new InCallServiceBindingConnection(serviceInfo));
@@ -1605,27 +1675,28 @@
.getRoleManagerAdapter().getCallCompanionApps();
if (callCompanionApps != null && !callCompanionApps.isEmpty()) {
for (String pkg : callCompanionApps) {
- InCallServiceInfo info = getInCallServiceComponent(pkg,
+ InCallServiceInfo info = getInCallServiceComponent(userFromCall, pkg,
IN_CALL_SERVICE_TYPE_COMPANION, true /* ignoreDisabled */);
if (info != null) {
nonUIInCalls.add(new InCallServiceBindingConnection(info));
}
}
}
- mNonUIInCallServiceConnections = new NonUIInCallServiceConnectionCollection(
- nonUIInCalls);
+ mNonUIInCallServiceConnections.put(userFromCall, new NonUIInCallServiceConnectionCollection(
+ nonUIInCalls));
}
private void connectToNonUiInCallServices(Call call) {
- if (mNonUIInCallServiceConnections == null) {
- updateNonUiInCallServices();
+ UserHandle userFromCall = getUserFromCall(call);
+ if (!mNonUIInCallServiceConnections.containsKey(userFromCall)) {
+ updateNonUiInCallServices(call);
}
- mNonUIInCallServiceConnections.connect(call);
+ mNonUIInCallServiceConnections.get(userFromCall).connect(call);
}
- private @Nullable InCallServiceInfo getDefaultDialerComponent() {
+ private @Nullable InCallServiceInfo getDefaultDialerComponent(UserHandle userHandle) {
String defaultPhoneAppName = mDefaultDialerCache.getDefaultDialerApplication(
- mCallsManager.getCurrentUserHandle().getIdentifier());
+ userHandle.getIdentifier());
String systemPhoneAppName = mDefaultDialerCache.getSystemDialerApplication();
Log.d(this, "getDefaultDialerComponent: defaultPhoneAppName=[%s]", defaultPhoneAppName);
@@ -1635,10 +1706,10 @@
InCallServiceInfo defaultPhoneAppComponent =
(systemPhoneAppName != null && systemPhoneAppName.equals(defaultPhoneAppName)) ?
/* The defaultPhoneApp is also the systemPhoneApp. Get systemPhoneApp info*/
- getInCallServiceComponent(defaultPhoneAppName,
+ getInCallServiceComponent(userHandle, defaultPhoneAppName,
IN_CALL_SERVICE_TYPE_SYSTEM_UI, true /* ignoreDisabled */)
/* The defaultPhoneApp is NOT the systemPhoneApp. Get defaultPhoneApp info*/
- : getInCallServiceComponent(defaultPhoneAppName,
+ : getInCallServiceComponent(userHandle, defaultPhoneAppName,
IN_CALL_SERVICE_TYPE_DEFAULT_DIALER_UI, true /* ignoreDisabled */);
Log.d(this, "getDefaultDialerComponent: defaultPhoneAppComponent=[%s]",
@@ -1650,13 +1721,16 @@
return defaultPhoneAppComponent;
}
- private InCallServiceInfo getCurrentCarModeComponent() {
- return getInCallServiceComponent(mCarModeTracker.getCurrentCarModePackage(),
+ private InCallServiceInfo getCurrentCarModeComponent(UserHandle userHandle) {
+ return getInCallServiceComponent(userHandle,
+ mCarModeTracker.getCurrentCarModePackage(),
IN_CALL_SERVICE_TYPE_CAR_MODE_UI, true /* ignoreDisabled */);
}
- private InCallServiceInfo getInCallServiceComponent(ComponentName componentName, int type) {
- List<InCallServiceInfo> list = getInCallServiceComponents(componentName, type);
+ private InCallServiceInfo getInCallServiceComponent(UserHandle userHandle,
+ ComponentName componentName, int type) {
+ List<InCallServiceInfo> list = getInCallServiceComponents(userHandle,
+ componentName, type);
if (list != null && !list.isEmpty()) {
return list.get(0);
} else {
@@ -1667,38 +1741,41 @@
}
}
- private InCallServiceInfo getInCallServiceComponent(String packageName, int type,
- boolean ignoreDisabled) {
- List<InCallServiceInfo> list = getInCallServiceComponents(packageName, type,
- ignoreDisabled);
+ private InCallServiceInfo getInCallServiceComponent(UserHandle userHandle,
+ String packageName, int type, boolean ignoreDisabled) {
+ List<InCallServiceInfo> list = getInCallServiceComponents(userHandle,
+ packageName, type, ignoreDisabled);
if (list != null && !list.isEmpty()) {
return list.get(0);
}
return null;
}
- private List<InCallServiceInfo> getInCallServiceComponents(int type) {
- return getInCallServiceComponents(null, null, type);
+ private List<InCallServiceInfo> getInCallServiceComponents(
+ UserHandle userHandle, int type) {
+ return getInCallServiceComponents(userHandle, null, null, type);
}
- private List<InCallServiceInfo> getInCallServiceComponents(String packageName, int type,
- boolean ignoreDisabled) {
- return getInCallServiceComponents(packageName, null, type, ignoreDisabled);
+ private List<InCallServiceInfo> getInCallServiceComponents(UserHandle userHandle,
+ String packageName, int type, boolean ignoreDisabled) {
+ return getInCallServiceComponents(userHandle, packageName, null,
+ type, ignoreDisabled);
}
- private List<InCallServiceInfo> getInCallServiceComponents(ComponentName componentName,
- int type) {
- return getInCallServiceComponents(null, componentName, type);
+ private List<InCallServiceInfo> getInCallServiceComponents(UserHandle userHandle,
+ ComponentName componentName, int type) {
+ return getInCallServiceComponents(userHandle, null, componentName, type);
}
- private List<InCallServiceInfo> getInCallServiceComponents(String packageName,
- ComponentName componentName, int requestedType) {
- return getInCallServiceComponents(packageName, componentName, requestedType,
- true /* ignoreDisabled */);
+ private List<InCallServiceInfo> getInCallServiceComponents(UserHandle userHandle,
+ String packageName, ComponentName componentName, int requestedType) {
+ return getInCallServiceComponents(userHandle, packageName,
+ componentName, requestedType, true /* ignoreDisabled */);
}
- private List<InCallServiceInfo> getInCallServiceComponents(String packageName,
- ComponentName componentName, int requestedType, boolean ignoreDisabled) {
+ private List<InCallServiceInfo> getInCallServiceComponents(UserHandle userHandle,
+ String packageName, ComponentName componentName,
+ int requestedType, boolean ignoreDisabled) {
List<InCallServiceInfo> retval = new LinkedList<>();
Intent serviceIntent = new Intent(InCallService.SERVICE_INTERFACE);
@@ -1708,16 +1785,15 @@
if (componentName != null) {
serviceIntent.setComponent(componentName);
}
-
PackageManager packageManager = mContext.getPackageManager();
- Context userContext = mContext.createContextAsUser(mCallsManager.getCurrentUserHandle(),
+ Context userContext = mContext.createContextAsUser(userHandle,
0 /* flags */);
PackageManager userPackageManager = userContext != null ?
userContext.getPackageManager() : packageManager;
for (ResolveInfo entry : packageManager.queryIntentServicesAsUser(
serviceIntent,
PackageManager.GET_META_DATA | PackageManager.MATCH_DISABLED_COMPONENTS,
- mCallsManager.getCurrentUserHandle().getIdentifier())) {
+ userHandle.getIdentifier())) {
ServiceInfo serviceInfo = entry.serviceInfo;
if (serviceInfo != null) {
@@ -1728,8 +1804,8 @@
serviceInfo.metaData.getBoolean(
TelecomManager.METADATA_INCLUDE_SELF_MANAGED_CALLS, false);
- int currentType = getInCallServiceType(entry.serviceInfo, packageManager,
- packageName);
+ int currentType = getInCallServiceType(userHandle,
+ entry.serviceInfo, packageManager, packageName);
ComponentName foundComponentName =
new ComponentName(serviceInfo.packageName, serviceInfo.name);
if (requestedType == IN_CALL_SERVICE_TYPE_NON_UI) {
@@ -1780,8 +1856,8 @@
/**
* Returns the type of InCallService described by the specified serviceInfo.
*/
- private int getInCallServiceType(ServiceInfo serviceInfo, PackageManager packageManager,
- String packageName) {
+ private int getInCallServiceType(UserHandle userHandle, ServiceInfo serviceInfo,
+ PackageManager packageManager, String packageName) {
// Verify that the InCallService requires the BIND_INCALL_SERVICE permission which
// enforces that only Telecom can bind to it.
boolean hasServiceBindPermission = serviceInfo.permission != null &&
@@ -1833,7 +1909,7 @@
// Check to see that it is the default dialer package
boolean isDefaultDialerPackage = Objects.equals(serviceInfo.packageName,
mDefaultDialerCache.getDefaultDialerApplication(
- mCallsManager.getCurrentUserHandle().getIdentifier()));
+ userHandle.getIdentifier()));
if (isDefaultDialerPackage && isUIService) {
return IN_CALL_SERVICE_TYPE_DEFAULT_DIALER_UI;
}
@@ -1852,11 +1928,11 @@
return IN_CALL_SERVICE_TYPE_INVALID;
}
- private void adjustServiceBindingsForEmergency() {
+ private void adjustServiceBindingsForEmergency(UserHandle userHandle) {
// The connected UI is not the system UI, so lets check if we should switch them
// if there exists an emergency number.
if (mCallsManager.isInEmergencyCall()) {
- mInCallServiceConnection.setHasEmergency(true);
+ mInCallServiceConnections.get(userHandle).setHasEmergency(true);
}
}
@@ -1869,7 +1945,7 @@
* @param service The {@link IInCallService} implementation.
* @return True if we successfully connected.
*/
- private boolean onConnected(InCallServiceInfo info, IBinder service) {
+ private boolean onConnected(InCallServiceInfo info, IBinder service, UserHandle userHandle) {
Log.i(this, "onConnected to %s", info.getComponentName());
if (info.getType() == IN_CALL_SERVICE_TYPE_CAR_MODE_UI
@@ -1878,7 +1954,9 @@
trackCallingUserInterfaceStarted(info);
}
IInCallService inCallService = IInCallService.Stub.asInterface(service);
- mInCallServices.put(info, inCallService);
+ mInCallServices.putIfAbsent(userHandle,
+ new ArrayMap<InCallController.InCallServiceInfo, IInCallService>());
+ mInCallServices.get(userHandle).put(info, inCallService);
try {
inCallService.setInCallAdapter(
@@ -1924,10 +2002,11 @@
return 0;
}
+ UserHandle userFromCall = getUserFromCall(call);
// Only send the RTT call if it's a UI in-call service
boolean includeRttCall = false;
- if (mInCallServiceConnection != null) {
- includeRttCall = info.equals(mInCallServiceConnection.getInfo());
+ if (mInCallServiceConnections.containsKey(userFromCall)) {
+ includeRttCall = info.equals(mInCallServiceConnections.get(userFromCall).getInfo());
}
// Track the call if we don't already know about it.
@@ -1953,14 +2032,16 @@
*
* @param disconnectedInfo The {@link InCallServiceInfo} of the service which disconnected.
*/
- private void onDisconnected(InCallServiceInfo disconnectedInfo) {
+ private void onDisconnected(InCallServiceInfo disconnectedInfo, UserHandle userHandle) {
Log.i(this, "onDisconnected from %s", disconnectedInfo.getComponentName());
if (disconnectedInfo.getType() == IN_CALL_SERVICE_TYPE_CAR_MODE_UI
|| disconnectedInfo.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI
|| disconnectedInfo.getType() == IN_CALL_SERVICE_TYPE_DEFAULT_DIALER_UI) {
trackCallingUserInterfaceStopped(disconnectedInfo);
}
- mInCallServices.remove(disconnectedInfo);
+ if (mInCallServices.containsKey(userHandle)) {
+ mInCallServices.get(userHandle).remove(disconnectedInfo);
+ }
}
/**
@@ -1982,10 +2063,12 @@
* {@code false} otherwise.
*/
private void updateCall(Call call, boolean videoProviderChanged, boolean rttInfoChanged) {
- if (!mInCallServices.isEmpty()) {
+ UserHandle userFromCall = getUserFromCall(call);
+ if (mInCallServices.containsKey(userFromCall)) {
Log.i(this, "Sending updateCall %s", call);
List<ComponentName> componentsUpdated = new ArrayList<>();
- for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.entrySet()) {
+ for (Map.Entry<InCallServiceInfo, IInCallService> entry : mInCallServices.
+ get(userFromCall).entrySet()) {
InCallServiceInfo info = entry.getKey();
if (call.isExternalCall() && !info.isExternalCallsSupported()) {
continue;
@@ -2001,7 +2084,8 @@
videoProviderChanged /* includeVideoProvider */,
mCallsManager.getPhoneAccountRegistrar(),
info.isExternalCallsSupported(),
- rttInfoChanged && info.equals(mInCallServiceConnection.getInfo()),
+ rttInfoChanged && info.equals(
+ mInCallServiceConnections.get(userFromCall).getInfo()),
info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI ||
info.getType() == IN_CALL_SERVICE_TYPE_NON_UI);
ComponentName componentName = info.getComponentName();
@@ -2041,8 +2125,11 @@
/**
* @return true if we are bound to the UI InCallService and it is connected.
*/
- private boolean isBoundAndConnectedToServices() {
- return mInCallServiceConnection != null && mInCallServiceConnection.isConnected();
+ private boolean isBoundAndConnectedToServices(UserHandle userHandle) {
+ if (!mInCallServiceConnections.containsKey(userHandle)) {
+ return false;
+ }
+ return mInCallServiceConnections.get(userHandle).isConnected();
}
/**
@@ -2061,15 +2148,17 @@
public void dump(IndentingPrintWriter pw) {
pw.println("mInCallServices (InCalls registered):");
pw.increaseIndent();
- for (InCallServiceInfo info : mInCallServices.keySet()) {
- pw.println(info);
- }
+ mInCallServices.values().forEach(inCallServices -> {
+ for (InCallServiceInfo info : inCallServices.keySet()) {
+ pw.println(info);
+ }
+ });
pw.decreaseIndent();
pw.println("ServiceConnections (InCalls bound):");
pw.increaseIndent();
- if (mInCallServiceConnection != null) {
- mInCallServiceConnection.dump(pw);
+ for (InCallServiceConnection inCallServiceConnection : mInCallServiceConnections.values()) {
+ inCallServiceConnection.dump(pw);
}
pw.decreaseIndent();
@@ -2079,22 +2168,25 @@
/**
* @return The package name of the UI which is currently bound, or null if none.
*/
- private ComponentName getConnectedUi() {
- InCallServiceInfo connectedUi = mInCallServices.keySet().stream().filter(
- i -> i.getType() == IN_CALL_SERVICE_TYPE_DEFAULT_DIALER_UI
- || i.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI)
- .findAny()
- .orElse(null);
- if (connectedUi != null) {
- return connectedUi.mComponentName;
+ private ComponentName getConnectedUi(UserHandle userHandle) {
+ if (mInCallServices.containsKey(userHandle)) {
+ InCallServiceInfo connectedUi = mInCallServices.get(
+ userHandle).keySet().stream().filter(
+ i -> i.getType() == IN_CALL_SERVICE_TYPE_DEFAULT_DIALER_UI
+ || i.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI)
+ .findAny()
+ .orElse(null);
+ if (connectedUi != null) {
+ return connectedUi.mComponentName;
+ }
}
return null;
}
- public boolean doesConnectedDialerSupportRinging() {
+ public boolean doesConnectedDialerSupportRinging(UserHandle userHandle) {
String ringingPackage = null;
- ComponentName connectedPackage = getConnectedUi();
+ ComponentName connectedPackage = getConnectedUi(userHandle);
if (connectedPackage != null) {
ringingPackage = connectedPackage.getPackageName().trim();
Log.d(this, "doesConnectedDialerSupportRinging: alreadyConnectedPackage=%s",
@@ -2104,7 +2196,7 @@
if (TextUtils.isEmpty(ringingPackage)) {
// The current in-call UI returned nothing, so lets use the default dialer.
ringingPackage = mDefaultDialerCache.getRoleManagerAdapter().getDefaultDialerApp(
- mCallsManager.getCurrentUserHandle().getIdentifier());
+ userHandle.getIdentifier());
if (ringingPackage != null) {
Log.d(this, "doesConnectedDialerSupportRinging: notCurentlyConnectedPackage=%s",
ringingPackage);
@@ -2119,7 +2211,7 @@
.setPackage(ringingPackage);
List<ResolveInfo> entries = mContext.getPackageManager().queryIntentServicesAsUser(
intent, PackageManager.GET_META_DATA,
- mCallsManager.getCurrentUserHandle().getIdentifier());
+ userHandle.getIdentifier());
if (entries.isEmpty()) {
Log.w(this, "doesConnectedDialerSupportRinging: couldn't find dialer's package info"
+ " <sad trombone>");
@@ -2151,15 +2243,32 @@
return childCalls;
}
- private ParcelableCall sanitizeParcelableCallForService(
+ @VisibleForTesting
+ public ParcelableCall sanitizeParcelableCallForService(
InCallServiceInfo info, ParcelableCall parcelableCall) {
ParcelableCall.ParcelableCallBuilder builder =
ParcelableCall.ParcelableCallBuilder.fromParcelableCall(parcelableCall);
- // Check for contacts permission. If it's not there, remove the contactsDisplayName.
PackageManager pm = mContext.getPackageManager();
+
+ // Check for contacts permission.
if (pm.checkPermission(Manifest.permission.READ_CONTACTS,
info.getComponentName().getPackageName()) != PackageManager.PERMISSION_GRANTED) {
+ // contacts permission is not present...
+
+ // removing the contactsDisplayName
builder.setContactDisplayName(null);
+ builder.setContactPhotoUri(null);
+
+ // removing the Call.EXTRA_IS_SUPPRESSED_BY_DO_NOT_DISTURB extra
+ if (parcelableCall.getExtras() != null) {
+ Bundle callBundle = parcelableCall.getExtras();
+ if (callBundle.containsKey(
+ android.telecom.Call.EXTRA_IS_SUPPRESSED_BY_DO_NOT_DISTURB)) {
+ Bundle newBundle = callBundle.deepCopy();
+ newBundle.remove(android.telecom.Call.EXTRA_IS_SUPPRESSED_BY_DO_NOT_DISTURB);
+ builder.setExtras(newBundle);
+ }
+ }
}
// TODO: move all the other service-specific sanitizations in here
@@ -2181,8 +2290,8 @@
// Disabled InCallService should also be considered as a valid InCallService here so that
// it can be added to the CarModeTracker, in case it will be enabled in future.
InCallServiceInfo info =
- getInCallServiceComponent(packageName, IN_CALL_SERVICE_TYPE_CAR_MODE_UI,
- false /* ignoreDisabled */);
+ getInCallServiceComponent(mCallsManager.getCurrentUserHandle(),
+ packageName, IN_CALL_SERVICE_TYPE_CAR_MODE_UI, false /* ignoreDisabled */);
return info != null && info.getType() == IN_CALL_SERVICE_TYPE_CAR_MODE_UI;
}
@@ -2231,16 +2340,19 @@
public void updateCarModeForConnections() {
Log.i(this, "updateCarModeForConnections: car mode apps: %s",
mCarModeTracker.getCarModeApps().stream().collect(Collectors.joining(", ")));
- if (mInCallServiceConnection != null) {
+
+ if (mInCallServiceConnections.containsKey(mCallsManager.getCurrentUserHandle())) {
+ CarSwappingInCallServiceConnection inCallServiceConnection = mInCallServiceConnections.
+ get(mCallsManager.getCurrentUserHandle());
if (shouldUseCarModeUI()) {
Log.i(this, "updateCarModeForConnections: potentially update car mode app.");
- mInCallServiceConnection.changeCarModeApp(
- mCarModeTracker.getCurrentCarModePackage());
+ inCallServiceConnection.changeCarModeApp(mCarModeTracker.getCurrentCarModePackage(),
+ mCallsManager.getCurrentUserHandle());
} else {
- if (mInCallServiceConnection.isCarMode()) {
+ if (inCallServiceConnection.isCarMode()) {
Log.i(this, "updateCarModeForConnections: car mode no longer "
+ "applicable; disabling");
- mInCallServiceConnection.disableCarMode();
+ inCallServiceConnection.disableCarMode();
}
}
}
@@ -2348,7 +2460,7 @@
== PermissionChecker.PERMISSION_GRANTED;
}
- private void sendCrashedInCallServiceNotification(String packageName) {
+ private void sendCrashedInCallServiceNotification(String packageName, UserHandle userHandle) {
PackageManager packageManager = mContext.getPackageManager();
CharSequence appName;
String systemDialer = mDefaultDialerCache.getSystemDialerApplication();
@@ -2376,8 +2488,8 @@
.setStyle(new Notification.BigTextStyle()
.bigText(mContext.getText(
R.string.notification_incallservice_not_responding_body)));
- notificationManager.notify(NOTIFICATION_TAG, IN_CALL_SERVICE_NOTIFICATION_ID,
- builder.build());
+ notificationManager.notifyAsUser(NOTIFICATION_TAG, IN_CALL_SERVICE_NOTIFICATION_ID,
+ builder.build(), userHandle);
}
private void updateCallTracking(Call call, InCallServiceInfo info, boolean isAdd) {
@@ -2386,4 +2498,11 @@
|| type == IN_CALL_SERVICE_TYPE_DEFAULT_DIALER_UI;
call.maybeOnInCallServiceTrackingChanged(isAdd, hasUi);
}
+
+ private UserHandle getUserFromCall(Call call) {
+ // Call may never be specified, so we can fall back to using the CallManager current user.
+ return call == null
+ ? mCallsManager.getCurrentUserHandle()
+ : call.getUserHandleFromTargetPhoneAccount();
+ }
}
diff --git a/src/com/android/server/telecom/InCallTonePlayer.java b/src/com/android/server/telecom/InCallTonePlayer.java
index 0367ba0..0957eb4 100644
--- a/src/com/android/server/telecom/InCallTonePlayer.java
+++ b/src/com/android/server/telecom/InCallTonePlayer.java
@@ -470,12 +470,6 @@
@VisibleForTesting
public boolean startTone() {
- // Skip playing the end call tone if the volume is silenced.
- if (mToneId == TONE_CALL_ENDED && !mAudioManagerAdapter.isVolumeOverZero()) {
- Log.i(this, "startTone: skip end-call tone as device is silenced.");
- return false;
- }
-
// Tone already done; don't allow re-used
if (mState == STATE_STOPPED) {
return false;
diff --git a/src/com/android/server/telecom/LogUtils.java b/src/com/android/server/telecom/LogUtils.java
index 12e780f..ca73b92 100644
--- a/src/com/android/server/telecom/LogUtils.java
+++ b/src/com/android/server/telecom/LogUtils.java
@@ -168,6 +168,8 @@
public static final String DIRECT_TO_VM_INITIATED = "DIRECT_TO_VM_INITIATED";
public static final String DIRECT_TO_VM_FINISHED = "DIRECT_TO_VM_FINISHED";
public static final String FILTERING_INITIATED = "FILTERING_INITIATED";
+ public static final String DND_PRE_CHECK_INITIATED = "DND_PRE_CHECK_INITIATED";
+ public static final String DND_PRE_CHECK_COMPLETED = "DND_PRE_CHECK_COMPLETED";
public static final String FILTERING_COMPLETED = "FILTERING_COMPLETED";
public static final String FILTERING_TIMED_OUT = "FILTERING_TIMED_OUT";
public static final String REMOTELY_HELD = "REMOTELY_HELD";
@@ -222,6 +224,7 @@
public static final String DIRECT_TO_VM_FINISHED_TIMING = "direct_to_vm_finished";
public static final String BLOCK_CHECK_FINISHED_TIMING = "block_check_finished";
public static final String FILTERING_COMPLETED_TIMING = "filtering_completed";
+ public static final String DND_PRE_CHECK_COMPLETED_TIMING = "dnd_pre_check_completed";
public static final String FILTERING_TIMED_OUT_TIMING = "filtering_timed_out";
public static final String START_CONNECTION_TO_REQUEST_DISCONNECT_TIMING =
"start_connection_to_request_disconnect";
@@ -243,6 +246,8 @@
BLOCK_CHECK_FINISHED_TIMING),
new TimedEventPair(FILTERING_INITIATED, FILTERING_COMPLETED,
FILTERING_COMPLETED_TIMING),
+ new TimedEventPair(DND_PRE_CHECK_INITIATED, DND_PRE_CHECK_COMPLETED,
+ DND_PRE_CHECK_COMPLETED_TIMING),
new TimedEventPair(FILTERING_INITIATED, FILTERING_TIMED_OUT,
FILTERING_TIMED_OUT_TIMING, 6000L),
new TimedEventPair(START_CONNECTION, REQUEST_DISCONNECT,
diff --git a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
index 86fedd5..eaeee97 100644
--- a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
+++ b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
@@ -139,7 +139,7 @@
disconnectTimeout = getDisconnectTimeoutFromApp(
getResultExtras(false), disconnectTimeout);
endEarly = true;
- } else if (isPotentialEmergencyNumber(resultNumber)) {
+ } else if (isEmergencyNumber(resultNumber)) {
Log.w(this, "Cannot modify outgoing call to emergency number %s.",
resultNumber);
disconnectTimeout = 0;
@@ -273,14 +273,14 @@
return result;
}
- final boolean isPotentialEmergencyNumber = isPotentialEmergencyNumber(number);
- Log.v(this, "isPotentialEmergencyNumber = %s", isPotentialEmergencyNumber);
+ final boolean isEmergencyNumber = isEmergencyNumber(number);
+ Log.v(this, "isEmergencyNumber = %s", isEmergencyNumber);
- action = calculateCallIntentAction(intent, isPotentialEmergencyNumber);
+ action = calculateCallIntentAction(intent, isEmergencyNumber);
intent.setAction(action);
if (Intent.ACTION_CALL.equals(action)) {
- if (isPotentialEmergencyNumber) {
+ if (isEmergencyNumber) {
if (!mIsDefaultOrSystemPhoneApp) {
Log.w(this, "Cannot call potential emergency number %s with CALL Intent %s "
+ "unless caller is system or default dialer.", number, intent);
@@ -293,7 +293,7 @@
}
}
} else if (Intent.ACTION_CALL_EMERGENCY.equals(action)) {
- if (!isPotentialEmergencyNumber) {
+ if (!isEmergencyNumber) {
Log.w(this, "Cannot call non-potential-emergency number %s with EMERGENCY_CALL "
+ "Intent %s.", number, intent);
result.disconnectCause = DisconnectCause.OUTGOING_CANCELED;
@@ -314,8 +314,18 @@
}
private String getNumberFromCallIntent(Intent intent) {
- String number;
- number = mPhoneNumberUtilsAdapter.getNumberFromIntent(intent, mContext);
+ String number = null;
+
+ Uri uri = intent.getData();
+ if (uri != null) {
+ String scheme = uri.getScheme();
+ if (scheme != null) {
+ if (scheme.equals("tel") || scheme.equals("sip")) {
+ number = uri.getSchemeSpecificPart();
+ }
+ }
+ }
+
if (TextUtils.isEmpty(number)) {
Log.w(this, "Empty number obtained from the call intent.");
return null;
@@ -364,7 +374,7 @@
callRedirectionWithService = callRedirectionProcessor
.canMakeCallRedirectionWithService();
if (callRedirectionWithService) {
- callRedirectionProcessor.performCallRedirection();
+ callRedirectionProcessor.performCallRedirection(mCall.getInitiatingUser());
}
}
@@ -507,23 +517,18 @@
* that only the CALL_PRIVILEGED and CALL_EMERGENCY intents are allowed to make emergency
* calls.
*
- * To prevent malicious 3rd party apps from making emergency calls by passing in an
- * "invalid" number like "9111234" (that isn't technically an emergency number but might
- * still result in an emergency call with some networks), we use
- * isPotentialLocalEmergencyNumber instead of isLocalEmergencyNumber.
- *
* @param number number to inspect in order to determine whether or not an emergency number
- * is potentially being dialed
- * @return True if the handle is potentially an emergency number.
+ * is being dialed
+ * @return True if the handle is an emergency number.
*/
- private boolean isPotentialEmergencyNumber(String number) {
+ private boolean isEmergencyNumber(String number) {
Log.v(this, "Checking restrictions for number : %s", Log.pii(number));
if (number == null) return false;
try {
- return mContext.getSystemService(TelephonyManager.class).isPotentialEmergencyNumber(
+ return mContext.getSystemService(TelephonyManager.class).isEmergencyNumber(
number);
} catch (Exception e) {
- Log.e(this, e, "isPotentialEmergencyNumber: Telephony threw an exception.");
+ Log.e(this, e, "isEmergencyNumber: Telephony threw an exception.");
return false;
}
}
@@ -533,17 +538,17 @@
* the appropriate call intent action.
*
* @param intent Intent to evaluate
- * @param isPotentialEmergencyNumber Whether or not the number is potentially an emergency
+ * @param isEmergencyNumber Whether or not the number is an emergency
* number.
* @return The appropriate action.
*/
- private String calculateCallIntentAction(Intent intent, boolean isPotentialEmergencyNumber) {
+ private String calculateCallIntentAction(Intent intent, boolean isEmergencyNumber) {
String action = intent.getAction();
/* Change CALL_PRIVILEGED into CALL or CALL_EMERGENCY as needed. */
if (Intent.ACTION_CALL_PRIVILEGED.equals(action)) {
- if (isPotentialEmergencyNumber) {
- Log.i(this, "ACTION_CALL_PRIVILEGED is used while the number is a potential"
+ if (isEmergencyNumber) {
+ Log.i(this, "ACTION_CALL_PRIVILEGED is used while the number is a"
+ " emergency number. Using ACTION_CALL_EMERGENCY as an action instead.");
action = Intent.ACTION_CALL_EMERGENCY;
} else {
diff --git a/src/com/android/server/telecom/ParcelableCallUtils.java b/src/com/android/server/telecom/ParcelableCallUtils.java
index 0becaef..673b99a 100644
--- a/src/com/android/server/telecom/ParcelableCallUtils.java
+++ b/src/com/android/server/telecom/ParcelableCallUtils.java
@@ -196,6 +196,8 @@
String callerDisplayName = call.getCallerDisplayNamePresentation() ==
TelecomManager.PRESENTATION_ALLOWED ? call.getCallerDisplayName() : null;
+ Uri contactPhotoUri = call.getContactPhotoUri();
+
List<Call> conferenceableCalls = call.getConferenceableCalls();
List<String> conferenceableCallIds = new ArrayList<String>(conferenceableCalls.size());
for (Call otherCall : conferenceableCalls) {
@@ -255,6 +257,7 @@
.setCallerNumberVerificationStatus(call.getCallerNumberVerificationStatus())
.setContactDisplayName(call.getName())
.setActiveChildCallId(activeChildCallId)
+ .setContactPhotoUri(contactPhotoUri)
.createParcelableCall();
}
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index 7b24a09..db577bd 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -248,7 +248,7 @@
}
List<PhoneAccountHandle> outgoing = getCallCapablePhoneAccounts(uriScheme, false,
- userHandle);
+ userHandle, false);
switch (outgoing.size()) {
case 0:
// There are no accounts, so there can be no default
@@ -287,6 +287,12 @@
if (account != null) {
return defaultPhoneAccountHandle.phoneAccountHandle;
}
+
+ Log.v(this,
+ "getUserSelectedOutgoingPhoneAccount: defaultPhoneAccountHandle"
+ + ".phoneAccountHandle=[%s] is not registered or owned by %s"
+ , defaultPhoneAccountHandle.phoneAccountHandle, userHandle);
+
return null;
}
@@ -317,7 +323,7 @@
}
// Get the PhoneAccount with the same group Id (and same ComponentName) that is not the
// newAccount that was just added
- List<PhoneAccount> accounts = getAllPhoneAccounts(userHandle).stream()
+ List<PhoneAccount> accounts = getAllPhoneAccounts(userHandle, false).stream()
.filter(account -> groupId.equals(account.getGroupId()) &&
!account.getAccountHandle().equals(excludePhoneAccountHandle) &&
Objects.equals(account.getAccountHandle().getComponentName(),
@@ -343,6 +349,15 @@
mState.defaultOutgoingAccountHandles.get(userHandle);
PhoneAccountHandle currentDefaultPhoneAccount = currentDefaultInfo == null ? null :
currentDefaultInfo.phoneAccountHandle;
+
+ Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s", accountHandle);
+
+ if (Objects.equals(currentDefaultPhoneAccount, accountHandle)) {
+ Log.i(this, "setUserSelectedOutgoingPhoneAccount: "
+ + "no change in default phoneAccountHandle. current is same as new.");
+ return;
+ }
+
boolean isSimAccount = false;
if (accountHandle == null) {
// Asking to clear the default outgoing is a valid request
@@ -371,24 +386,21 @@
.put(userHandle, new DefaultPhoneAccountHandle(userHandle, accountHandle,
account.getGroupId()));
}
- Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s", accountHandle);
// Potentially update the default voice subid in SubscriptionManager.
- if (!Objects.equals(currentDefaultPhoneAccount, accountHandle)) {
- int newSubId = accountHandle == null ? SubscriptionManager.INVALID_SUBSCRIPTION_ID :
- getSubscriptionIdForPhoneAccount(accountHandle);
- if (isSimAccount || accountHandle == null) {
- int currentVoiceSubId = mSubscriptionManager.getDefaultVoiceSubscriptionId();
- if (newSubId != currentVoiceSubId) {
- Log.i(this, "setUserSelectedOutgoingPhoneAccount: update voice sub; "
- + "account=%s, subId=%d", accountHandle, newSubId);
- mSubscriptionManager.setDefaultVoiceSubscriptionId(newSubId);
- }
+ int newSubId = accountHandle == null ? SubscriptionManager.INVALID_SUBSCRIPTION_ID :
+ getSubscriptionIdForPhoneAccount(accountHandle);
+ if (isSimAccount || accountHandle == null) {
+ int currentVoiceSubId = mSubscriptionManager.getDefaultVoiceSubscriptionId();
+ if (newSubId != currentVoiceSubId) {
+ Log.i(this, "setUserSelectedOutgoingPhoneAccount: update voice sub; "
+ + "account=%s, subId=%d", accountHandle, newSubId);
+ mSubscriptionManager.setDefaultVoiceSubscriptionId(newSubId);
} else {
- Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s is not a sub", accountHandle);
+ Log.i(this, "setUserSelectedOutgoingPhoneAccount: no change to voice sub");
}
} else {
- Log.i(this, "setUserSelectedOutgoingPhoneAccount: no change to voice sub");
+ Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s is not a sub", accountHandle);
}
write();
@@ -457,7 +469,7 @@
// loop through and look for any connection manager in the same package.
List<PhoneAccountHandle> allSimCallManagers = getPhoneAccountHandles(
PhoneAccount.CAPABILITY_CONNECTION_MANAGER, null, null,
- true /* includeDisabledAccounts */, userHandle);
+ true /* includeDisabledAccounts */, userHandle, false);
for (PhoneAccountHandle accountHandle : allSimCallManagers) {
ComponentName component = accountHandle.getComponentName();
@@ -713,16 +725,13 @@
*
* @return The list of {@link PhoneAccountHandle}s.
*/
- public List<PhoneAccountHandle> getAllPhoneAccountHandles(UserHandle userHandle) {
- return getPhoneAccountHandles(0, null, null, false, userHandle);
+ public List<PhoneAccountHandle> getAllPhoneAccountHandles(UserHandle userHandle,
+ boolean crossUserAccess) {
+ return getPhoneAccountHandles(0, null, null, false, userHandle, crossUserAccess);
}
- public List<PhoneAccount> getAllPhoneAccounts(UserHandle userHandle) {
- return getPhoneAccounts(0, null, null, false, userHandle);
- }
-
- public List<PhoneAccount> getAllPhoneAccountsOfCurrentUser() {
- return getAllPhoneAccounts(mCurrentUserHandle);
+ public List<PhoneAccount> getAllPhoneAccounts(UserHandle userHandle, boolean crossUserAccess) {
+ return getPhoneAccounts(0, null, null, false, mCurrentUserHandle, crossUserAccess);
}
/**
@@ -736,9 +745,11 @@
* @return The phone account handles.
*/
public List<PhoneAccountHandle> getCallCapablePhoneAccounts(
- String uriScheme, boolean includeDisabledAccounts, UserHandle userHandle) {
+ String uriScheme, boolean includeDisabledAccounts,
+ UserHandle userHandle, boolean crossUserAccess) {
return getCallCapablePhoneAccounts(uriScheme, includeDisabledAccounts, userHandle,
- 0 /* capabilities */, PhoneAccount.CAPABILITY_EMERGENCY_CALLS_ONLY);
+ 0 /* capabilities */, PhoneAccount.CAPABILITY_EMERGENCY_CALLS_ONLY,
+ crossUserAccess);
}
/**
@@ -755,11 +766,11 @@
*/
public List<PhoneAccountHandle> getCallCapablePhoneAccounts(
String uriScheme, boolean includeDisabledAccounts, UserHandle userHandle,
- int capabilities, int excludedCapabilities) {
+ int capabilities, int excludedCapabilities, boolean crossUserAccess) {
return getPhoneAccountHandles(
PhoneAccount.CAPABILITY_CALL_PROVIDER | capabilities,
excludedCapabilities /*excludedCapabilities*/,
- uriScheme, null, includeDisabledAccounts, userHandle);
+ uriScheme, null, includeDisabledAccounts, userHandle, crossUserAccess);
}
/**
@@ -777,12 +788,7 @@
PhoneAccount.CAPABILITY_SELF_MANAGED,
PhoneAccount.CAPABILITY_EMERGENCY_CALLS_ONLY /* excludedCapabilities */,
null /* uriScheme */, null /* packageName */, false /* includeDisabledAccounts */,
- userHandle);
- }
-
- public List<PhoneAccountHandle> getCallCapablePhoneAccountsOfCurrentUser(
- String uriScheme, boolean includeDisabledAccounts) {
- return getCallCapablePhoneAccounts(uriScheme, includeDisabledAccounts, mCurrentUserHandle);
+ userHandle, false);
}
/**
@@ -791,7 +797,7 @@
public List<PhoneAccountHandle> getSimPhoneAccounts(UserHandle userHandle) {
return getPhoneAccountHandles(
PhoneAccount.CAPABILITY_CALL_PROVIDER | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION,
- null, null, false, userHandle);
+ null, null, false, userHandle, false);
}
public List<PhoneAccountHandle> getSimPhoneAccountsOfCurrentUser() {
@@ -806,7 +812,7 @@
*/
public List<PhoneAccountHandle> getPhoneAccountsForPackage(String packageName,
UserHandle userHandle) {
- return getPhoneAccountHandles(0, null, packageName, false, userHandle);
+ return getPhoneAccountHandles(0, null, packageName, false, userHandle, false);
}
/**
@@ -1254,9 +1260,10 @@
String uriScheme,
String packageName,
boolean includeDisabledAccounts,
- UserHandle userHandle) {
+ UserHandle userHandle,
+ boolean crossUserAccess) {
return getPhoneAccountHandles(capabilities, 0 /*excludedCapabilities*/, uriScheme,
- packageName, includeDisabledAccounts, userHandle);
+ packageName, includeDisabledAccounts, userHandle, crossUserAccess);
}
/**
@@ -1269,12 +1276,13 @@
String uriScheme,
String packageName,
boolean includeDisabledAccounts,
- UserHandle userHandle) {
+ UserHandle userHandle,
+ boolean crossUserAccess) {
List<PhoneAccountHandle> handles = new ArrayList<>();
for (PhoneAccount account : getPhoneAccounts(
capabilities, excludedCapabilities, uriScheme, packageName,
- includeDisabledAccounts, userHandle)) {
+ includeDisabledAccounts, userHandle, crossUserAccess)) {
handles.add(account.getAccountHandle());
}
return handles;
@@ -1285,9 +1293,10 @@
String uriScheme,
String packageName,
boolean includeDisabledAccounts,
- UserHandle userHandle) {
+ UserHandle userHandle,
+ boolean crossUserAccess) {
return getPhoneAccounts(capabilities, 0 /*excludedCapabilities*/, uriScheme, packageName,
- includeDisabledAccounts, userHandle);
+ includeDisabledAccounts, userHandle, crossUserAccess);
}
/**
@@ -1307,7 +1316,8 @@
String uriScheme,
String packageName,
boolean includeDisabledAccounts,
- UserHandle userHandle) {
+ UserHandle userHandle,
+ boolean crossUserAccess) {
List<PhoneAccount> accounts = new ArrayList<>(mState.accounts.size());
for (PhoneAccount m : mState.accounts) {
if (!(m.isEnabled() || includeDisabledAccounts)) {
@@ -1339,7 +1349,7 @@
// Not the right package name; skip this one.
continue;
}
- if (!isVisibleForUser(m, userHandle, false)) {
+ if (!crossUserAccess && !isVisibleForUser(m, userHandle, false)) {
// Account is not visible for the current user; skip this one.
continue;
}
diff --git a/src/com/android/server/telecom/RespondViaSmsSettings.java b/src/com/android/server/telecom/RespondViaSmsSettings.java
index 661038b..d038a6e 100755
--- a/src/com/android/server/telecom/RespondViaSmsSettings.java
+++ b/src/com/android/server/telecom/RespondViaSmsSettings.java
@@ -89,6 +89,8 @@
if (actionBar != null) {
// android.R.id.home will be triggered in onOptionsItemSelected()
actionBar.setDisplayHomeAsUpEnabled(true);
+ // set the talkback voice prompt to "Back" instead of "Navigate Up"
+ actionBar.setHomeActionContentDescription(R.string.back);
}
}
diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java
index c859fde..2828d12 100644
--- a/src/com/android/server/telecom/Ringer.java
+++ b/src/com/android/server/telecom/Ringer.java
@@ -53,15 +53,20 @@
*/
@VisibleForTesting
public class Ringer {
- public static class VibrationEffectProxy {
- public VibrationEffect createWaveform(long[] timings, int[] amplitudes, int repeat) {
- return VibrationEffect.createWaveform(timings, amplitudes, repeat);
- }
+ /**
+ * Flag only for local debugging. Do not submit enabled.
+ */
+ private static final boolean DEBUG_RINGER = false;
- public VibrationEffect get(Uri ringtoneUri, Context context) {
- return VibrationEffect.get(ringtoneUri, context);
- }
+ public static class VibrationEffectProxy {
+ public VibrationEffect createWaveform(long[] timings, int[] amplitudes, int repeat) {
+ return VibrationEffect.createWaveform(timings, amplitudes, repeat);
}
+
+ public VibrationEffect get(Uri ringtoneUri, Context context) {
+ return VibrationEffect.get(ringtoneUri, context);
+ }
+ }
@VisibleForTesting
public VibrationEffect mDefaultVibrationEffect;
@@ -152,11 +157,10 @@
*/
private CompletableFuture<Void> mBlockOnRingingFuture = null;
- private CompletableFuture<Void> mVibrateFuture = CompletableFuture.completedFuture(null);
-
private InCallTonePlayer mCallWaitingPlayer;
private RingtoneFactory mRingtoneFactory;
private AudioManager mAudioManager;
+ private NotificationManager mNotificationManager;
/**
* Call objects that are ringing, vibrating or call-waiting. These are used only for logging
@@ -189,7 +193,8 @@
RingtoneFactory ringtoneFactory,
Vibrator vibrator,
VibrationEffectProxy vibrationEffectProxy,
- InCallController inCallController) {
+ InCallController inCallController,
+ NotificationManager notificationManager) {
mLock = new Object();
mSystemSettingsUtil = systemSettingsUtil;
@@ -202,6 +207,7 @@
mRingtoneFactory = ringtoneFactory;
mInCallController = inCallController;
mVibrationEffectProxy = vibrationEffectProxy;
+ mNotificationManager = notificationManager;
if (mContext.getResources().getBoolean(R.bool.use_simple_vibration_pattern)) {
mDefaultVibrationEffect = mVibrationEffectProxy.createWaveform(SIMPLE_VIBRATION_PATTERN,
@@ -213,6 +219,8 @@
mIsHapticPlaybackSupportedByDevice =
mSystemSettingsUtil.isHapticPlaybackSupported(mContext);
+
+ mAudioManager = mContext.getSystemService(AudioManager.class);
}
@VisibleForTesting
@@ -220,6 +228,11 @@
mBlockOnRingingFuture = future;
}
+ @VisibleForTesting
+ public void setNotificationManager(NotificationManager notificationManager) {
+ mNotificationManager = notificationManager;
+ }
+
public boolean startRinging(Call foregroundCall, boolean isHfpDeviceAttached) {
if (foregroundCall == null) {
Log.wtf(this, "startRinging called with null foreground call.");
@@ -258,9 +271,13 @@
}
if (attributes.isEndEarly()) {
+ boolean acquireAudioFocus = attributes.shouldAcquireAudioFocus();
if (attributes.letDialerHandleRinging()) {
Log.addEvent(foregroundCall, LogUtils.Events.SKIP_RINGING, "Dialer handles");
+ // Dialer will setup a ringtone, provide the audio focus if its audible.
+ acquireAudioFocus |= attributes.isRingerAudible();
}
+
if (attributes.isSilentRingingRequested()) {
Log.addEvent(foregroundCall, LogUtils.Events.SKIP_RINGING, "Silent ringing "
+ "requested");
@@ -268,17 +285,22 @@
if (mBlockOnRingingFuture != null) {
mBlockOnRingingFuture.complete(null);
}
- return attributes.shouldAcquireAudioFocus();
+ return acquireAudioFocus;
}
stopCallWaiting();
- VibrationEffect effect;
- CompletableFuture<Boolean> hapticsFuture = null;
// Determine if the settings and DND mode indicate that the vibrator can be used right now.
- boolean isVibratorEnabled = isVibratorEnabled(mContext, attributes.shouldRingForContact());
+ final boolean isVibratorEnabled =
+ isVibratorEnabled(mContext, attributes.shouldRingForContact());
boolean shouldApplyRampingRinger =
isVibratorEnabled && mSystemSettingsUtil.isRampingRingerEnabled(mContext);
+
+ boolean isHapticOnly = false;
+ boolean useCustomVibrationEffect = false;
+
+ mVolumeShaperConfig = null;
+
if (attributes.isRingerAudible()) {
mRingingCall = foregroundCall;
Log.addEvent(foregroundCall, LogUtils.Events.START_RINGER);
@@ -287,119 +309,152 @@
// ringtones should be available by the time this code executes. We can safely
// request the custom ringtone from the call and expect it to be current.
if (shouldApplyRampingRinger) {
- Log.i(this, "start ramping ringer.");
+ Log.i(this, "create ramping ringer.");
+ float silencePoint = (float) (RAMPING_RINGER_VIBRATION_DURATION)
+ / (float) (RAMPING_RINGER_VIBRATION_DURATION + RAMPING_RINGER_DURATION);
+ mVolumeShaperConfig =
+ new VolumeShaper.Configuration.Builder()
+ .setDuration(RAMPING_RINGER_VIBRATION_DURATION + RAMPING_RINGER_DURATION)
+ .setCurve(
+ new float[] {0.f, silencePoint + EPSILON /*keep monotonicity*/, 1.f},
+ new float[] {0.f, 0.f, 1.f})
+ .setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
+ .build();
if (mSystemSettingsUtil.isAudioCoupledVibrationForRampingRingerEnabled()) {
- effect = getVibrationEffectForCall(mRingtoneFactory, foregroundCall);
- } else {
- effect = mDefaultVibrationEffect;
+ useCustomVibrationEffect = true;
}
- if (mVolumeShaperConfig == null) {
- float silencePoint = (float) (RAMPING_RINGER_VIBRATION_DURATION)
- / (float) (RAMPING_RINGER_VIBRATION_DURATION + RAMPING_RINGER_DURATION);
- mVolumeShaperConfig = new VolumeShaper.Configuration.Builder()
- .setDuration(
- RAMPING_RINGER_VIBRATION_DURATION + RAMPING_RINGER_DURATION)
- .setCurve(new float[]{0.f, silencePoint + EPSILON /*keep monotonicity*/,
- 1.f}, new float[]{0.f, 0.f, 1.f})
- .setInterpolatorType(
- VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
- .build();
- }
- hapticsFuture = mRingtonePlayer.play(mRingtoneFactory, foregroundCall,
- mVolumeShaperConfig, attributes.isRingerAudible(), isVibratorEnabled);
} else {
+ if (DEBUG_RINGER) {
+ Log.i(this, "Create ringer with custom vibration effect");
+ }
// Ramping ringtone is not enabled.
- hapticsFuture = mRingtonePlayer.play(mRingtoneFactory, foregroundCall, null,
- attributes.isRingerAudible(), isVibratorEnabled);
- effect = getVibrationEffectForCall(mRingtoneFactory, foregroundCall);
+ useCustomVibrationEffect = true;
}
} else {
- Log.addEvent(foregroundCall, LogUtils.Events.SKIP_RINGING, "Inaudible: "
- + attributes.getInaudibleReason());
- if (isVibratorEnabled && mIsHapticPlaybackSupportedByDevice) {
- // Attempt to run the attentional haptic ringtone first and fallback to the default
- // vibration effect if hapticFuture is completed with false.
- hapticsFuture = mRingtonePlayer.play(mRingtoneFactory, foregroundCall, null,
- attributes.isRingerAudible(), isVibratorEnabled);
+ Log.addEvent(foregroundCall, LogUtils.Events.SKIP_RINGING,
+ "Inaudible: " + attributes.getInaudibleReason()
+ + " isVibratorEnabled=" + isVibratorEnabled);
+
+ if (isVibratorEnabled) {
+ // If ringer is not audible for this call, then the phone is in "Vibrate" mode.
+ // Use haptic-only ringtone or do not play anything.
+ isHapticOnly = true;
+ if (DEBUG_RINGER) {
+ Log.i(this, "Set ringtone as haptic only: " + isHapticOnly);
+ }
+ } else {
+ if (mBlockOnRingingFuture != null) {
+ mBlockOnRingingFuture.complete(null);
+ }
+ foregroundCall.setUserMissed(USER_MISSED_NO_VIBRATE);
+ return attributes.shouldAcquireAudioFocus(); // ringer not audible
}
- effect = mDefaultVibrationEffect;
}
- if (hapticsFuture != null) {
- final boolean shouldRingForContact = attributes.shouldRingForContact();
- final boolean isRingerAudible = attributes.isRingerAudible();
- mVibrateFuture = hapticsFuture.thenAccept(isUsingAudioCoupledHaptics -> {
- if (!isUsingAudioCoupledHaptics || !mIsHapticPlaybackSupportedByDevice) {
- Log.i(this, "startRinging: fileHasHaptics=%b, hapticsSupported=%b",
- isUsingAudioCoupledHaptics, mIsHapticPlaybackSupportedByDevice);
- maybeStartVibration(foregroundCall, shouldRingForContact, effect,
- isVibratorEnabled, isRingerAudible);
- } else if (shouldApplyRampingRinger
- && !mSystemSettingsUtil.isAudioCoupledVibrationForRampingRingerEnabled()) {
- Log.i(this, "startRinging: apply ramping ringer vibration");
- maybeStartVibration(foregroundCall, shouldRingForContact, effect,
- isVibratorEnabled, isRingerAudible);
- } else {
- Log.addEvent(foregroundCall, LogUtils.Events.SKIP_VIBRATION,
- "using audio-coupled haptics");
- }
- });
- if (mBlockOnRingingFuture != null) {
- mVibrateFuture.whenComplete((v, e) -> mBlockOnRingingFuture.complete(null));
+ boolean hapticChannelsMuted = !isVibratorEnabled || !mIsHapticPlaybackSupportedByDevice;
+ if (shouldApplyRampingRinger
+ && !mSystemSettingsUtil.isAudioCoupledVibrationForRampingRingerEnabled()
+ && isVibratorEnabled) {
+ Log.i(this, "Muted haptic channels since audio coupled ramping ringer is disabled");
+ hapticChannelsMuted = true;
+ } else if (hapticChannelsMuted) {
+ Log.i(this, "Muted haptic channels isVibratorEnabled=%s, hapticPlaybackSupported=%s",
+ isVibratorEnabled, mIsHapticPlaybackSupportedByDevice);
+ }
+ Ringtone ringtone;
+ if (isHapticOnly) {
+ if (hapticChannelsMuted) {
+ Log.i(this, "want haptic only ringtone but haptics are muted, skip ringtone play");
+ ringtone = null;
+ } else {
+ ringtone = mRingtoneFactory.getHapticOnlyRingtone();
}
} else {
+ ringtone = mRingtoneFactory.getRingtone(
+ foregroundCall, mVolumeShaperConfig, hapticChannelsMuted);
+ }
+
+ final VibrationEffect vibrationEffect;
+ if (useCustomVibrationEffect) {
+ if (DEBUG_RINGER) {
+ Log.d(this, "Using ringtone defined vibration effect.");
+ }
+ vibrationEffect = getVibrationEffectForRingtone(ringtone);
+ } else {
+ vibrationEffect = mDefaultVibrationEffect;
+ }
+
+ if (ringtone == null) {
+ Log.w(this, "No ringtone was found bail out from playing.");
+ // No ringtone was found, try as a last resort to check if vibration can be performed.
+ vibrateIfNeeded(/* isUsingAudioCoupledHaptics */ false, attributes, foregroundCall,
+ vibrationEffect, isVibratorEnabled);
if (mBlockOnRingingFuture != null) {
mBlockOnRingingFuture.complete(null);
}
- Log.w(this, "startRinging: No haptics future; fallback to default behavior");
- maybeStartVibration(foregroundCall, attributes.shouldRingForContact(), effect,
- isVibratorEnabled, attributes.isRingerAudible());
+ return attributes.shouldAcquireAudioFocus();
}
- return attributes.shouldAcquireAudioFocus();
+ boolean isUsingAudioCoupledHaptics = !hapticChannelsMuted && ringtone.hasHapticChannels();
+
+ // There is a ringtone and we want to play it.
+ mRingtonePlayer.play(ringtone);
+
+ vibrateIfNeeded(isUsingAudioCoupledHaptics, attributes, foregroundCall, vibrationEffect,
+ isVibratorEnabled);
+ if (mBlockOnRingingFuture != null) {
+ mBlockOnRingingFuture.complete(null);
+ }
+
+ // shouldAcquireAudioFocus is meant to be true, but that check is deferred to here
+ // because until now is when we actually know if the ringtone loading worked.
+ return attributes.shouldAcquireAudioFocus() || attributes.isRingerAudible();
}
- private void maybeStartVibration(Call foregroundCall, boolean shouldRingForContact,
- VibrationEffect effect, boolean isVibrationEnabled, boolean isRingerAudible) {
+ private void vibrateIfNeeded(boolean isUsingAudioCoupledHaptics, RingerAttributes attributes,
+ Call foregroundCall, VibrationEffect effect, boolean isVibratorEnabled) {
+ final boolean shouldRingForContact = attributes.shouldRingForContact();
+
+ if (isUsingAudioCoupledHaptics) {
+ Log.addEvent(
+ foregroundCall, LogUtils.Events.SKIP_VIBRATION, "using audio-coupled haptics");
+ return;
+ }
+
synchronized (mLock) {
- mAudioManager = mContext.getSystemService(AudioManager.class);
- if (isVibrationEnabled && !mIsVibrating && shouldRingForContact) {
+ if (isVibratorEnabled && !mIsVibrating && shouldRingForContact) {
Log.addEvent(foregroundCall, LogUtils.Events.START_VIBRATOR,
- "hasVibrator=%b, userRequestsVibrate=%b, ringerMode=%d, isVibrating=%b",
- mVibrator.hasVibrator(),
- mSystemSettingsUtil.isRingVibrationEnabled(mContext),
- mAudioManager.getRingerMode(), mIsVibrating);
- if (mSystemSettingsUtil.isRampingRingerEnabled(mContext) && isRingerAudible) {
- Log.i(this, "start vibration for ramping ringer.");
- } else {
- Log.i(this, "start normal vibration.");
- }
+ "hasVibrator=%b, userRequestsVibrate=%b, ringerMode=%d, isVibrating=%b",
+ mVibrator.hasVibrator(), mSystemSettingsUtil.isRingVibrationEnabled(mContext),
+ mAudioManager.getRingerMode(), mIsVibrating);
mIsVibrating = true;
mVibrator.vibrate(effect, VIBRATION_ATTRIBUTES);
+ Log.i(this, "start vibration.");
} else {
foregroundCall.setUserMissed(USER_MISSED_NO_VIBRATE);
Log.addEvent(foregroundCall, LogUtils.Events.SKIP_VIBRATION,
- "hasVibrator=%b, userRequestsVibrate=%b, ringerMode=%d, isVibrating=%b",
- mVibrator.hasVibrator(),
- mSystemSettingsUtil.isRingVibrationEnabled(mContext),
- mAudioManager.getRingerMode(), mIsVibrating);
+ "hasVibrator=%b, userRequestsVibrate=%b, ringerMode=%d, isVibrating=%b",
+ mVibrator.hasVibrator(), mSystemSettingsUtil.isRingVibrationEnabled(mContext),
+ mAudioManager.getRingerMode(), mIsVibrating);
}
}
}
- private VibrationEffect getVibrationEffectForCall(RingtoneFactory factory, Call call) {
+ private VibrationEffect getVibrationEffectForRingtone(Ringtone ringtone) {
VibrationEffect effect = null;
- Ringtone ringtone = factory.getRingtone(call);
Uri ringtoneUri = ringtone != null ? ringtone.getUri() : null;
if (ringtoneUri != null) {
try {
effect = mVibrationEffectProxy.get(ringtoneUri, mContext);
+ if (effect == null) {
+ Log.i(this, "did not find vibration effect, falling back to default vibration");
+ }
} catch (IllegalArgumentException iae) {
// Deep in the bowels of the VibrationEffect class it is possible for an
// IllegalArgumentException to be thrown if there is an invalid URI specified in the
// device config, or a content provider failure. Rather than crashing the Telecom
// process we will just use the default vibration effect.
- Log.e(this, iae, "getVibrationEffectForCall: failed to get vibration effect");
+ Log.e(this, iae, "getVibrationEffectForRingtone: failed to get vibration effect");
effect = null;
}
}
@@ -419,7 +474,8 @@
return;
}
- if (mInCallController.doesConnectedDialerSupportRinging()) {
+ if (mInCallController.doesConnectedDialerSupportRinging(
+ call.getUserHandleFromTargetPhoneAccount())) {
Log.addEvent(call, LogUtils.Events.SKIP_RINGING, "Dialer handles");
return;
}
@@ -451,12 +507,6 @@
mRingtonePlayer.stop();
- // If we haven't started vibrating because we were waiting for the haptics info, cancel
- // it and don't vibrate at all.
- if (mVibrateFuture != null) {
- mVibrateFuture.cancel(true);
- }
-
if (mIsVibrating) {
Log.addEvent(mVibratingCall, LogUtils.Events.STOP_VIBRATOR);
mVibrator.cancel();
@@ -483,16 +533,33 @@
return mRingtonePlayer.isPlaying();
}
- private boolean shouldRingForContact(Uri contactUri) {
- final NotificationManager manager =
- (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ /**
+ * shouldRingForContact checks if the caller matches one of the Do Not Disturb bypass
+ * settings (ex. A contact or repeat caller might be able to bypass DND settings). If
+ * matchesCallFilter returns true, this means the caller can bypass the Do Not Disturb settings
+ * and interrupt the user; otherwise call is suppressed.
+ */
+ public boolean shouldRingForContact(Call call) {
+ // avoid re-computing manager.matcherCallFilter(Bundle)
+ if (call.wasDndCheckComputedForCall()) {
+ Log.v(this, "shouldRingForContact: returning computation from DndCallFilter.");
+ return !call.isCallSuppressedByDoNotDisturb();
+ }
+
+ final Uri contactUri = call.getHandle();
final Bundle peopleExtras = new Bundle();
if (contactUri != null) {
ArrayList<Person> personList = new ArrayList<>();
personList.add(new Person.Builder().setUri(contactUri.toString()).build());
peopleExtras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, personList);
}
- return manager.matchesCallFilter(peopleExtras);
+
+ // query NotificationManager
+ boolean shouldRing = mNotificationManager.matchesCallFilter(peopleExtras);
+ // store the suppressed status in the call object
+ call.setCallIsSuppressedByDoNotDisturb(!shouldRing);
+
+ return shouldRing;
}
private boolean hasExternalRinger(Call foregroundCall) {
@@ -508,10 +575,8 @@
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
// Use AudioManager#getRingerMode for more accurate result, instead of
// AudioManager#getRingerModeInternal which only useful for volume controllers
- NotificationManager notificationManager = context.getSystemService(
- NotificationManager.class);
- boolean zenModeOn = notificationManager != null
- && notificationManager.getZenMode() != ZEN_MODE_OFF;
+ boolean zenModeOn = mNotificationManager != null
+ && mNotificationManager.getZenMode() != ZEN_MODE_OFF;
return mVibrator.hasVibrator()
&& mSystemSettingsUtil.isRingVibrationEnabled(context)
&& (audioManager.getRingerMode() != AudioManager.RINGER_MODE_SILENT
@@ -526,22 +591,19 @@
boolean isVolumeOverZero = mAudioManager.getStreamVolume(AudioManager.STREAM_RING) > 0;
timer.record("isVolumeOverZero");
- boolean shouldRingForContact = shouldRingForContact(call.getHandle());
+ boolean shouldRingForContact = shouldRingForContact(call);
timer.record("shouldRingForContact");
- boolean isRingtonePresent = !(mRingtoneFactory.getRingtone(call) == null);
- timer.record("getRingtone");
boolean isSelfManaged = call.isSelfManaged();
timer.record("isSelfManaged");
boolean isSilentRingingRequested = call.isSilentRingingRequested();
timer.record("isSilentRingRequested");
- boolean isRingerAudible = isVolumeOverZero && shouldRingForContact && isRingtonePresent;
+ boolean isRingerAudible = isVolumeOverZero && shouldRingForContact;
timer.record("isRingerAudible");
String inaudibleReason = "";
if (!isRingerAudible) {
- inaudibleReason = String.format(
- "isVolumeOverZero=%s, shouldRingForContact=%s, isRingtonePresent=%s",
- isVolumeOverZero, shouldRingForContact, isRingtonePresent);
+ inaudibleReason = String.format("isVolumeOverZero=%s, shouldRingForContact=%s",
+ isVolumeOverZero, shouldRingForContact);
}
boolean hasExternalRinger = hasExternalRinger(call);
@@ -549,7 +611,8 @@
// Don't do call waiting operations or vibration unless these are false.
boolean isTheaterModeOn = mSystemSettingsUtil.isTheaterModeOn(mContext);
timer.record("isTheaterModeOn");
- boolean letDialerHandleRinging = mInCallController.doesConnectedDialerSupportRinging();
+ boolean letDialerHandleRinging = mInCallController.doesConnectedDialerSupportRinging(
+ call.getUserHandleFromTargetPhoneAccount());
timer.record("letDialerHandleRinging");
Log.i(this, "startRinging timings: " + timer);
@@ -566,10 +629,10 @@
// Acquire audio focus under any of the following conditions:
// 1. Should ring for contact and there's an HFP device attached
// 2. Volume is over zero, we should ring for the contact, and there's a audible ringtone
- // present.
+ // present. (This check is deferred until ringer knows the ringtone)
// 3. The call is self-managed.
boolean shouldAcquireAudioFocus =
- isRingerAudible || (isHfpDeviceAttached && shouldRingForContact) || isSelfManaged;
+ (isHfpDeviceAttached && shouldRingForContact) || isSelfManaged;
// Set missed reason according to attributes
if (!isVolumeOverZero) {
diff --git a/src/com/android/server/telecom/RingtoneFactory.java b/src/com/android/server/telecom/RingtoneFactory.java
index 5c46998..6e8c7e3 100644
--- a/src/com/android/server/telecom/RingtoneFactory.java
+++ b/src/com/android/server/telecom/RingtoneFactory.java
@@ -65,7 +65,9 @@
}
public Ringtone getRingtone(Call incomingCall,
- @Nullable VolumeShaper.Configuration volumeShaperConfig) {
+ @Nullable VolumeShaper.Configuration volumeShaperConfig, boolean hapticChannelsMuted) {
+ AudioAttributes audioAttrs = getDefaultRingtoneAudioAttributes(hapticChannelsMuted);
+
// Use the default ringtone of the work profile if the contact is a work profile contact.
Context userContext = isWorkContact(incomingCall) ?
getWorkProfileContextForUser(mCallsManager.getCurrentUserHandle()) :
@@ -73,8 +75,6 @@
Uri ringtoneUri = incomingCall.getRingtone();
Ringtone ringtone = null;
- AudioAttributes audioAttrs = getRingtoneAudioAttributes();
-
if(ringtoneUri != null && userContext != null) {
// Ringtone URI is explicitly specified. First, try to create a Ringtone with that.
try {
@@ -101,9 +101,11 @@
Log.i(this, "getRingtone: Settings.System.DEFAULT_RINGTONE_URI is null.");
}
}
+
if (defaultRingtoneUri == null) {
return null;
}
+
try {
ringtone = RingtoneManager.getRingtone(
contextToUse, defaultRingtoneUri, volumeShaperConfig, audioAttrs);
@@ -114,24 +116,23 @@
return ringtone;
}
- public AudioAttributes getRingtoneAudioAttributes() {
+ public AudioAttributes getDefaultRingtoneAudioAttributes(boolean hapticChannelsMuted) {
return new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .setHapticChannelsMuted(hapticChannelsMuted)
.build();
}
- public Ringtone getRingtone(Call incomingCall) {
- return getRingtone(incomingCall, null);
- }
-
/** Returns a ringtone to be used when ringer is not audible for the incoming call. */
@Nullable
public Ringtone getHapticOnlyRingtone() {
Uri ringtoneUri = Uri.parse("file://" + mContext.getString(
com.android.internal.R.string.config_defaultRingtoneVibrationSound));
- AudioAttributes audioAttrs = getRingtoneAudioAttributes();
- Ringtone ringtone = RingtoneManager.getRingtone(mContext, ringtoneUri, null, audioAttrs);
+ AudioAttributes audioAttrs = getDefaultRingtoneAudioAttributes(
+ /* hapticChannelsMuted */ false);
+ Ringtone ringtone = RingtoneManager.getRingtone(
+ mContext, ringtoneUri, /* volumeShaperConfig */ null, audioAttrs);
if (ringtone != null) {
// Make sure the sound is muted.
ringtone.setVolume(0);
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 5015099..ab35043 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -70,7 +70,10 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
+import java.util.Set;
// TODO: Needed for move to system service: import com.android.internal.R;
@@ -207,11 +210,14 @@
}
synchronized (mLock) {
final UserHandle callingUserHandle = Binder.getCallingUserHandle();
+ boolean hasCrossUserAccess = mContext.checkCallingOrSelfPermission(
+ Manifest.permission.INTERACT_ACROSS_USERS)
+ == PackageManager.PERMISSION_GRANTED;
long token = Binder.clearCallingIdentity();
try {
return new ParceledListSlice<>(
mPhoneAccountRegistrar.getCallCapablePhoneAccounts(null,
- includeDisabledAccounts, callingUserHandle));
+ includeDisabledAccounts, callingUserHandle, hasCrossUserAccess));
} catch (Exception e) {
Log.e(this, e, "getCallCapablePhoneAccounts");
throw e;
@@ -307,7 +313,7 @@
try {
return new ParceledListSlice<>(mPhoneAccountRegistrar
.getCallCapablePhoneAccounts(uriScheme, false,
- callingUserHandle));
+ callingUserHandle, false));
} catch (Exception e) {
Log.e(this, e, "getPhoneAccountsSupportingScheme %s", uriScheme);
throw e;
@@ -361,42 +367,46 @@
public PhoneAccount getPhoneAccount(PhoneAccountHandle accountHandle,
String callingPackage) {
try {
- enforceCallingPackage(callingPackage, "getPhoneAccount");
- } catch (SecurityException se) {
- EventLog.writeEvent(0x534e4554, "196406138", Binder.getCallingUid(),
- "getPhoneAccount: invalid calling package");
- throw se;
- }
- synchronized (mLock) {
- final UserHandle callingUserHandle = Binder.getCallingUserHandle();
- if (CompatChanges.isChangeEnabled(
- TelecomManager.ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION,
- callingPackage, Binder.getCallingUserHandle())) {
- if (Binder.getCallingUid() != Process.SHELL_UID &&
- !canGetPhoneAccount(callingPackage, accountHandle)) {
- SecurityException e = new SecurityException("getPhoneAccount API requires" +
- "READ_PHONE_NUMBERS");
+ Log.startSession("TSI.gPA", Log.getPackageAbbreviation(callingPackage));
+ try {
+ enforceCallingPackage(callingPackage, "getPhoneAccount");
+ } catch (SecurityException se) {
+ EventLog.writeEvent(0x534e4554, "196406138", Binder.getCallingUid(),
+ "getPhoneAccount: invalid calling package");
+ throw se;
+ }
+ synchronized (mLock) {
+ final UserHandle callingUserHandle = Binder.getCallingUserHandle();
+ if (CompatChanges.isChangeEnabled(
+ TelecomManager.ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION,
+ callingPackage, Binder.getCallingUserHandle())) {
+ if (Binder.getCallingUid() != Process.SHELL_UID &&
+ !canGetPhoneAccount(callingPackage, accountHandle)) {
+ SecurityException e = new SecurityException(
+ "getPhoneAccount API requires" +
+ "READ_PHONE_NUMBERS");
+ Log.e(this, e, "getPhoneAccount %s", accountHandle);
+ throw e;
+ }
+ }
+ long token = Binder.clearCallingIdentity();
+ try {
+ // In ideal case, we should not resolve the handle across profiles. But
+ // given the fact that profile's call is handled by its parent user's
+ // in-call UI, parent user's in call UI need to be able to get phone account
+ // from the profile's phone account handle.
+ return mPhoneAccountRegistrar
+ .getPhoneAccount(accountHandle, callingUserHandle,
+ /* acrossProfiles */ true);
+ } catch (Exception e) {
Log.e(this, e, "getPhoneAccount %s", accountHandle);
throw e;
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
- long token = Binder.clearCallingIdentity();
- try {
- Log.startSession("TSI.gPA");
- // In ideal case, we should not resolve the handle across profiles. But given
- // the fact that profile's call is handled by its parent user's in-call UI,
- // parent user's in call UI need to be able to get phone account from the
- // profile's phone account handle.
- return mPhoneAccountRegistrar
- .getPhoneAccount(accountHandle, callingUserHandle,
- /* acrossProfiles */ true);
- } catch (Exception e) {
- Log.e(this, e, "getPhoneAccount %s", accountHandle);
- throw e;
- } finally {
- Binder.restoreCallingIdentity(token);
- Log.endSession();
- }
+ } finally {
+ Log.endSession();
}
}
@@ -446,7 +456,7 @@
long token = Binder.clearCallingIdentity();
try {
return new ParceledListSlice<>(mPhoneAccountRegistrar
- .getAllPhoneAccounts(callingUserHandle));
+ .getAllPhoneAccounts(callingUserHandle, false));
} catch (Exception e) {
Log.e(this, e, "getAllPhoneAccounts");
throw e;
@@ -474,10 +484,13 @@
synchronized (mLock) {
final UserHandle callingUserHandle = Binder.getCallingUserHandle();
+ boolean hasCrossUserAccess = mContext.checkCallingOrSelfPermission(
+ Manifest.permission.INTERACT_ACROSS_USERS)
+ == PackageManager.PERMISSION_GRANTED;
long token = Binder.clearCallingIdentity();
try {
return new ParceledListSlice<>(mPhoneAccountRegistrar
- .getAllPhoneAccountHandles(callingUserHandle));
+ .getAllPhoneAccountHandles(callingUserHandle, hasCrossUserAccess));
} catch (Exception e) {
Log.e(this, e, "getAllPhoneAccounts");
throw e;
@@ -491,10 +504,10 @@
}
@Override
- public PhoneAccountHandle getSimCallManager(int subId) {
+ public PhoneAccountHandle getSimCallManager(int subId, String callingPackage) {
synchronized (mLock) {
try {
- Log.startSession("TSI.gSCM");
+ Log.startSession("TSI.gSCM", Log.getPackageAbbreviation(callingPackage));
final int callingUid = Binder.getCallingUid();
final int user = UserHandle.getUserId(callingUid);
long token = Binder.clearCallingIdentity();
@@ -516,10 +529,10 @@
}
@Override
- public PhoneAccountHandle getSimCallManagerForUser(int user) {
+ public PhoneAccountHandle getSimCallManagerForUser(int user, String callingPackage) {
synchronized (mLock) {
try {
- Log.startSession("TSI.gSCMFU");
+ Log.startSession("TSI.gSCMFU", Log.getPackageAbbreviation(callingPackage));
final int callingUid = Binder.getCallingUid();
if (user != ActivityManager.getCurrentUser()) {
enforceCrossUserPermission(callingUid);
@@ -540,9 +553,9 @@
}
@Override
- public void registerPhoneAccount(PhoneAccount account) {
+ public void registerPhoneAccount(PhoneAccount account, String callingPackage) {
try {
- Log.startSession("TSI.rPA");
+ Log.startSession("TSI.rPA", Log.getPackageAbbreviation(callingPackage));
synchronized (mLock) {
try {
enforcePhoneAccountModificationForPackage(
@@ -616,10 +629,11 @@
}
@Override
- public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
+ public void unregisterPhoneAccount(PhoneAccountHandle accountHandle,
+ String callingPackage) {
synchronized (mLock) {
try {
- Log.startSession("TSI.uPA");
+ Log.startSession("TSI.uPA", Log.getPackageAbbreviation(callingPackage));
enforcePhoneAccountModificationForPackage(
accountHandle.getComponentName().getPackageName());
enforceUserHandleMatchesCaller(accountHandle);
@@ -662,7 +676,7 @@
public boolean isVoiceMailNumber(PhoneAccountHandle accountHandle, String number,
String callingPackage, String callingFeatureId) {
try {
- Log.startSession("TSI.iVMN");
+ Log.startSession("TSI.iVMN", Log.getPackageAbbreviation(callingPackage));
synchronized (mLock) {
if (!canReadPhoneState(callingPackage, callingFeatureId, "isVoiceMailNumber")) {
return false;
@@ -695,7 +709,7 @@
public String getVoiceMailNumber(PhoneAccountHandle accountHandle, String callingPackage,
String callingFeatureId) {
try {
- Log.startSession("TSI.gVMN");
+ Log.startSession("TSI.gVMN", Log.getPackageAbbreviation(callingPackage));
if (!canReadPhoneState(callingPackage, callingFeatureId, "getVoiceMailNumber")) {
return null;
}
@@ -731,7 +745,7 @@
public String getLine1Number(PhoneAccountHandle accountHandle, String callingPackage,
String callingFeatureId) {
try {
- Log.startSession("getL1N");
+ Log.startSession("getL1N", Log.getPackageAbbreviation(callingPackage));
if (!canReadPhoneNumbers(callingPackage, callingFeatureId, "getLine1Number")) {
return null;
}
@@ -768,15 +782,16 @@
@Override
public void silenceRinger(String callingPackage) {
try {
- Log.startSession("TSI.sR");
+ Log.startSession("TSI.sR", Log.getPackageAbbreviation(callingPackage));
synchronized (mLock) {
enforcePermissionOrPrivilegedDialer(MODIFY_PHONE_STATE, callingPackage);
-
+ UserHandle callingUserHandle = Binder.getCallingUserHandle();
long token = Binder.clearCallingIdentity();
try {
Log.i(this, "Silence Ringer requested by %s", callingPackage);
- mCallsManager.getCallAudioManager().silenceRingers();
- mCallsManager.getInCallController().silenceRinger();
+ Set<UserHandle> userHandles = mCallsManager.getCallAudioManager().
+ silenceRingers(mContext, callingUserHandle);
+ mCallsManager.getInCallController().silenceRinger(userHandles);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -808,13 +823,14 @@
* @see android.telecom.TelecomManager#getDefaultDialerPackage
*/
@Override
- public String getDefaultDialerPackage() {
+ public String getDefaultDialerPackage(String callingPackage) {
try {
- Log.startSession("TSI.gDDP");
+ Log.startSession("TSI.gDDP", Log.getPackageAbbreviation(callingPackage));
+ int callerUserId = UserHandle.getCallingUserId();
final long token = Binder.clearCallingIdentity();
try {
return mDefaultDialerCache.getDefaultDialerApplication(
- ActivityManager.getCurrentUser());
+ callerUserId);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -852,9 +868,9 @@
* @see android.telecom.TelecomManager#getSystemDialerPackage
*/
@Override
- public String getSystemDialerPackage() {
+ public String getSystemDialerPackage(String callingPackage) {
try {
- Log.startSession("TSI.gSDP");
+ Log.startSession("TSI.gSDP", Log.getPackageAbbreviation(callingPackage));
return mDefaultDialerCache.getSystemDialerApplication();
} finally {
Log.endSession();
@@ -885,7 +901,7 @@
@Override
public boolean isInCall(String callingPackage, String callingFeatureId) {
try {
- Log.startSession("TSI.iIC");
+ Log.startSession("TSI.iIC", Log.getPackageAbbreviation(callingPackage));
if (!canReadPhoneState(callingPackage, callingFeatureId, "isInCall")) {
return false;
}
@@ -904,7 +920,7 @@
@Override
public boolean hasManageOngoingCallsPermission(String callingPackage) {
try {
- Log.startSession("TSI.hMOCP");
+ Log.startSession("TSI.hMOCP", Log.getPackageAbbreviation(callingPackage));
enforceCallingPackage(callingPackage, "hasManageOngoingCallsPermission");
return PermissionChecker.checkPermissionForDataDeliveryFromDataSource(
mContext, Manifest.permission.MANAGE_ONGOING_CALLS,
@@ -925,7 +941,7 @@
@Override
public boolean isInManagedCall(String callingPackage, String callingFeatureId) {
try {
- Log.startSession("TSI.iIMC");
+ Log.startSession("TSI.iIMC", Log.getPackageAbbreviation(callingPackage));
if (!canReadPhoneState(callingPackage, callingFeatureId, "isInManagedCall")) {
throw new SecurityException("Only the default dialer or caller with " +
"READ_PHONE_STATE permission can use this method.");
@@ -1002,6 +1018,22 @@
public int getCallStateUsingPackage(String callingPackage, String callingFeatureId) {
try {
Log.startSession("TSI.getCallStateUsingPackage");
+
+ // ensure the callingPackage is not spoofed
+ // skip check for privileged UIDs and throw SE if package does not match records
+ if (!isPrivilegedUid(callingPackage)
+ && !callingUidMatchesPackageManagerRecords(callingPackage)) {
+ EventLog.writeEvent(0x534e4554, "236813210", Binder.getCallingUid(),
+ "getCallStateUsingPackage");
+ Log.i(this,
+ "getCallStateUsingPackage: packageName does not match records for "
+ + "callingPackage=[%s], callingUid=[%d]",
+ callingPackage, Binder.getCallingUid());
+ throw new SecurityException(String.format("getCallStateUsingPackage: "
+ + "enforceCallingPackage: callingPackage=[%s], callingUid=[%d]",
+ callingPackage, Binder.getCallingUid()));
+ }
+
if (CompatChanges.isChangeEnabled(
TelecomManager.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION, callingPackage,
Binder.getCallingUserHandle())) {
@@ -1020,6 +1052,19 @@
}
}
+ private boolean isPrivilegedUid(String callingPackage) {
+ int callingUid = Binder.getCallingUid();
+ boolean isPrivileged = false;
+ switch (callingUid) {
+ case Process.ROOT_UID:
+ case Process.SYSTEM_UID:
+ case Process.SHELL_UID:
+ isPrivileged = true;
+ break;
+ }
+ return isPrivileged;
+ }
+
/**
* @see android.telecom.TelecomManager#endCall
*/
@@ -1103,9 +1148,10 @@
synchronized (mLock) {
+ UserHandle callingUser = Binder.getCallingUserHandle();
long token = Binder.clearCallingIdentity();
try {
- mCallsManager.getInCallController().bringToForeground(showDialpad);
+ mCallsManager.getInCallController().bringToForeground(showDialpad, callingUser);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1282,9 +1328,10 @@
* @see android.telecom.TelecomManager#addNewIncomingCall
*/
@Override
- public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
+ public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras,
+ String callingPackage) {
try {
- Log.startSession("TSI.aNIC");
+ Log.startSession("TSI.aNIC", Log.getPackageAbbreviation(callingPackage));
synchronized (mLock) {
Log.i(this, "Adding new incoming call with phoneAccountHandle %s",
phoneAccountHandle);
@@ -1302,7 +1349,7 @@
// Make sure it doesn't cross the UserHandle boundary
enforceUserHandleMatchesCaller(phoneAccountHandle);
enforcePhoneAccountIsRegisteredEnabled(phoneAccountHandle,
- Binder.getCallingUserHandle());
+ phoneAccountHandle.getUserHandle());
if (isSelfManagedConnectionService(phoneAccountHandle)) {
// Self-managed phone account, ensure it has MANAGE_OWN_CALLS.
mContext.enforceCallingOrSelfPermission(
@@ -1344,9 +1391,10 @@
* @see android.telecom.TelecomManager#addNewIncomingConference
*/
@Override
- public void addNewIncomingConference(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
+ public void addNewIncomingConference(PhoneAccountHandle phoneAccountHandle, Bundle extras,
+ String callingPackage) {
try {
- Log.startSession("TSI.aNIC");
+ Log.startSession("TSI.aNIC", Log.getPackageAbbreviation(callingPackage));
synchronized (mLock) {
Log.i(this, "Adding new incoming conference with phoneAccountHandle %s",
phoneAccountHandle);
@@ -1392,9 +1440,10 @@
* @see android.telecom.TelecomManager#acceptHandover
*/
@Override
- public void acceptHandover(Uri srcAddr, int videoState, PhoneAccountHandle destAcct) {
+ public void acceptHandover(Uri srcAddr, int videoState, PhoneAccountHandle destAcct,
+ String callingPackage) {
try {
- Log.startSession("TSI.aHO");
+ Log.startSession("TSI.aHO", Log.getPackageAbbreviation(callingPackage));
synchronized (mLock) {
Log.i(this, "acceptHandover; srcAddr=%s, videoState=%s, dest=%s",
Log.pii(srcAddr), VideoProfile.videoStateToString(videoState),
@@ -1625,10 +1674,11 @@
enforcePermission(MODIFY_PHONE_STATE);
enforcePermission(WRITE_SECURE_SETTINGS);
synchronized (mLock) {
+ int callerUserId = UserHandle.getCallingUserId();
long token = Binder.clearCallingIdentity();
try {
return mDefaultDialerCache.setDefaultDialer(packageName,
- ActivityManager.getCurrentUser());
+ callerUserId);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1726,8 +1776,13 @@
* @see android.telecom.TelecomManager#createManageBlockedNumbersIntent
*/
@Override
- public Intent createManageBlockedNumbersIntent() {
- return BlockedNumbersActivity.getIntentForStartingActivity();
+ public Intent createManageBlockedNumbersIntent(String callingPackage) {
+ try {
+ Log.startSession("TSI.cMBNI", Log.getPackageAbbreviation(callingPackage));
+ return BlockedNumbersActivity.getIntentForStartingActivity();
+ } finally {
+ Log.endSession();
+ }
}
@@ -1754,7 +1809,7 @@
@Override
public boolean isIncomingCallPermitted(PhoneAccountHandle phoneAccountHandle,
String callingPackage) {
- Log.startSession("TSI.iICP");
+ Log.startSession("TSI.iICP", Log.getPackageAbbreviation(callingPackage));
try {
enforceCallingPackage(callingPackage, "isIncomingCallPermitted");
enforcePhoneAccountHandleMatchesCaller(phoneAccountHandle, callingPackage);
@@ -1779,7 +1834,7 @@
@Override
public boolean isOutgoingCallPermitted(PhoneAccountHandle phoneAccountHandle,
String callingPackage) {
- Log.startSession("TSI.iOCP");
+ Log.startSession("TSI.iOCP", Log.getPackageAbbreviation(callingPackage));
try {
enforceCallingPackage(callingPackage, "isOutgoingCallPermitted");
enforcePhoneAccountHandleMatchesCaller(phoneAccountHandle, callingPackage);
@@ -1905,14 +1960,18 @@
synchronized (mLock) {
enforceShellOnly(Binder.getCallingUid(), "cleanupStuckCalls");
Binder.withCleanCallingIdentity(() -> {
+ Set<UserHandle> userHandles = new HashSet<>();
for (Call call : mCallsManager.getCalls()) {
call.cleanup();
if (call.getState() == CallState.DISCONNECTED
|| call.getState() == CallState.DISCONNECTING) {
mCallsManager.markCallAsRemoved(call);
}
+ userHandles.add(call.getUserHandleFromTargetPhoneAccount());
}
- mCallsManager.getInCallController().unbindFromServices();
+ for (UserHandle userHandle : userHandles) {
+ mCallsManager.getInCallController().unbindFromServices(userHandle);
+ }
});
}
} finally {
@@ -2375,21 +2434,49 @@
}
private void enforceCallingPackage(String packageName, String message) {
+ int callingUid = Binder.getCallingUid();
+
+ if (callingUid != Process.ROOT_UID &&
+ !callingUidMatchesPackageManagerRecords(packageName)) {
+ throw new SecurityException(message + ": Package " + packageName
+ + " does not belong to " + callingUid);
+ }
+ }
+
+ /**
+ * helper method that compares the binder_uid to what the packageManager_uid reports for the
+ * passed in packageName.
+ *
+ * returns true if the binder_uid matches the packageManager_uid records
+ */
+ private boolean callingUidMatchesPackageManagerRecords(String packageName) {
int packageUid = -1;
int callingUid = Binder.getCallingUid();
- PackageManager pm = mContext.createContextAsUser(
- UserHandle.getUserHandleForUid(callingUid), 0).getPackageManager();
+ PackageManager pm;
+ try{
+ pm = mContext.createContextAsUser(
+ UserHandle.getUserHandleForUid(callingUid), 0).getPackageManager();
+ }
+ catch (Exception e){
+ Log.i(this, "callingUidMatchesPackageManagerRecords:"
+ + " createContextAsUser hit exception=[%s]", e.toString());
+ return false;
+ }
if (pm != null) {
try {
packageUid = pm.getPackageUid(packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
- // packageUid is -1
+ // packageUid is -1.
}
}
- if (packageUid != callingUid && callingUid != Process.ROOT_UID) {
- throw new SecurityException(message + ": Package " + packageName
- + " does not belong to " + callingUid);
+
+ if (packageUid != callingUid) {
+ Log.i(this, "callingUidMatchesPackageManagerRecords: uid mismatch found for"
+ + "packageName=[%s]. packageManager reports packageUid=[%d] but "
+ + "binder reports callingUid=[%d]", packageName, packageUid, callingUid);
}
+
+ return packageUid == callingUid;
}
private void enforceTelecomFeature() {
@@ -2454,7 +2541,9 @@
private void enforceUserHandleMatchesCaller(PhoneAccountHandle accountHandle) {
if (!Binder.getCallingUserHandle().equals(accountHandle.getUserHandle())) {
- throw new SecurityException("Calling UserHandle does not match PhoneAccountHandle's");
+ // Enforce INTERACT_ACROSS_USERS if the calling user handle does not match
+ // phone account's user handle
+ enforceInAppCrossUserPermission();
}
}
@@ -2473,6 +2562,12 @@
}
}
+ private void enforceInAppCrossUserPermission() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS, "Must be system or have"
+ + " INTERACT_ACROSS_USERS permission");
+ }
+
// to be used for TestApi methods that can only be called with SHELL UID.
private void enforceShellOnly(int callingUid, String message) {
if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID) {
diff --git a/src/com/android/server/telecom/callfiltering/CallFilteringResult.java b/src/com/android/server/telecom/callfiltering/CallFilteringResult.java
index 84ce4d4..931d5bb 100644
--- a/src/com/android/server/telecom/callfiltering/CallFilteringResult.java
+++ b/src/com/android/server/telecom/callfiltering/CallFilteringResult.java
@@ -29,6 +29,7 @@
private boolean mShouldReject;
private boolean mShouldAddToCallLog;
private boolean mShouldShowNotification;
+ private boolean mDndSuppressed = false;
private boolean mShouldSilence = false;
private boolean mShouldScreenViaAudio = false;
private boolean mContactExists = false;
@@ -58,6 +59,11 @@
return this;
}
+ public Builder setDndSuppressed(boolean shouldPerformCheck) {
+ mDndSuppressed = shouldPerformCheck;
+ return this;
+ }
+
public Builder setShouldSilence(boolean shouldSilence) {
mShouldSilence = shouldSilence;
return this;
@@ -101,6 +107,7 @@
.setShouldReject(result.shouldReject)
.setShouldAddToCallLog(result.shouldAddToCallLog)
.setShouldShowNotification(result.shouldShowNotification)
+ .setDndSuppressed(result.shouldSuppressCallDueToDndStatus)
.setShouldSilence(result.shouldSilence)
.setCallBlockReason(result.mCallBlockReason)
.setShouldScreenViaAudio(result.shouldScreenViaAudio)
@@ -113,8 +120,9 @@
public CallFilteringResult build() {
return new CallFilteringResult(mShouldAllowCall, mShouldReject, mShouldSilence,
- mShouldAddToCallLog, mShouldShowNotification, mCallBlockReason,
- mCallScreeningAppName, mCallScreeningComponentName, mCallScreeningResponse,
+ mShouldAddToCallLog, mShouldShowNotification,
+ mDndSuppressed, mCallBlockReason, mCallScreeningAppName,
+ mCallScreeningComponentName, mCallScreeningResponse,
mIsResponseFromSystemDialer, mShouldScreenViaAudio, mContactExists);
}
}
@@ -125,6 +133,7 @@
public boolean shouldAddToCallLog;
public boolean shouldScreenViaAudio = false;
public boolean shouldShowNotification;
+ public boolean shouldSuppressCallDueToDndStatus = false;
public int mCallBlockReason;
public CharSequence mCallScreeningAppName;
public String mCallScreeningComponentName;
@@ -133,8 +142,9 @@
public boolean contactExists;
private CallFilteringResult(boolean shouldAllowCall, boolean shouldReject, boolean
- shouldSilence, boolean shouldAddToCallLog, boolean shouldShowNotification, int
- callBlockReason, CharSequence callScreeningAppName, String callScreeningComponentName,
+ shouldSilence, boolean shouldAddToCallLog, boolean shouldShowNotification, boolean
+ shouldSuppress, int callBlockReason, CharSequence callScreeningAppName,
+ String callScreeningComponentName,
CallScreeningService.ParcelableCallResponse callScreeningResponse,
boolean isResponseFromSystemDialer,
boolean shouldScreenViaAudio, boolean contactExists) {
@@ -143,6 +153,7 @@
this.shouldSilence = shouldSilence;
this.shouldAddToCallLog = shouldAddToCallLog;
this.shouldShowNotification = shouldShowNotification;
+ this.shouldSuppressCallDueToDndStatus = shouldSuppress;
this.shouldScreenViaAudio = shouldScreenViaAudio;
this.mCallBlockReason = callBlockReason;
this.mCallScreeningAppName = callScreeningAppName;
@@ -202,6 +213,8 @@
.setShouldAddToCallLog(shouldAddToCallLog && other.shouldAddToCallLog)
.setShouldShowNotification(shouldShowNotification && other.shouldShowNotification)
.setShouldScreenViaAudio(shouldScreenViaAudio || other.shouldScreenViaAudio)
+ .setDndSuppressed(shouldSuppressCallDueToDndStatus
+ || other.shouldSuppressCallDueToDndStatus)
.setContactExists(contactExists || other.contactExists);
combineScreeningResponses(b, this, other);
return b.build();
@@ -228,6 +241,8 @@
.setShouldSilence(shouldSilence || other.shouldSilence)
.setShouldAddToCallLog(shouldAddToCallLog && other.shouldAddToCallLog)
.setShouldShowNotification(shouldShowNotification && other.shouldShowNotification)
+ .setDndSuppressed(shouldSuppressCallDueToDndStatus
+ || other.shouldSuppressCallDueToDndStatus)
.setShouldScreenViaAudio(shouldScreenViaAudio || other.shouldScreenViaAudio)
.setCallBlockReason(callBlockReason)
.setCallScreeningAppName(callScreeningAppName)
@@ -272,6 +287,7 @@
if (shouldSilence != that.shouldSilence) return false;
if (shouldAddToCallLog != that.shouldAddToCallLog) return false;
if (shouldShowNotification != that.shouldShowNotification) return false;
+ if (shouldSuppressCallDueToDndStatus != that.shouldSuppressCallDueToDndStatus) return false;
if (mCallBlockReason != that.mCallBlockReason) return false;
if (contactExists != that.contactExists) return false;
@@ -318,6 +334,10 @@
sb.append(", notified");
}
+ if (shouldSuppressCallDueToDndStatus) {
+ sb.append(", DND suppressed");
+ }
+
if (contactExists) {
sb.append(", contact exists");
}
diff --git a/src/com/android/server/telecom/callfiltering/DndCallFilter.java b/src/com/android/server/telecom/callfiltering/DndCallFilter.java
new file mode 100644
index 0000000..a100bad
--- /dev/null
+++ b/src/com/android/server/telecom/callfiltering/DndCallFilter.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.telecom.callfiltering;
+
+import android.telecom.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import com.android.server.telecom.Call;
+import com.android.server.telecom.LogUtils;
+import com.android.server.telecom.Ringer;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+
+/**
+ * DndCallFilter is a incoming call filter that adds the
+ * {@link android.telecom.Call.EXTRA_IS_SUPPRESSED_BY_DO_NOT_DISTURB } early in the call processing.
+ * Adding {@link android.telecom.Call.EXTRA_IS_SUPPRESSED_BY_DO_NOT_DISTURB } before the Call object
+ * is passed to all InCallServices is crucial for InCallServices that may disrupt the user and
+ * potentially bypass the current Do Not Disturb settings.
+ */
+public class DndCallFilter extends CallFilter {
+
+ private final Call mCall;
+ private final Ringer mRinger;
+
+ public DndCallFilter(Call call, Ringer ringer) {
+ mCall = call;
+ mRinger = ringer;
+ }
+
+ @VisibleForTesting
+ @Override
+ public CompletionStage<CallFilteringResult> startFilterLookup(CallFilteringResult result) {
+ CompletableFuture<CallFilteringResult> resultFuture = new CompletableFuture<>();
+
+ // start timer for query to NotificationManager
+ Log.addEvent(mCall, LogUtils.Events.DND_PRE_CHECK_INITIATED);
+
+ // query NotificationManager to determine if the call should ring or be suppressed
+ boolean shouldSuppress = !mRinger.shouldRingForContact(mCall);
+
+ // store the shouldSuppress value in the call object which will be passed to InCallServices
+ mCall.setCallIsSuppressedByDoNotDisturb(shouldSuppress);
+
+ // end timer
+ Log.addEvent(mCall, LogUtils.Events.DND_PRE_CHECK_COMPLETED, shouldSuppress);
+
+ // complete the resultFuture object
+ resultFuture.complete(new CallFilteringResult.Builder()
+ .setShouldAllowCall(true)
+ .setShouldAddToCallLog(true)
+ .setShouldShowNotification(true)
+ .setDndSuppressed(shouldSuppress)
+ .build());
+
+ return resultFuture;
+ }
+
+}
diff --git a/src/com/android/server/telecom/callfiltering/IncomingCallFilterGraph.java b/src/com/android/server/telecom/callfiltering/IncomingCallFilterGraph.java
index 9fa864e..d79e80e 100644
--- a/src/com/android/server/telecom/callfiltering/IncomingCallFilterGraph.java
+++ b/src/com/android/server/telecom/callfiltering/IncomingCallFilterGraph.java
@@ -41,6 +41,7 @@
.setShouldReject(false)
.setShouldAddToCallLog(true)
.setShouldShowNotification(true)
+ .setDndSuppressed(false)
.build();
private final CallFilterResultCallback mListener;
@@ -143,6 +144,7 @@
.setShouldSilence(false)
.setShouldAddToCallLog(true)
.setShouldShowNotification(true)
+ .setDndSuppressed(false)
.build();
for (CallFilter dependencyFilter : filter.getDependencies()) {
result = result.combine(dependencyFilter.getResult());
diff --git a/src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java b/src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java
index 2f057b0..c3e8976 100644
--- a/src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java
+++ b/src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java
@@ -74,7 +74,7 @@
mServiceType = serviceType;
}
- private void process() {
+ private void process(UserHandle userHandleForCallRedirection) {
Intent intent = new Intent(CallRedirectionService.SERVICE_INTERFACE)
.setComponent(mComponentName);
ServiceConnection connection = new CallRedirectionServiceConnection();
@@ -83,7 +83,7 @@
connection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
| Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS,
- UserHandle.CURRENT)) {
+ userHandleForCallRedirection)) {
Log.d(this, "bindService, found " + mServiceType + " call redirection service,"
+ " waiting for it to connect");
mConnection = connection;
@@ -327,7 +327,8 @@
mPhoneAccountHandle, mRedirectionGatewayInfo, mSpeakerphoneOn,
mVideoState, mShouldCancelCall, mUiAction);
} else {
- performCarrierCallRedirection();
+ // Use the current user for carrier call redirection
+ performCarrierCallRedirection(UserHandle.CURRENT);
}
} else if (mIsCarrierRedirectionPending) {
Log.addEvent(mCall, LogUtils.Events.REDIRECTION_COMPLETED_CARRIER);
@@ -343,39 +344,40 @@
/**
* The entry to perform call redirection of the call from (@link CallsManager)
*/
- public void performCallRedirection() {
+ public void performCallRedirection(UserHandle userHandleForCallRedirection) {
// If the Gateway Info is set with intent, only request with carrier call redirection.
if (mRedirectionGatewayInfo != null) {
- performCarrierCallRedirection();
+ // Use the current user for carrier call redirection
+ performCarrierCallRedirection(UserHandle.CURRENT);
} else {
- performUserDefinedCallRedirection();
+ performUserDefinedCallRedirection(userHandleForCallRedirection);
}
}
- private void performUserDefinedCallRedirection() {
+ private void performUserDefinedCallRedirection(UserHandle userHandleForCallRedirection) {
Log.d(this, "performUserDefinedCallRedirection");
ComponentName componentName =
mCallRedirectionProcessorHelper.getUserDefinedCallRedirectionService();
if (componentName != null) {
mAttempt = new CallRedirectionAttempt(componentName, SERVICE_TYPE_USER_DEFINED);
- mAttempt.process();
+ mAttempt.process(userHandleForCallRedirection);
mIsUserDefinedRedirectionPending = true;
processTimeoutForCallRedirection(SERVICE_TYPE_USER_DEFINED);
} else {
Log.i(this, "There are no user-defined call redirection services installed on this"
+ " device.");
- performCarrierCallRedirection();
+ performCarrierCallRedirection(UserHandle.CURRENT);
}
}
- private void performCarrierCallRedirection() {
+ private void performCarrierCallRedirection(UserHandle userHandleForCallRedirection) {
Log.d(this, "performCarrierCallRedirection");
ComponentName componentName =
mCallRedirectionProcessorHelper.getCarrierCallRedirectionService(
mPhoneAccountHandle);
if (componentName != null) {
mAttempt = new CallRedirectionAttempt(componentName, SERVICE_TYPE_CARRIER);
- mAttempt.process();
+ mAttempt.process(userHandleForCallRedirection);
mIsCarrierRedirectionPending = true;
processTimeoutForCallRedirection(SERVICE_TYPE_CARRIER);
} else {
diff --git a/src/com/android/server/telecom/settings/BlockedNumbersActivity.java b/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
index bc54e11..6e2eb97 100644
--- a/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
+++ b/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
@@ -101,6 +101,8 @@
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
+ // set the talkback voice prompt to "Back" instead of "Navigate Up"
+ actionBar.setHomeActionContentDescription(R.string.back);
}
if (!BlockedNumberContract.canCurrentUserBlockNumbers(this)) {
diff --git a/src/com/android/server/telecom/ui/AudioProcessingNotification.java b/src/com/android/server/telecom/ui/AudioProcessingNotification.java
index 7a61460..e38178e 100644
--- a/src/com/android/server/telecom/ui/AudioProcessingNotification.java
+++ b/src/com/android/server/telecom/ui/AudioProcessingNotification.java
@@ -19,6 +19,7 @@
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
+import android.os.UserHandle;
import android.telecom.Log;
import com.android.server.telecom.Call;
@@ -52,7 +53,8 @@
showAudioProcessingNotification(call);
} else if (oldState == CallState.AUDIO_PROCESSING
&& newState != CallState.AUDIO_PROCESSING) {
- cancelAudioProcessingNotification();
+ cancelAudioProcessingNotification(
+ call.getUserHandleFromTargetPhoneAccount());
}
}
@@ -66,7 +68,8 @@
@Override
public void onCallRemoved(Call call) {
if (call == mCallInAudioProcessing) {
- cancelAudioProcessingNotification();
+ cancelAudioProcessingNotification(
+ call.getUserHandleFromTargetPhoneAccount());
}
}
@@ -76,7 +79,8 @@
* @param call The missed call.
*/
private void showAudioProcessingNotification(Call call) {
- Log.i(this, "showAudioProcessingNotification");
+ Log.i(this, "showAudioProcessingNotification for user = %s",
+ call.getUserHandleFromTargetPhoneAccount());
mCallInAudioProcessing = call;
Notification.Builder builder = new Notification.Builder(mContext,
@@ -92,12 +96,14 @@
Notification notification = builder.build();
- mNotificationManager.notify(
- NOTIFICATION_TAG, AUDIO_PROCESSING_NOTIFICATION_ID, notification);
+ mNotificationManager.notifyAsUser(NOTIFICATION_TAG, AUDIO_PROCESSING_NOTIFICATION_ID,
+ notification, mCallInAudioProcessing.getUserHandleFromTargetPhoneAccount());
}
/** Cancels the audio processing notification. */
- private void cancelAudioProcessingNotification() {
- mNotificationManager.cancel(NOTIFICATION_TAG, AUDIO_PROCESSING_NOTIFICATION_ID);
+ private void cancelAudioProcessingNotification(UserHandle userHandle) {
+ Log.i(this, "cancelAudioProcessingNotification for user = %s", userHandle);
+ mNotificationManager.cancelAsUser(NOTIFICATION_TAG,
+ AUDIO_PROCESSING_NOTIFICATION_ID, userHandle);
}
}
diff --git a/src/com/android/server/telecom/ui/IncomingCallNotifier.java b/src/com/android/server/telecom/ui/IncomingCallNotifier.java
index 0c1c5a3..3b188d4 100644
--- a/src/com/android/server/telecom/ui/IncomingCallNotifier.java
+++ b/src/com/android/server/telecom/ui/IncomingCallNotifier.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import android.os.UserHandle;
import android.telecom.Log;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
@@ -166,22 +167,26 @@
showIncomingCallNotification(mIncomingCall);
} else if (hadIncomingCall && !hasIncomingCall) {
previousIncomingCall.removeListener(mCallListener);
- hideIncomingCallNotification();
+ hideIncomingCallNotification(
+ previousIncomingCall.getUserHandleFromTargetPhoneAccount());
}
}
}
private void showIncomingCallNotification(Call call) {
- Log.i(this, "showIncomingCallNotification showCall = %s", call);
+ Log.i(this, "showIncomingCallNotification showCall = %s for user = %s",
+ call, call.getUserHandleFromTargetPhoneAccount());
Notification.Builder builder = getNotificationBuilder(call,
mCallsManagerProxy.getActiveCall());
- mNotificationManager.notify(NOTIFICATION_TAG, NOTIFICATION_INCOMING_CALL, builder.build());
+ mNotificationManager.notifyAsUser(NOTIFICATION_TAG, NOTIFICATION_INCOMING_CALL,
+ builder.build(), call.getUserHandleFromTargetPhoneAccount());
}
- private void hideIncomingCallNotification() {
- Log.i(this, "hideIncomingCallNotification");
- mNotificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_INCOMING_CALL);
+ private void hideIncomingCallNotification(UserHandle userHandle) {
+ Log.i(this, "hideIncomingCallNotification for user = %s", userHandle);
+ mNotificationManager.cancelAsUser(NOTIFICATION_TAG, NOTIFICATION_INCOMING_CALL,
+ userHandle);
}
private String getNotificationName(Call call) {
diff --git a/src/com/android/server/telecom/voip/ParallelTransaction.java b/src/com/android/server/telecom/voip/ParallelTransaction.java
new file mode 100644
index 0000000..c2d532c
--- /dev/null
+++ b/src/com/android/server/telecom/voip/ParallelTransaction.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.telecom.voip;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * A VoipCallTransaction implementation that its sub transactions will be executed in parallel
+ */
+public class ParallelTransaction extends VoipCallTransaction {
+ public ParallelTransaction(List<VoipCallTransaction> subTransactions) {
+ super(subTransactions);
+ }
+
+ @Override
+ public void start() {
+ // post timeout work
+ mHandler.postDelayed(() -> {
+ if (mCompleted.getAndSet(true)) {
+ return;
+ }
+ if (mCompleteListener != null) {
+ mCompleteListener.onTransactionTimeout(mTransactionName);
+ }
+ finish();
+ }, TIMEOUT_LIMIT);
+
+ if (mSubTransactions != null && mSubTransactions.size() > 0) {
+ TransactionManager.TransactionCompleteListener subTransactionListener =
+ new TransactionManager.TransactionCompleteListener() {
+ private final AtomicInteger mCount = new AtomicInteger(mSubTransactions.size());
+
+ @Override
+ public void onTransactionCompleted(VoipCallTransactionResult result,
+ String transactionName) {
+ if (result.getResult() != VoipCallTransactionResult.RESULT_SUCCEED) {
+ mHandler.post(() -> {
+ VoipCallTransactionResult mainResult =
+ new VoipCallTransactionResult(
+ VoipCallTransactionResult.RESULT_FAILED,
+ String.format("sub transaction %s failed",
+ transactionName));
+ mCompleteListener.onTransactionCompleted(mainResult,
+ mTransactionName);
+ finish();
+ });
+ } else {
+ if (mCount.decrementAndGet() == 0) {
+ scheduleTransaction();
+ }
+ }
+ }
+
+ @Override
+ public void onTransactionTimeout(String transactionName) {
+ mHandler.post(() -> {
+ VoipCallTransactionResult mainResult = new VoipCallTransactionResult(
+ VoipCallTransactionResult.RESULT_FAILED,
+ String.format("sub transaction %s timed out",
+ transactionName));
+ mCompleteListener.onTransactionCompleted(mainResult,
+ mTransactionName);
+ finish();
+ });
+ }
+ };
+ for (VoipCallTransaction transaction : mSubTransactions) {
+ transaction.setCompleteListener(subTransactionListener);
+ transaction.start();
+ }
+ } else {
+ scheduleTransaction();
+ }
+ }
+}
diff --git a/src/com/android/server/telecom/voip/SerialTransaction.java b/src/com/android/server/telecom/voip/SerialTransaction.java
new file mode 100644
index 0000000..9fe547c
--- /dev/null
+++ b/src/com/android/server/telecom/voip/SerialTransaction.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.telecom.voip;
+
+import java.util.List;
+
+/**
+ * A VoipCallTransaction implementation that its sub transactions will be executed in serial
+ */
+public class SerialTransaction extends VoipCallTransaction {
+ public SerialTransaction(List<VoipCallTransaction> subTransactions) {
+ super(subTransactions);
+ }
+
+ @Override
+ public void start() {
+ // post timeout work
+ mHandler.postDelayed(() -> {
+ if (mCompleted.getAndSet(true)) {
+ return;
+ }
+ if (mCompleteListener != null) {
+ mCompleteListener.onTransactionTimeout(mTransactionName);
+ }
+ finish();
+ }, TIMEOUT_LIMIT);
+
+ if (mSubTransactions != null && mSubTransactions.size() > 0) {
+ TransactionManager.TransactionCompleteListener subTransactionListener =
+ new TransactionManager.TransactionCompleteListener() {
+
+ @Override
+ public void onTransactionCompleted(VoipCallTransactionResult result,
+ String transactionName) {
+ if (result.getResult() != VoipCallTransactionResult.RESULT_SUCCEED) {
+ mHandler.post(() -> {
+ VoipCallTransactionResult mainResult =
+ new VoipCallTransactionResult(
+ VoipCallTransactionResult.RESULT_FAILED,
+ String.format("sub transaction %s failed",
+ transactionName));
+ mCompleteListener.onTransactionCompleted(mainResult,
+ mTransactionName);
+ finish();
+ });
+ } else {
+ if (mSubTransactions.size() > 0) {
+ VoipCallTransaction transaction = mSubTransactions.remove(0);
+ transaction.setCompleteListener(this);
+ transaction.start();
+ } else {
+ scheduleTransaction();
+ }
+ }
+ }
+
+ @Override
+ public void onTransactionTimeout(String transactionName) {
+ mHandler.post(() -> {
+ VoipCallTransactionResult mainResult = new VoipCallTransactionResult(
+ VoipCallTransactionResult.RESULT_FAILED,
+ String.format("sub transaction %s timed out",
+ transactionName));
+ mCompleteListener.onTransactionCompleted(mainResult,
+ mTransactionName);
+ finish();
+ });
+ }
+ };
+ VoipCallTransaction transaction = mSubTransactions.remove(0);
+ transaction.setCompleteListener(subTransactionListener);
+ transaction.start();
+ } else {
+ scheduleTransaction();
+ }
+ }
+}
diff --git a/src/com/android/server/telecom/voip/TransactionManager.java b/src/com/android/server/telecom/voip/TransactionManager.java
new file mode 100644
index 0000000..27e8069
--- /dev/null
+++ b/src/com/android/server/telecom/voip/TransactionManager.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.telecom.voip;
+
+import android.os.OutcomeReceiver;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayDeque;
+import java.util.Queue;
+
+public class TransactionManager {
+ private static final String TAG = "VoipCallTransactionManager";
+ private static TransactionManager INSTANCE = null;
+ private static final Object sLock = new Object();
+ private Queue<VoipCallTransaction> mTransactions;
+ private VoipCallTransaction mCurrentTransaction;
+
+ public interface TransactionCompleteListener {
+ void onTransactionCompleted(VoipCallTransactionResult result, String transactionName);
+ void onTransactionTimeout(String transactionName);
+ }
+
+ private TransactionManager() {
+ mTransactions = new ArrayDeque<>();
+ mCurrentTransaction = null;
+
+ }
+
+ public static TransactionManager getInstance() {
+ synchronized (sLock) {
+ if (INSTANCE == null) {
+ INSTANCE = new TransactionManager();
+ }
+ }
+ return INSTANCE;
+ }
+
+ @VisibleForTesting
+ public static TransactionManager getTestInstance() {
+ return new TransactionManager();
+ }
+
+ public void addTransaction(VoipCallTransaction transaction,
+ OutcomeReceiver<VoipCallTransactionResult, Exception> receiver) {
+ synchronized (sLock) {
+ mTransactions.add(transaction);
+ transaction.setCompleteListener(new TransactionCompleteListener() {
+ @Override
+ public void onTransactionCompleted(VoipCallTransactionResult result,
+ String transactionName) {
+ if (result.getResult() == 0
+ /* TODO: change this to static value in TelecomManager */) {
+ receiver.onResult(result);
+ } else {
+ receiver.onError(new Exception());
+ }
+ finishTransaction();
+ }
+
+ @Override
+ public void onTransactionTimeout(String transactionName) {
+ receiver.onResult(new VoipCallTransactionResult(
+ VoipCallTransactionResult.RESULT_FAILED, transactionName + " timeout"));
+ finishTransaction();
+ }
+ });
+ }
+ startTransactions();
+ }
+
+ private void startTransactions() {
+ synchronized (sLock) {
+ if (mTransactions.isEmpty()) {
+ // No transaction waiting for process
+ return;
+ }
+
+ if (mCurrentTransaction != null) {
+ // Ongoing transaction
+ return;
+ }
+ mCurrentTransaction = mTransactions.poll();
+ mCurrentTransaction.start();
+ }
+ }
+
+ private void finishTransaction() {
+ synchronized (sLock) {
+ mCurrentTransaction = null;
+ }
+ startTransactions();
+ }
+
+ @VisibleForTesting
+ public void clear() {
+ synchronized (sLock) {
+ for (VoipCallTransaction transaction : mTransactions) {
+ transaction.finish();
+ }
+ }
+ }
+}
diff --git a/src/com/android/server/telecom/voip/VoipCallTransaction.java b/src/com/android/server/telecom/voip/VoipCallTransaction.java
new file mode 100644
index 0000000..413a1cd
--- /dev/null
+++ b/src/com/android/server/telecom/voip/VoipCallTransaction.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.telecom.voip;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+
+import com.android.server.telecom.LoggedHandlerExecutor;
+
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Function;
+
+public class VoipCallTransaction {
+ //TODO: add log events
+ protected static final long TIMEOUT_LIMIT = 5000L;
+ protected final AtomicBoolean mCompleted = new AtomicBoolean(false);
+ protected String mTransactionName = this.getClass().getSimpleName();
+ private HandlerThread mHandlerThread;
+ protected Handler mHandler;
+ protected TransactionManager.TransactionCompleteListener mCompleteListener;
+ protected List<VoipCallTransaction> mSubTransactions;
+
+ public VoipCallTransaction(
+ List<VoipCallTransaction> subTransactions) {
+ mSubTransactions = subTransactions;
+ mHandlerThread = new HandlerThread(this.toString());
+ mHandlerThread.start();
+ mHandler = new Handler(mHandlerThread.getLooper());
+ }
+
+ public VoipCallTransaction() {
+ this(null /** mSubTransactions */);
+ }
+
+ public void start() {
+ // post timeout work
+ mHandler.postDelayed(() -> {
+ if (mCompleted.getAndSet(true)) {
+ return;
+ }
+ if (mCompleteListener != null) {
+ mCompleteListener.onTransactionTimeout(mTransactionName);
+ }
+ finish();
+ }, TIMEOUT_LIMIT);
+
+ scheduleTransaction();
+ }
+
+ protected void scheduleTransaction() {
+ CompletableFuture<Void> future = CompletableFuture.completedFuture(null);
+ future.thenComposeAsync(this::processTransaction,
+ new LoggedHandlerExecutor(mHandler, mTransactionName + "@"
+ + hashCode() + ".pT", null))
+ .thenApplyAsync(
+ (Function<VoipCallTransactionResult, Void>) result -> {
+ mCompleted.set(true);
+ if (mCompleteListener != null) {
+ mCompleteListener.onTransactionCompleted(result, mTransactionName);
+ }
+ finish();
+ return null;
+ });
+ }
+
+ public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ return CompletableFuture.completedFuture(
+ new VoipCallTransactionResult(VoipCallTransactionResult.RESULT_SUCCEED, null));
+ }
+
+ public void setCompleteListener(TransactionManager.TransactionCompleteListener listener) {
+ mCompleteListener = listener;
+ }
+
+ public void finish() {
+ // finish all sub transactions
+ if (mSubTransactions != null && mSubTransactions.size() > 0) {
+ mSubTransactions.forEach(VoipCallTransaction::finish);
+ }
+ mHandlerThread.quit();
+ }
+}
diff --git a/src/com/android/server/telecom/voip/VoipCallTransactionResult.java b/src/com/android/server/telecom/voip/VoipCallTransactionResult.java
new file mode 100644
index 0000000..c610e06
--- /dev/null
+++ b/src/com/android/server/telecom/voip/VoipCallTransactionResult.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.telecom.voip;
+
+import com.android.server.telecom.Call;
+
+import java.util.Objects;
+
+public class VoipCallTransactionResult {
+ public static final int RESULT_SUCCEED = 0;
+ public static final int RESULT_FAILED = 1;
+
+ private int mResult;
+ private String mMessage;
+ private Call mCall;
+
+ public VoipCallTransactionResult(int result, String message) {
+ mResult = result;
+ mMessage = message;
+ }
+
+ public VoipCallTransactionResult(int result, Call call, String message) {
+ mResult = result;
+ mCall = call;
+ mMessage = message;
+ }
+
+ public int getResult() {
+ return mResult;
+ }
+
+ public String getMessage() {
+ return mMessage;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof VoipCallTransactionResult)) return false;
+ VoipCallTransactionResult that = (VoipCallTransactionResult) o;
+ return mResult == that.mResult && Objects.equals(mMessage, that.mMessage);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mResult, mMessage);
+ }
+}
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index 049a501..453450d 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -87,6 +87,7 @@
*/
@RunWith(JUnit4.class)
public class BasicCallTests extends TelecomSystemTest {
+ private static final String CALLING_PACKAGE = BasicCallTests.class.getPackageName();
private static final String TEST_BUNDLE_KEY = "android.telecom.extra.TEST";
private static final String TEST_EVENT = "android.telecom.event.TEST";
@@ -327,7 +328,7 @@
TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
Uri.fromParts(PhoneAccount.SCHEME_TEL, phoneNumber, null));
mTelecomSystem.getTelecomServiceImpl().getBinder()
- .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras);
+ .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras, CALLING_PACKAGE);
waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
TEST_TIMEOUT);
@@ -392,7 +393,7 @@
TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
Uri.fromParts(PhoneAccount.SCHEME_TEL, "650-555-1212", null));
mTelecomSystem.getTelecomServiceImpl().getBinder()
- .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras);
+ .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras, CALLING_PACKAGE);
waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
TEST_TIMEOUT);
@@ -442,7 +443,7 @@
TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
Uri.fromParts(PhoneAccount.SCHEME_TEL, "650-555-1212", null));
mTelecomSystem.getTelecomServiceImpl().getBinder()
- .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras);
+ .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras, CALLING_PACKAGE);
waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
TEST_TIMEOUT);
@@ -494,7 +495,7 @@
TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
Uri.fromParts(PhoneAccount.SCHEME_TEL, phoneNumber, null));
mTelecomSystem.getTelecomServiceImpl().getBinder()
- .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras);
+ .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras, CALLING_PACKAGE);
waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
TEST_TIMEOUT);
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
index 6092293..ed1979d 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
@@ -53,7 +53,9 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -89,6 +91,7 @@
@Mock ConnectionServiceWrapper mockConnectionServiceWrapper;
@Mock WiredHeadsetManager mockWiredHeadsetManager;
@Mock StatusBarNotifier mockStatusBarNotifier;
+ @Mock Call fakeSelfManagedCall;
@Mock Call fakeCall;
@Mock CallAudioManager mockCallAudioManager;
@@ -116,11 +119,16 @@
};
when(mockCallsManager.getForegroundCall()).thenReturn(fakeCall);
+ when(mockCallsManager.getTrackedCalls()).thenReturn(Set.of(fakeCall));
when(mockCallsManager.getLock()).thenReturn(mLock);
when(mockCallsManager.hasVideoCall()).thenReturn(false);
when(fakeCall.getConnectionService()).thenReturn(mockConnectionServiceWrapper);
when(fakeCall.isAlive()).thenReturn(true);
when(fakeCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_ALL);
+ when(fakeSelfManagedCall.getConnectionService()).thenReturn(mockConnectionServiceWrapper);
+ when(fakeSelfManagedCall.isAlive()).thenReturn(true);
+ when(fakeSelfManagedCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_ALL);
+ when(fakeSelfManagedCall.isSelfManaged()).thenReturn(true);
doNothing().when(mockConnectionServiceWrapper).onCallAudioStateChanged(any(Call.class),
any(CallAudioState.class));
@@ -153,6 +161,51 @@
assertNotNull(stateMachine);
}
+ @SmallTest
+ @Test
+ public void testTrackedCallsReceiveAudioRouteChange() {
+ CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine(
+ mContext,
+ mockCallsManager,
+ mockBluetoothRouteManager,
+ mockWiredHeadsetManager,
+ mockStatusBarNotifier,
+ mAudioServiceFactory,
+ CallAudioRouteStateMachine.EARPIECE_AUTO_DETECT,
+ mThreadHandler.getLooper());
+ stateMachine.setCallAudioManager(mockCallAudioManager);
+
+ Set<Call> trackedCalls = new HashSet<>(Arrays.asList(fakeCall, fakeSelfManagedCall));
+ when(mockCallsManager.getTrackedCalls()).thenReturn(trackedCalls);
+
+ // start state --> ROUTE_EARPIECE
+ CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE,
+ CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER);
+ stateMachine.initialize(initState);
+
+ stateMachine.setCallAudioManager(mockCallAudioManager);
+
+ assertEquals(stateMachine.getCurrentCallAudioState().getRoute(),
+ CallAudioRouteStateMachine.ROUTE_EARPIECE);
+
+ // ROUTE_EARPIECE --> ROUTE_SPEAKER
+ stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_SPEAKER,
+ CallAudioRouteStateMachine.SPEAKER_ON);
+
+ stateMachine.sendMessageWithSessionInfo(
+ CallAudioRouteStateMachine.UPDATE_SYSTEM_AUDIO_ROUTE);
+
+ waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);
+ waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);
+
+ // assert expected end state
+ assertEquals(stateMachine.getCurrentCallAudioState().getRoute(),
+ CallAudioRouteStateMachine.ROUTE_SPEAKER);
+ // should update the audio route on all tracked calls ...
+ verify(mockConnectionServiceWrapper, times(trackedCalls.size()))
+ .onCallAudioStateChanged(any(), any());
+ }
+
@MediumTest
@Test
public void testStreamRingMuteChange() {
@@ -749,6 +802,7 @@
mockConnectionServiceWrapper);
fakeCall = mock(Call.class);
when(mockCallsManager.getForegroundCall()).thenReturn(fakeCall);
+ when(mockCallsManager.getTrackedCalls()).thenReturn(Set.of(fakeCall));
when(fakeCall.getConnectionService()).thenReturn(mockConnectionServiceWrapper);
when(fakeCall.isAlive()).thenReturn(true);
when(fakeCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_ALL);
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java
index 3eacc3a..5caa432 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java
@@ -64,6 +64,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
@RunWith(Parameterized.class)
public class CallAudioRouteTransitionTests extends TelecomTestCase {
@@ -182,6 +183,7 @@
};
when(mockCallsManager.getForegroundCall()).thenReturn(fakeCall);
+ when(mockCallsManager.getTrackedCalls()).thenReturn(Set.of(fakeCall));
when(mockCallsManager.getLock()).thenReturn(mLock);
when(mockCallsManager.hasVideoCall()).thenReturn(false);
when(fakeCall.getConnectionService()).thenReturn(mockConnectionServiceWrapper);
diff --git a/tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java b/tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java
index 0a896a8..406b1f6 100644
--- a/tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java
@@ -193,9 +193,9 @@
startProcessWithNoGateWayInfo();
disableUserDefinedCallRedirectionService();
disableCarrierCallRedirectionService();
- mProcessor.performCallRedirection();
+ mProcessor.performCallRedirection(UserHandle.CURRENT);
verify(mContext, times(0)).bindServiceAsUser(any(Intent.class),
- any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+ any(ServiceConnection.class), anyInt(), eq(UserHandle.CURRENT));
verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), eq(mHandle),
eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION));
@@ -208,9 +208,9 @@
waitForHandlerAction(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY);
disableUserDefinedCallRedirectionService();
enableCarrierCallRedirectionService();
- mProcessor.performCallRedirection();
+ mProcessor.performCallRedirection(UserHandle.CURRENT);
verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
- any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+ any(ServiceConnection.class), anyInt(), eq(UserHandle.CURRENT));
verify(mCallsManager, times(0)).onCallRedirectionComplete(eq(mCall), any(),
eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION));
@@ -228,9 +228,9 @@
waitForHandlerAction(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY);
enableUserDefinedCallRedirectionService();
disableCarrierCallRedirectionService();
- mProcessor.performCallRedirection();
+ mProcessor.performCallRedirection(UserHandle.CURRENT);
verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
- any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+ any(ServiceConnection.class), anyInt(), eq(UserHandle.CURRENT));
verify(mCallsManager, times(0)).onCallRedirectionComplete(eq(mCall), any(),
eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
eq(false), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
@@ -256,10 +256,10 @@
waitForHandlerAction(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY);
enableUserDefinedCallRedirectionService();
enableCarrierCallRedirectionService();
- mProcessor.performCallRedirection();
+ mProcessor.performCallRedirection(UserHandle.CURRENT);
verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
- any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+ any(ServiceConnection.class), anyInt(), eq(UserHandle.CURRENT));
verify(mCallsManager, times(0)).onCallRedirectionComplete(eq(mCall), any(),
eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
eq(false), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
@@ -294,9 +294,9 @@
startProcessWithGateWayInfo();
enableUserDefinedCallRedirectionService();
enableCarrierCallRedirectionService();
- mProcessor.performCallRedirection();
+ mProcessor.performCallRedirection(UserHandle.CURRENT);
verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
- any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+ any(ServiceConnection.class), anyInt(), eq(UserHandle.CURRENT));
verify(mCallsManager, times(0)).onCallRedirectionComplete(eq(mCall), any(),
eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION));
@@ -313,13 +313,13 @@
enableUserDefinedCallRedirectionService();
disableCarrierCallRedirectionService();
- mProcessor.performCallRedirection();
+ mProcessor.performCallRedirection(UserHandle.CURRENT);
// Capture binding and mock it out.
ArgumentCaptor<ServiceConnection> serviceConnectionCaptor = ArgumentCaptor.forClass(
ServiceConnection.class);
verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
- serviceConnectionCaptor.capture(), anyInt(), any(UserHandle.class));
+ serviceConnectionCaptor.capture(), anyInt(), eq(UserHandle.CURRENT));
// Mock out a service which performed a redirection
IBinder mockBinder = mock(IBinder.class);
diff --git a/tests/src/com/android/server/telecom/tests/CallTest.java b/tests/src/com/android/server/telecom/tests/CallTest.java
index d326a29..0492f0a 100644
--- a/tests/src/com/android/server/telecom/tests/CallTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallTest.java
@@ -346,4 +346,30 @@
assertTrue(hasCallDirectionChanged[0]);
assertTrue(call.isIncoming());
}
+
+ @Test
+ public void testIsSuppressedByDoNotDisturbExtra() {
+ Call call = new Call(
+ "1", /* callId */
+ mContext,
+ mMockCallsManager,
+ mLock,
+ null /* ConnectionServiceRepository */,
+ mMockPhoneNumberUtilsAdapter,
+ TEST_ADDRESS,
+ null /* GatewayInfo */,
+ null /* connectionManagerPhoneAccountHandle */,
+ SIM_1_HANDLE,
+ Call.CALL_DIRECTION_UNDEFINED,
+ false /* shouldAttachToExistingConnection*/,
+ true /* isConference */,
+ mMockClockProxy,
+ mMockToastProxy);
+
+ assertFalse(call.wasDndCheckComputedForCall());
+ assertFalse(call.isCallSuppressedByDoNotDisturb());
+ call.setCallIsSuppressedByDoNotDisturb(true);
+ assertTrue(call.wasDndCheckComputedForCall());
+ assertTrue(call.isCallSuppressedByDoNotDisturb());
+ }
}
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
index 160114a..526ab69 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -383,7 +383,7 @@
when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
SIM_1_HANDLE);
when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
- any(), anyInt(), anyInt())).thenReturn(
+ any(), anyInt(), anyInt(), anyBoolean())).thenReturn(
new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
@@ -407,7 +407,7 @@
when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
null);
when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
- any(), anyInt(), anyInt())).thenReturn(
+ any(), anyInt(), anyInt(), anyBoolean())).thenReturn(
new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
@@ -431,8 +431,8 @@
when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
null);
when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
- any(), eq(PhoneAccount.CAPABILITY_VIDEO_CALLING), anyInt())).thenReturn(
- new ArrayList<>(Arrays.asList(SIM_2_HANDLE)));
+ any(), eq(PhoneAccount.CAPABILITY_VIDEO_CALLING), anyInt(), anyBoolean()))
+ .thenReturn(new ArrayList<>(Arrays.asList(SIM_2_HANDLE)));
List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
null /* phoneAcct */, TEST_ADDRESS, true /* isVideo */, false /* isEmergency */, null /* userHandle */)
@@ -455,11 +455,11 @@
null);
// When querying for video capable accounts, return nothing.
when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
- any(), eq(PhoneAccount.CAPABILITY_VIDEO_CALLING), anyInt())).thenReturn(
- Collections.emptyList());
+ any(), eq(PhoneAccount.CAPABILITY_VIDEO_CALLING), anyInt(), anyBoolean())).
+ thenReturn(Collections.emptyList());
// When querying for non-video capable accounts, return one.
when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
- any(), eq(0 /* none specified */), anyInt())).thenReturn(
+ any(), eq(0 /* none specified */), anyInt(), anyBoolean())).thenReturn(
new ArrayList<>(Arrays.asList(SIM_1_HANDLE)));
List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
null /* phoneAcct */, TEST_ADDRESS, true /* isVideo */, false /* isEmergency */, null /* userHandle */)
@@ -481,7 +481,7 @@
when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
null);
when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
- any(), anyInt(), anyInt())).thenReturn(
+ any(), anyInt(), anyInt(), anyBoolean())).thenReturn(
new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
@@ -502,7 +502,7 @@
when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
null);
when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
- any(), anyInt(), anyInt())).thenReturn(
+ any(), anyInt(), anyInt(), anyBoolean())).thenReturn(
new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
@@ -942,6 +942,43 @@
@SmallTest
@Test
+ public void testNoFilteringOfNetworkIdentifiedEmergencyCalls() {
+ // GIVEN an incoming call which is network identified as an emergency call.
+ Call incomingCall = addSpyCall(CallState.NEW);
+ incomingCall.setConnectionProperties(Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL);
+ doReturn(false).when(incomingCall).can(Connection.CAPABILITY_HOLD);
+ doReturn(false).when(incomingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
+ doReturn(true).when(incomingCall)
+ .hasProperty(Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL);
+ doReturn(true).when(incomingCall).setState(anyInt(), any());
+
+ // WHEN the incoming call is successfully added.
+ mCallsManager.onSuccessfulIncomingCall(incomingCall);
+
+ // THEN the incoming call is not using call filtering
+ verify(incomingCall).setIsUsingCallFiltering(eq(false));
+ }
+
+ @SmallTest
+ @Test
+ public void testNoFilteringOfEmergencySmsModeCalls() {
+ // GIVEN an incoming call which is network identified as an emergency call.
+ Call incomingCall = addSpyCall(CallState.NEW);
+ when(mComponentContextFixture.getTelephonyManager().isInEmergencySmsMode())
+ .thenReturn(true);
+ doReturn(false).when(incomingCall).can(Connection.CAPABILITY_HOLD);
+ doReturn(false).when(incomingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
+ doReturn(true).when(incomingCall).setState(anyInt(), any());
+
+ // WHEN the incoming call is successfully added.
+ mCallsManager.onSuccessfulIncomingCall(incomingCall);
+
+ // THEN the incoming call is not using call filtering
+ verify(incomingCall).setIsUsingCallFiltering(eq(false));
+ }
+
+ @SmallTest
+ @Test
public void testAcceptIncomingCallWhenHeadsetMediaButtonShortPress() {
// GIVEN an incoming call
Call incomingCall = addSpyCall();
@@ -1141,7 +1178,7 @@
when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
SIM_1_HANDLE);
when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
- any(), anyInt(), anyInt())).thenReturn(
+ any(), anyInt(), anyInt(), anyBoolean())).thenReturn(
new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
mCallsManager.addConnectionServiceRepositoryCache(SIM_2_HANDLE.getComponentName(),
SIM_2_HANDLE.getUserHandle(), service);
@@ -1477,7 +1514,7 @@
when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
SIM_1_HANDLE);
when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
- any(), anyInt(), anyInt())).thenReturn(
+ any(), anyInt(), anyInt(), anyBoolean())).thenReturn(
new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
// Let's add an existing call which is in connecting state; this emulates the case where
@@ -1676,6 +1713,43 @@
new UserHandle(90210)));
}
+ /**
+ * Verifies that if a {@link android.telecom.CallScreeningService} app can properly request
+ * notification show for rejected calls.
+ */
+ @SmallTest
+ @Test
+ public void testCallScreeningServiceRequestShowNotification() {
+ Call callSpy = addSpyCall(CallState.NEW);
+ CallFilteringResult result = new CallFilteringResult.Builder()
+ .setShouldAllowCall(false)
+ .setShouldReject(true)
+ .setCallScreeningComponentName("com.foo/.Blah")
+ .setCallScreeningAppName("Blah")
+ .setShouldAddToCallLog(true)
+ .setShouldShowNotification(true).build();
+
+ mCallsManager.onCallFilteringComplete(callSpy, result, false /* timeout */);
+ verify(mMissedCallNotifier).showMissedCallNotification(
+ any(MissedCallNotifier.CallInfo.class));
+ }
+
+ @Test
+ public void testSetStateOnlyCalledOnce() {
+ // GIVEN a new self-managed call
+ Call newCall = addSpyCall();
+ doReturn(true).when(newCall).isSelfManaged();
+ newCall.setState(CallState.DISCONNECTED, "");
+
+ // WHEN ActionSetCallState is given a disconnect call
+ assertEquals(CallState.DISCONNECTED, newCall.getState());
+ // attempt to set the call active
+ mCallsManager.createActionSetCallStateAndPerformAction(newCall, CallState.ACTIVE, "");
+
+ // THEN assert remains disconnected
+ assertEquals(CallState.DISCONNECTED, newCall.getState());
+ }
+
@SmallTest
@Test
public void testCrossUserCallRedirectionEndEarlyForIncapablePhoneAccount() {
@@ -1780,7 +1854,7 @@
TelephonyManager mockTelephonyManager = mComponentContextFixture.getTelephonyManager();
when(mockTelephonyManager.getMaxNumberOfSimultaneouslyActiveSims()).thenReturn(1);
when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
- any(), anyInt(), anyInt())).thenReturn(
+ any(), anyInt(), anyInt(), anyBoolean())).thenReturn(
new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
when(mPhoneAccountRegistrar.getSimPhoneAccountsOfCurrentUser()).thenReturn(
new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
diff --git a/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java b/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java
index cb376af..f977ddb 100644
--- a/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java
+++ b/tests/src/com/android/server/telecom/tests/CreateConnectionProcessorTest.java
@@ -16,8 +16,10 @@
package com.android.server.telecom.tests;
+import android.Manifest;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Binder;
@@ -55,6 +57,8 @@
import java.util.UUID;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.any;
@@ -75,6 +79,7 @@
private static final String TEST_PACKAGE = "com.android.server.telecom.tests";
private static final String TEST_CLASS =
"com.android.server.telecom.tests.MockConnectionService";
+ private static final UserHandle USER_HANDLE_10 = new UserHandle(10);
@Mock
ConnectionServiceRepository mMockConnectionServiceRepository;
@@ -137,7 +142,10 @@
SubscriptionManager.INVALID_SIM_SLOT_INDEX);
}
});
- when(mMockAccountRegistrar.getAllPhoneAccountsOfCurrentUser()).thenReturn(phoneAccounts);
+ when(mMockAccountRegistrar.getAllPhoneAccounts(any(UserHandle.class), anyBoolean()))
+ .thenReturn(phoneAccounts);
+ when(mMockCall.getUserHandleFromTargetPhoneAccount()).
+ thenReturn(Binder.getCallingUserHandle());
}
@Override
@@ -200,7 +208,7 @@
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
// Make sure the target phone account has the correct permissions
PhoneAccount mFakeTargetPhoneAccount = makeQuickAccount("cm_acct",
- PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
+ PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION, null);
when(mMockAccountRegistrar.getPhoneAccountUnchecked(pAHandle)).thenReturn(
mFakeTargetPhoneAccount);
@@ -229,7 +237,7 @@
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle);
PhoneAccount mFakeTargetPhoneAccount = makeQuickAccount("cm_acct",
- PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
+ PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION, null);
when(mMockAccountRegistrar.getPhoneAccountUnchecked(pAHandle)).thenReturn(
mFakeTargetPhoneAccount);
when(mMockCall.getConnectionService()).thenReturn(service);
@@ -269,7 +277,7 @@
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle);
PhoneAccount mFakeTargetPhoneAccount = makeQuickAccount("cm_acct",
- PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
+ PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION, null);
when(mMockAccountRegistrar.getPhoneAccountUnchecked(pAHandle)).thenReturn(
mFakeTargetPhoneAccount);
when(mMockCall.getConnectionService()).thenReturn(service);
@@ -315,7 +323,7 @@
// Do not use this account, even though it is a SIM subscription and can place emergency
// calls
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
- PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer", 0);
+ PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer", 0, null);
mapToSubSlot(emergencyPhoneAccount, 2 /*subId*/, 1 /*slotId*/);
phoneAccounts.add(emergencyPhoneAccount);
@@ -332,6 +340,36 @@
}
/**
+ * Ensure that when no phone accounts (visible to the user) are available for the call, we use
+ * an available sim from other another user (on the condition that the user has the
+ * INTERACT_ACROSS_USERS permission).
+ */
+ @SmallTest
+ @Test
+ public void testEmergencyCallAcrossUsers() throws Exception {
+ when(mMockCall.isEmergencyCall()).thenReturn(true);
+ when(mMockCall.isTestEmergencyCall()).thenReturn(false);
+ ConnectionServiceWrapper service = makeConnectionServiceWrapper();
+ // Add an emergency account associated with a different user and expect this to be called.
+ PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer",
+ 0, USER_HANDLE_10);
+ mapToSubSlot(emergencyPhoneAccount, 1 /*subId*/, 0 /*slotId*/);
+ phoneAccounts.add(emergencyPhoneAccount);
+ PhoneAccountHandle emergencyPhoneAccountHandle = emergencyPhoneAccount.getAccountHandle();
+
+ mTestCreateConnectionProcessor.process();
+
+ verify(mMockCall).setConnectionManagerPhoneAccount(eq(emergencyPhoneAccountHandle));
+ verify(mMockCall).setTargetPhoneAccount(eq(emergencyPhoneAccountHandle));
+ verify(mMockCall).setConnectionService(eq(service));
+ verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class));
+ // Notify successful connection to call
+ CallIdMapper mockCallIdMapper = mock(CallIdMapper.class);
+ mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null);
+ verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null);
+ }
+
+ /**
* Ensure that the non-emergency capable PhoneAccount and the SIM manager is not chosen to place
* the emergency call if there is an emergency capable PhoneAccount available as well.
*/
@@ -351,7 +389,7 @@
"cm_acct", 0);
phoneAccounts.add(callManagerPA);
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
- PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer", 0);
+ PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer", 0, null);
mapToSubSlot(emergencyPhoneAccount, 2 /*subId*/, 1 /*slotId*/);
phoneAccounts.add(emergencyPhoneAccount);
PhoneAccountHandle emergencyPhoneAccountHandle = emergencyPhoneAccount.getAccountHandle();
@@ -387,10 +425,10 @@
"cm_acct", 0);
phoneAccounts.add(callManagerPA);
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
- PhoneAccount emergencyPhoneAccount1 = makeEmergencyPhoneAccount("tel_emer1", 0);
+ PhoneAccount emergencyPhoneAccount1 = makeEmergencyPhoneAccount("tel_emer1", 0, null);
phoneAccounts.add(emergencyPhoneAccount1);
mapToSubSlot(emergencyPhoneAccount1, 1 /*subId*/, 1 /*slotId*/);
- PhoneAccount emergencyPhoneAccount2 = makeEmergencyPhoneAccount("tel_emer2", 0);
+ PhoneAccount emergencyPhoneAccount2 = makeEmergencyPhoneAccount("tel_emer2", 0, null);
phoneAccounts.add(emergencyPhoneAccount2);
mapToSubSlot(emergencyPhoneAccount2, 2 /*subId*/, 0 /*slotId*/);
PhoneAccountHandle emergencyPhoneAccountHandle2 = emergencyPhoneAccount2.getAccountHandle();
@@ -418,12 +456,12 @@
when(mMockCall.isEmergencyCall()).thenReturn(true);
when(mMockCall.isTestEmergencyCall()).thenReturn(false);
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
- PhoneAccount emergencyPhoneAccount1 = makeEmergencyPhoneAccount("tel_emer1", 0);
+ PhoneAccount emergencyPhoneAccount1 = makeEmergencyPhoneAccount("tel_emer1", 0, null);
mapToSubSlot(emergencyPhoneAccount1, 1 /*subId*/, 0 /*slotId*/);
setTargetPhoneAccount(mMockCall, emergencyPhoneAccount1.getAccountHandle());
phoneAccounts.add(emergencyPhoneAccount1);
PhoneAccount emergencyPhoneAccount2 = makeEmergencyPhoneAccount("tel_emer2",
- PhoneAccount.CAPABILITY_EMERGENCY_PREFERRED);
+ PhoneAccount.CAPABILITY_EMERGENCY_PREFERRED, null);
mapToSubSlot(emergencyPhoneAccount2, 2 /*subId*/, 1 /*slotId*/);
phoneAccounts.add(emergencyPhoneAccount2);
PhoneAccountHandle emergencyPhoneAccountHandle2 = emergencyPhoneAccount2.getAccountHandle();
@@ -455,10 +493,10 @@
"cm_acct", 0);
phoneAccounts.add(callManagerPA);
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
- PhoneAccount emergencyPhoneAccount1 = makeEmergencyPhoneAccount("tel_emer1", 0);
+ PhoneAccount emergencyPhoneAccount1 = makeEmergencyPhoneAccount("tel_emer1", 0, null);
mapToSubSlot(emergencyPhoneAccount1, 1 /*subId*/, 0 /*slotId*/);
phoneAccounts.add(emergencyPhoneAccount1);
- PhoneAccount emergencyPhoneAccount2 = makeEmergencyPhoneAccount("tel_emer2", 0);
+ PhoneAccount emergencyPhoneAccount2 = makeEmergencyPhoneAccount("tel_emer2", 0, null);
// Make this the user preferred account
mapToSubSlot(emergencyPhoneAccount2, 2 /*subId*/, 1 /*slotId*/);
setTargetPhoneAccount(mMockCall, emergencyPhoneAccount2.getAccountHandle());
@@ -492,13 +530,13 @@
"cm_acct", 0);
phoneAccounts.add(callManagerPA);
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
- PhoneAccount emergencyPhoneAccount1 = makeEmergencyPhoneAccount("tel_emer1", 0);
+ PhoneAccount emergencyPhoneAccount1 = makeEmergencyPhoneAccount("tel_emer1", 0, null);
// make this the user preferred account
setTargetPhoneAccount(mMockCall, emergencyPhoneAccount1.getAccountHandle());
mapToSubSlot(emergencyPhoneAccount1, 1 /*subId*/,
SubscriptionManager.INVALID_SIM_SLOT_INDEX /*slotId*/);
phoneAccounts.add(emergencyPhoneAccount1);
- PhoneAccount emergencyPhoneAccount2 = makeEmergencyPhoneAccount("tel_emer2", 0);
+ PhoneAccount emergencyPhoneAccount2 = makeEmergencyPhoneAccount("tel_emer2", 0, null);
mapToSubSlot(emergencyPhoneAccount2, 2 /*subId*/, 1 /*slotId*/);
phoneAccounts.add(emergencyPhoneAccount2);
PhoneAccountHandle emergencyPhoneAccountHandle2 = emergencyPhoneAccount2.getAccountHandle();
@@ -529,11 +567,11 @@
"cm_acct", 0);
phoneAccounts.add(callManagerPA);
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
- PhoneAccount emergencyPhoneAccount1 = makeEmergencyPhoneAccount("tel_emer1", 0);
+ PhoneAccount emergencyPhoneAccount1 = makeEmergencyPhoneAccount("tel_emer1", 0, null);
mapToSubSlot(emergencyPhoneAccount1, 1 /*subId*/,
SubscriptionManager.INVALID_SIM_SLOT_INDEX /*slotId*/);
phoneAccounts.add(emergencyPhoneAccount1);
- PhoneAccount emergencyPhoneAccount2 = makeEmergencyPhoneAccount("tel_emer2", 0);
+ PhoneAccount emergencyPhoneAccount2 = makeEmergencyPhoneAccount("tel_emer2", 0, null);
mapToSubSlot(emergencyPhoneAccount2, 2 /*subId*/, 1 /*slotId*/);
phoneAccounts.add(emergencyPhoneAccount2);
PhoneAccountHandle emergencyPhoneAccountHandle2 = emergencyPhoneAccount2.getAccountHandle();
@@ -593,7 +631,7 @@
PhoneAccount emerCallManagerPA = getNewEmergencyConnectionManagerPhoneAccount("cm_acct",
PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS);
ConnectionServiceWrapper service = makeConnectionServiceWrapper();
- PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer", 0);
+ PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer", 0, null);
phoneAccounts.add(emergencyPhoneAccount);
mapToSubSlot(regularAccount, 2 /*subId*/, 1 /*slotId*/);
mTestCreateConnectionProcessor.process();
@@ -682,7 +720,7 @@
private PhoneAccount makeEmergencyTestPhoneAccount(String id, int capabilities) {
final PhoneAccount emergencyPhoneAccount = makeQuickAccount(id, capabilities |
- PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS);
+ PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS, null);
PhoneAccountHandle emergencyPhoneAccountHandle = emergencyPhoneAccount.getAccountHandle();
givePhoneAccountBindPermission(emergencyPhoneAccountHandle);
when(mMockAccountRegistrar.getPhoneAccountUnchecked(emergencyPhoneAccountHandle))
@@ -690,10 +728,11 @@
return emergencyPhoneAccount;
}
- private PhoneAccount makeEmergencyPhoneAccount(String id, int capabilities) {
+ private PhoneAccount makeEmergencyPhoneAccount(String id, int capabilities,
+ UserHandle userHandle) {
final PhoneAccount emergencyPhoneAccount = makeQuickAccount(id, capabilities |
PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS |
- PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
+ PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION, userHandle);
PhoneAccountHandle emergencyPhoneAccountHandle = emergencyPhoneAccount.getAccountHandle();
givePhoneAccountBindPermission(emergencyPhoneAccountHandle);
when(mMockAccountRegistrar.getPhoneAccountUnchecked(emergencyPhoneAccountHandle))
@@ -702,7 +741,7 @@
}
private PhoneAccount makePhoneAccount(String id, int capabilities) {
- final PhoneAccount phoneAccount = makeQuickAccount(id, capabilities);
+ final PhoneAccount phoneAccount = makeQuickAccount(id, capabilities, null);
PhoneAccountHandle phoneAccountHandle = phoneAccount.getAccountHandle();
givePhoneAccountBindPermission(phoneAccountHandle);
when(mMockAccountRegistrar.getPhoneAccountUnchecked(
@@ -720,7 +759,7 @@
}
private PhoneAccountHandle getNewConnectionMangerHandleForCall(Call call, String id) {
- PhoneAccountHandle callManagerPAHandle = makeQuickAccountHandle(id);
+ PhoneAccountHandle callManagerPAHandle = makeQuickAccountHandle(id, null);
when(mMockAccountRegistrar.getSimCallManagerFromCall(eq(call))).thenReturn(
callManagerPAHandle);
givePhoneAccountBindPermission(callManagerPAHandle);
@@ -728,7 +767,7 @@
}
private PhoneAccountHandle getNewTargetPhoneAccountHandle(String id) {
- PhoneAccountHandle pAHandle = makeQuickAccountHandle(id);
+ PhoneAccountHandle pAHandle = makeQuickAccountHandle(id, null);
givePhoneAccountBindPermission(pAHandle);
return pAHandle;
}
@@ -739,7 +778,7 @@
private PhoneAccount createNewConnectionManagerPhoneAccountForCall(Call call, String id,
int capability) {
- PhoneAccount callManagerPA = makeQuickAccount(id, capability);
+ PhoneAccount callManagerPA = makeQuickAccount(id, capability, null);
when(mMockAccountRegistrar.getSimCallManagerFromCall(eq(call))).thenReturn(
callManagerPA.getAccountHandle());
givePhoneAccountBindPermission(callManagerPA.getAccountHandle());
@@ -749,7 +788,7 @@
}
private PhoneAccount getNewEmergencyConnectionManagerPhoneAccount(String id, int capability) {
- PhoneAccount callManagerPA = makeQuickAccount(id, capability);
+ PhoneAccount callManagerPA = makeQuickAccount(id, capability, null);
when(mMockAccountRegistrar.getSimCallManagerOfCurrentUser()).thenReturn(
callManagerPA.getAccountHandle());
givePhoneAccountBindPermission(callManagerPA.getAccountHandle());
@@ -766,21 +805,24 @@
ConnectionServiceWrapper wrapper = mock(ConnectionServiceWrapper.class);
when(mMockConnectionServiceRepository.getService(
eq(makeQuickConnectionServiceComponentName()),
- eq(Binder.getCallingUserHandle()))).thenReturn(wrapper);
+ any(UserHandle.class))).thenReturn(wrapper);
return wrapper;
}
- private static PhoneAccountHandle makeQuickAccountHandle(String id) {
- return new PhoneAccountHandle(makeQuickConnectionServiceComponentName(), id,
- Binder.getCallingUserHandle());
+ private static PhoneAccountHandle makeQuickAccountHandle(String id, UserHandle userHandle) {
+ if (userHandle == null) {
+ userHandle = Binder.getCallingUserHandle();
+ }
+ return new PhoneAccountHandle(makeQuickConnectionServiceComponentName(), id, userHandle);
}
- private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) {
- return new PhoneAccount.Builder(makeQuickAccountHandle(id), "label" + idx);
+ private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx,
+ UserHandle userHandle) {
+ return new PhoneAccount.Builder(makeQuickAccountHandle(id, userHandle), "label" + idx);
}
- private PhoneAccount makeQuickAccount(String id, int idx) {
- return makeQuickAccountBuilder(id, idx)
+ private PhoneAccount makeQuickAccount(String id, int idx, UserHandle userHandle) {
+ return makeQuickAccountBuilder(id, idx, userHandle)
.setAddress(Uri.parse("http://foo.com/" + idx))
.setSubscriptionAddress(Uri.parse("tel:555-000" + idx))
.setCapabilities(idx)
diff --git a/tests/src/com/android/server/telecom/tests/DndCallFilteringTests.java b/tests/src/com/android/server/telecom/tests/DndCallFilteringTests.java
new file mode 100644
index 0000000..4885d61
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/DndCallFilteringTests.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.telecom.tests;
+
+import android.net.Uri;
+
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.TimeUnit;
+
+
+import com.android.server.telecom.Call;
+import com.android.server.telecom.Ringer;
+import com.android.server.telecom.callfiltering.CallFilteringResult;
+import com.android.server.telecom.callfiltering.DndCallFilter;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.when;
+
+import junit.framework.Assert;
+
+@RunWith(JUnit4.class)
+public class DndCallFilteringTests extends TelecomTestCase {
+
+ // mocks
+ @Mock private Call mCall;
+ @Mock private Ringer mRinger;
+ // constants
+ private final long FILTER_TIMEOUT = 2000;
+
+ private final CallFilteringResult BASE_RESULT = new CallFilteringResult.Builder()
+ .setShouldAllowCall(true)
+ .setShouldAddToCallLog(true)
+ .setShouldShowNotification(true)
+ .build();
+
+
+ private final CallFilteringResult CALL_SUPPRESSED_RESULT = new CallFilteringResult.Builder()
+ .setShouldAllowCall(true)
+ .setShouldAddToCallLog(true)
+ .setShouldShowNotification(true)
+ .setDndSuppressed(true)
+ .build();
+
+ private final CallFilteringResult CALL_NOT_SUPPRESSED_RESULT = new CallFilteringResult.Builder()
+ .setShouldAllowCall(true)
+ .setShouldAddToCallLog(true)
+ .setShouldShowNotification(true)
+ .setDndSuppressed(false)
+ .build();
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ // Dynamic variables
+ Uri testHandle = Uri.parse("tel:1235551234");
+ when(mCall.getHandle()).thenReturn(testHandle);
+ when(mCall.wasDndCheckComputedForCall()).thenReturn(false);
+ }
+
+ @Override
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test DndCallFilter suppresses a call and builds a CALL_SUPPRESSED_RESULT when given
+ * a false shouldRingForContact answer.
+ *
+ * @throws Exception; should not throw
+ */
+ @Test
+ public void testShouldSuppressCall() throws Exception {
+ // GIVEN
+ DndCallFilter filter = new DndCallFilter(mCall, mRinger);
+
+ // WHEN
+ assertNotNull(filter);
+ when(mRinger.shouldRingForContact(mCall)).thenReturn(false);
+
+ // THEN
+ CompletionStage<CallFilteringResult> resultFuture = filter.startFilterLookup(BASE_RESULT);
+
+ Assert.assertEquals(CALL_SUPPRESSED_RESULT, resultFuture.toCompletableFuture()
+ .get(FILTER_TIMEOUT, TimeUnit.MILLISECONDS));
+ }
+
+ /**
+ * Test DndCallFilter allows a call to ring and builds a CALL_NOT_SUPPRESSED_RESULT when
+ * given a true shouldRingForContact answer.
+ *
+ * @throws Exception; should not throw
+ */
+ @Test
+ public void testCallShouldRingAndNotBeSuppressed() throws Exception {
+ // GIVEN
+ DndCallFilter filter = new DndCallFilter(mCall, mRinger);
+
+ // WHEN
+ assertNotNull(filter);
+ when(mRinger.shouldRingForContact(mCall)).thenReturn(true);
+
+ // THEN
+ CompletionStage<CallFilteringResult> resultFuture = filter.startFilterLookup(BASE_RESULT);
+
+ // ASSERT
+ Assert.assertEquals(CALL_NOT_SUPPRESSED_RESULT, resultFuture.toCompletableFuture()
+ .get(FILTER_TIMEOUT, TimeUnit.MILLISECONDS));
+ }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/server/telecom/tests/EmergencyCallHelperTest.java b/tests/src/com/android/server/telecom/tests/EmergencyCallHelperTest.java
new file mode 100644
index 0000000..380e327
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/EmergencyCallHelperTest.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2022 Tc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.telecom.tests;
+
+import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.server.telecom.Call;
+import com.android.server.telecom.DefaultDialerCache;
+import com.android.server.telecom.EmergencyCallHelper;
+import com.android.server.telecom.Timeouts;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(JUnit4.class)
+public class EmergencyCallHelperTest extends TelecomTestCase {
+ private static final String SYSTEM_DIALER_PACKAGE = "abc.xyz";
+ private EmergencyCallHelper mEmergencyCallHelper;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private DefaultDialerCache mDefaultDialerCache;
+ @Mock
+ private Timeouts.Adapter mTimeoutsAdapter;
+ @Mock
+ private UserHandle mUserHandle;
+ @Mock
+ private Call mCall;
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ MockitoAnnotations.initMocks(this);
+ mContext = mComponentContextFixture.getTestDouble().getApplicationContext();
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ mEmergencyCallHelper = new EmergencyCallHelper(mContext, mDefaultDialerCache,
+ mTimeoutsAdapter);
+ when(mDefaultDialerCache.getSystemDialerApplication()).thenReturn(SYSTEM_DIALER_PACKAGE);
+
+ //start with no perms
+ when(mPackageManager.checkPermission(eq(ACCESS_BACKGROUND_LOCATION),
+ eq(SYSTEM_DIALER_PACKAGE))).thenReturn(
+ PackageManager.PERMISSION_DENIED);
+
+ when(mPackageManager.checkPermission(eq(ACCESS_FINE_LOCATION),
+ eq(SYSTEM_DIALER_PACKAGE))).thenReturn(
+ PackageManager.PERMISSION_DENIED);
+
+ when(mCall.isEmergencyCall()).thenReturn(true);
+ when(mContext.getResources().getBoolean(R.bool.grant_location_permission_enabled)).thenReturn(
+ true);
+ }
+
+ @Override
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ private void verifyRevokeInvokedFor(String perm) {
+ verify(mPackageManager, times(1)).revokeRuntimePermission(eq(SYSTEM_DIALER_PACKAGE),
+ eq(perm), eq(mUserHandle));
+ }
+
+ private void verifyRevokeNotInvokedFor(String perm) {
+ verify(mPackageManager, never()).revokeRuntimePermission(eq(SYSTEM_DIALER_PACKAGE),
+ eq(perm), eq(mUserHandle));
+ }
+
+ private void verifyGrantInvokedFor(String perm) {
+ verify(mPackageManager, times(1)).grantRuntimePermission(
+ nullable(String.class),
+ eq(perm), eq(mUserHandle));
+ }
+
+ private void verifyGrantNotInvokedFor(String perm) {
+ verify(mPackageManager, never()).grantRuntimePermission(
+ nullable(String.class),
+ eq(perm), eq(mUserHandle));
+ }
+
+ @SmallTest
+ @Test
+ public void testEmergencyCallHelperRevokesOnlyFinePermAfterBackgroundPermGrantException() {
+
+ //granting of background location perm fails
+ doThrow(new SecurityException()).when(mPackageManager).grantRuntimePermission(
+ nullable(String.class),
+ eq(ACCESS_BACKGROUND_LOCATION), eq(mUserHandle));
+
+ mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(mCall, mUserHandle);
+ mEmergencyCallHelper.maybeRevokeTemporaryLocationPermission();
+
+ verifyGrantInvokedFor(ACCESS_BACKGROUND_LOCATION);
+ verifyGrantInvokedFor(ACCESS_FINE_LOCATION);
+ //only fine perm should be revoked
+ verifyRevokeNotInvokedFor(ACCESS_BACKGROUND_LOCATION);
+ verifyRevokeInvokedFor(ACCESS_FINE_LOCATION);
+ }
+
+ @SmallTest
+ @Test
+ public void testEmergencyCallHelperRevokesOnlyBackgroundPermAfterFinePermGrantException() {
+
+ //granting of fine location perm fails
+ doThrow(new SecurityException()).when(mPackageManager).grantRuntimePermission(
+ nullable(String.class),
+ eq(ACCESS_FINE_LOCATION), eq(mUserHandle));
+
+ mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(mCall, mUserHandle);
+ mEmergencyCallHelper.maybeRevokeTemporaryLocationPermission();
+
+ //only background perm should be revoked
+ verifyGrantInvokedFor(ACCESS_BACKGROUND_LOCATION);
+ verifyGrantInvokedFor(ACCESS_FINE_LOCATION);
+ //only fine perm should be revoked
+ verifyRevokeNotInvokedFor(ACCESS_FINE_LOCATION);
+ verifyRevokeInvokedFor(ACCESS_BACKGROUND_LOCATION);
+ }
+
+ @SmallTest
+ @Test
+ public void testNoPermGrantWhenPackageHasAllPerms() {
+
+ when(mPackageManager.checkPermission(eq(ACCESS_BACKGROUND_LOCATION),
+ eq(SYSTEM_DIALER_PACKAGE))).thenReturn(
+ PackageManager.PERMISSION_GRANTED);
+
+ when(mPackageManager.checkPermission(eq(ACCESS_FINE_LOCATION),
+ eq(SYSTEM_DIALER_PACKAGE))).thenReturn(
+ PackageManager.PERMISSION_GRANTED);
+
+ mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(mCall, mUserHandle);
+ mEmergencyCallHelper.maybeRevokeTemporaryLocationPermission();
+
+ //permissions should neither be granted or revoked
+ verifyGrantNotInvokedFor(ACCESS_BACKGROUND_LOCATION);
+ verifyGrantNotInvokedFor(ACCESS_FINE_LOCATION);
+ verifyRevokeNotInvokedFor(ACCESS_BACKGROUND_LOCATION);
+ verifyRevokeNotInvokedFor(ACCESS_FINE_LOCATION);
+ }
+
+ @SmallTest
+ @Test
+ public void testNoPermGrantForNonEmergencyCall() {
+
+ when(mCall.isEmergencyCall()).thenReturn(false);
+
+ mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(mCall, mUserHandle);
+ mEmergencyCallHelper.maybeRevokeTemporaryLocationPermission();
+
+ //permissions should neither be granted or revoked
+ verifyGrantNotInvokedFor(ACCESS_BACKGROUND_LOCATION);
+ verifyGrantNotInvokedFor(ACCESS_FINE_LOCATION);
+ verifyRevokeNotInvokedFor(ACCESS_BACKGROUND_LOCATION);
+ verifyRevokeNotInvokedFor(ACCESS_FINE_LOCATION);
+ }
+
+ @SmallTest
+ @Test
+ public void testNoPermGrantWhenGrantLocationPermissionIsFalse() {
+
+ when(mContext.getResources().getBoolean(R.bool.grant_location_permission_enabled)).thenReturn(
+ false);
+
+ mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(mCall, mUserHandle);
+ mEmergencyCallHelper.maybeRevokeTemporaryLocationPermission();
+
+ //permissions should neither be granted or revoked
+ verifyGrantNotInvokedFor(ACCESS_BACKGROUND_LOCATION);
+ verifyGrantNotInvokedFor(ACCESS_FINE_LOCATION);
+ verifyRevokeNotInvokedFor(ACCESS_BACKGROUND_LOCATION);
+ verifyRevokeNotInvokedFor(ACCESS_FINE_LOCATION);
+ }
+
+ @SmallTest
+ @Test
+ public void testOnlyFineLocationPermIsGrantedAndRevoked() {
+
+ when(mPackageManager.checkPermission(eq(ACCESS_BACKGROUND_LOCATION),
+ eq(SYSTEM_DIALER_PACKAGE))).thenReturn(
+ PackageManager.PERMISSION_GRANTED);
+
+ mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(mCall, mUserHandle);
+ mEmergencyCallHelper.maybeRevokeTemporaryLocationPermission();
+
+ //permissions should neither be granted or revoked
+ verifyGrantNotInvokedFor(ACCESS_BACKGROUND_LOCATION);
+ verifyGrantInvokedFor(ACCESS_FINE_LOCATION);
+ verifyRevokeNotInvokedFor(ACCESS_BACKGROUND_LOCATION);
+ verifyRevokeInvokedFor(ACCESS_FINE_LOCATION);
+ }
+
+ @SmallTest
+ @Test
+ public void testOnlyBackgroundLocationPermIsGrantedAndRevoked() {
+
+ when(mPackageManager.checkPermission(eq(ACCESS_FINE_LOCATION),
+ eq(SYSTEM_DIALER_PACKAGE))).thenReturn(
+ PackageManager.PERMISSION_GRANTED);
+
+ mEmergencyCallHelper.maybeGrantTemporaryLocationPermission(mCall, mUserHandle);
+ mEmergencyCallHelper.maybeRevokeTemporaryLocationPermission();
+
+ //permissions should neither be granted or revoked
+ verifyGrantNotInvokedFor(ACCESS_FINE_LOCATION);
+ verifyGrantInvokedFor(ACCESS_BACKGROUND_LOCATION);
+ verifyRevokeNotInvokedFor(ACCESS_FINE_LOCATION);
+ verifyRevokeInvokedFor(ACCESS_BACKGROUND_LOCATION);
+ }
+}
diff --git a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
index 3d387a8..d0a8383 100644
--- a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
+++ b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
@@ -35,6 +35,7 @@
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -95,6 +96,7 @@
import com.android.server.telecom.DefaultDialerCache;
import com.android.server.telecom.EmergencyCallHelper;
import com.android.server.telecom.InCallController;
+import com.android.server.telecom.ParcelableCallUtils;
import com.android.server.telecom.PhoneAccountRegistrar;
import com.android.server.telecom.R;
import com.android.server.telecom.RoleManagerAdapter;
@@ -112,6 +114,7 @@
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import org.mockito.invocation.InvocationOnMock;
@@ -144,6 +147,7 @@
@Mock Analytics.CallInfoImpl mCallInfo;
@Mock NotificationManager mNotificationManager;
@Mock PermissionInfo mMockPermissionInfo;
+ @Mock InCallController.InCallServiceInfo mInCallServiceInfo;
@Rule
public TestRule compatChangeRule = new PlatformCompatChangeRule();
@@ -172,7 +176,8 @@
private static final int APPOP_NONUI_UID = 7;
private static final PhoneAccountHandle PA_HANDLE =
- new PhoneAccountHandle(new ComponentName("pa_pkg", "pa_cls"), "pa_id");
+ new PhoneAccountHandle(new ComponentName("pa_pkg", "pa_cls"),
+ "pa_id_0", UserHandle.of(CURRENT_USER_ID));
private UserHandle mUserHandle = UserHandle.of(CURRENT_USER_ID);
private InCallController mInCallController;
@@ -191,6 +196,7 @@
super.setUp();
MockitoAnnotations.initMocks(this);
when(mMockCall.getAnalytics()).thenReturn(new Analytics.CallInfo());
+ when(mMockCall.getUserHandleFromTargetPhoneAccount()).thenReturn(mUserHandle);
doReturn(mMockResources).when(mMockContext).getResources();
doReturn(mMockAppOpsManager).when(mMockContext).getSystemService(AppOpsManager.class);
doReturn(SYS_PKG).when(mMockResources).getString(
@@ -285,6 +291,15 @@
@SmallTest
@Test
+ public void testBringToForeground_NoInCallServices() {
+ // verify that there is not any bound InCallServices for the user requesting for foreground
+ assertFalse(mInCallController.getInCallServices().containsKey(mUserHandle));
+ // ensure that the method behaves properly on invocation
+ mInCallController.bringToForeground(true /* showDialPad */, mUserHandle /* callingUser */);
+ }
+
+ @SmallTest
+ @Test
public void testCarModeAppRemoval() {
setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
@@ -348,6 +363,7 @@
when(mMockCallsManager.isInEmergencyCall()).thenReturn(false);
when(mMockCall.isIncoming()).thenReturn(true);
when(mMockCall.isExternalCall()).thenReturn(false);
+ when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
when(mTimeoutsAdapter.getEmergencyCallbackWindowMillis(any(ContentResolver.class)))
.thenReturn(300_000L);
@@ -359,7 +375,7 @@
bindIntentCaptor.capture(),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
Intent bindIntent = bindIntentCaptor.getValue();
assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
@@ -393,7 +409,7 @@
bindIntentCaptor.capture(),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
Intent bindIntent = bindIntentCaptor.getValue();
assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
@@ -421,7 +437,7 @@
when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID))
.thenReturn(DEF_PKG);
when(mMockContext.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class),
- anyInt(), eq(UserHandle.CURRENT))).thenReturn(true);
+ anyInt(), eq(mUserHandle))).thenReturn(true);
setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
mInCallController.bindToServices(mMockCall);
@@ -445,7 +461,7 @@
bindIntentCaptor.capture(),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
Intent bindIntent = bindIntentCaptor.getValue();
assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
@@ -475,7 +491,7 @@
.thenReturn(DEF_PKG);
when(mMockContext.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT))).thenReturn(true);
+ eq(mUserHandle))).thenReturn(true);
when(mTimeoutsAdapter.getEmergencyCallbackWindowMillis(any(ContentResolver.class)))
.thenReturn(300_000L);
@@ -503,7 +519,7 @@
bindIntentCaptor.capture(),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
Intent bindIntent = bindIntentCaptor.getValue();
assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
@@ -552,7 +568,7 @@
ArgumentCaptor.forClass(ServiceConnection.class);
when(mMockContext.bindServiceAsUser(any(Intent.class), serviceConnectionCaptor.capture(),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT))).thenReturn(true);
+ eq(mUserHandle))).thenReturn(true);
when(mTimeoutsAdapter.getEmergencyCallbackWindowMillis(any(ContentResolver.class)))
.thenReturn(300_000L);
@@ -580,7 +596,7 @@
bindIntentCaptor.capture(),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
Intent bindIntent = bindIntentCaptor.getValue();
assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
@@ -609,7 +625,7 @@
bindIntentCaptor.capture(),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
// Verify we were re-granted the runtime permission.
verify(mMockPackageManager, times(2)).grantRuntimePermission(eq(SYS_PKG),
@@ -663,7 +679,7 @@
bindIntentCaptor.capture(),
serviceConnectionCaptor.capture(),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
Intent bindIntent = bindIntentCaptor.getValue();
assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
@@ -695,7 +711,7 @@
bindIntentCaptor2.capture(),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
bindIntent = bindIntentCaptor2.getValue();
assertEquals(SYS_PKG, bindIntent.getComponent().getPackageName());
@@ -710,6 +726,7 @@
when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
when(mMockCall.isIncoming()).thenReturn(false);
when(mMockCall.isExternalCall()).thenReturn(false);
+ when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
when(mMockCall.getAnalytics()).thenReturn(mCallInfo);
when(mMockContext.bindServiceAsUser(
@@ -741,8 +758,9 @@
// verify(mockInCallService).setInCallAdapter(any(IInCallAdapter.class));
serviceConnection.onNullBinding(defDialerComponentName);
- verify(mNotificationManager).notify(eq(NOTIFICATION_TAG),
- eq(IN_CALL_SERVICE_NOTIFICATION_ID), any(Notification.class));
+ verify(mNotificationManager).notifyAsUser(eq(NOTIFICATION_TAG),
+ eq(IN_CALL_SERVICE_NOTIFICATION_ID), any(Notification.class),
+ eq(mUserHandle));
verify(mCallInfo).addInCallService(eq(defDialerComponentName.flattenToShortString()),
anyInt(), anyLong(), eq(true));
@@ -751,10 +769,50 @@
bindIntentCaptor2.capture(),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
assertEquals(sysDialerComponentName, bindIntentCaptor2.getValue().getComponent());
}
+ @Test
+ public void testBindToService_CarModeUI_Crash() throws Exception {
+ setupMocks(false /* isExternalCall */);
+ setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
+
+ // Enable car mode
+ when(mMockSystemStateHelper.isCarModeOrProjectionActive()).thenReturn(true);
+ mInCallController.handleCarModeChange(UiModeManager.DEFAULT_PRIORITY, CAR_PKG, true);
+
+ // Now bind; we should only bind to one app.
+ mInCallController.bindToServices(mMockCall);
+
+ // Bind InCallServices
+ ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
+ ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
+ ArgumentCaptor.forClass(ServiceConnection.class);
+ verify(mMockContext, times(1)).bindServiceAsUser(
+ bindIntentCaptor.capture(),
+ serviceConnectionCaptor.capture(),
+ eq(serviceBindingFlags),
+ eq(mUserHandle));
+
+ // Verify bind car mode ui
+ assertEquals(1, bindIntentCaptor.getAllValues().size());
+ verifyBinding(bindIntentCaptor, 0, CAR_PKG, CAR_CLASS);
+
+ // Emulate a crash in the CarModeUI
+ ServiceConnection serviceConnection = serviceConnectionCaptor.getValue();
+ serviceConnection.onServiceDisconnected(bindIntentCaptor.getValue().getComponent());
+
+ ArgumentCaptor<Intent> bindIntentCaptor2 = ArgumentCaptor.forClass(Intent.class);
+ verify(mMockContext, times(2)).bindServiceAsUser(
+ bindIntentCaptor2.capture(),
+ any(ServiceConnection.class),
+ eq(serviceBindingFlags),
+ eq(mUserHandle));
+
+ verifyBinding(bindIntentCaptor2, 1, CAR_PKG, CAR_CLASS);
+ }
+
/**
* Ensures that the {@link InCallController} will bind to an {@link InCallService} which
* supports external calls.
@@ -785,7 +843,7 @@
bindIntentCaptor.capture(),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
Intent bindIntent = bindIntentCaptor.getValue();
assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
@@ -805,6 +863,7 @@
when(mMockCallsManager.isInEmergencyCall()).thenReturn(false);
when(mMockCall.isIncoming()).thenReturn(true);
when(mMockCall.isExternalCall()).thenReturn(false);
+ when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID)).thenReturn(DEF_PKG);
when(mMockContext.bindServiceAsUser(nullable(Intent.class),
nullable(ServiceConnection.class), anyInt(), nullable(UserHandle.class)))
@@ -823,7 +882,7 @@
bindIntentCaptor.capture(),
serviceConnectionCaptor.capture(),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
// Pretend that the call has gone away.
when(mMockCallsManager.getCalls()).thenReturn(Collections.emptyList());
@@ -871,7 +930,7 @@
bindIntentCaptor.capture(),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
// Verify bind car mode ui
assertEquals(1, bindIntentCaptor.getAllValues().size());
verifyBinding(bindIntentCaptor, 0, CAR_PKG, CAR_CLASS);
@@ -899,7 +958,7 @@
bindIntentCaptor.capture(),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
// Verify bind to default package, instead of the invalid car mode ui.
assertEquals(1, bindIntentCaptor.getAllValues().size());
verifyBinding(bindIntentCaptor, 0, DEF_PKG, DEF_CLASS);
@@ -942,7 +1001,7 @@
bindIntentCaptor.capture(),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
// Verify bind
assertEquals(2, bindIntentCaptor.getAllValues().size());
@@ -986,7 +1045,7 @@
bindIntentCaptor.capture(),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
// Verify bind
assertEquals(1, bindIntentCaptor.getAllValues().size());
@@ -995,8 +1054,10 @@
verifyBinding(bindIntentCaptor, 0, NONUI_PKG, NONUI_CLASS);
// Verify notification is not sent by NotificationManager
- verify(mNotificationManager, times(0)).notify(eq(InCallController.NOTIFICATION_TAG),
- eq(InCallController.IN_CALL_SERVICE_NOTIFICATION_ID), any());
+ verify(mNotificationManager, times(0)).notifyAsUser(
+ eq(InCallController.NOTIFICATION_TAG),
+ eq(InCallController.IN_CALL_SERVICE_NOTIFICATION_ID), any(),
+ eq(mUserHandle));
}
@MediumTest
@@ -1019,7 +1080,7 @@
bindIntentCaptor.capture(),
serviceConnectionCaptor.capture(),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
assertEquals(1, bindIntentCaptor.getAllValues().size());
verifyBinding(bindIntentCaptor, 0, DEF_PKG, DEF_CLASS);
@@ -1057,7 +1118,7 @@
bindIntentCaptor.capture(),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
}
/**
@@ -1088,7 +1149,7 @@
bindIntentCaptor.capture(),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
// Verify bind car mode ui
assertEquals(4, bindIntentCaptor.getAllValues().size());
@@ -1125,6 +1186,7 @@
when(mMockCallsManager.isInEmergencyCall()).thenReturn(false);
when(mMockCall.isIncoming()).thenReturn(false);
when(mMockCall.isExternalCall()).thenReturn(false);
+ when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID)).thenReturn(DEF_PKG);
when(mMockContext.bindServiceAsUser(nullable(Intent.class),
nullable(ServiceConnection.class), anyInt(), nullable(UserHandle.class)))
@@ -1145,7 +1207,7 @@
bindIntentCaptor.capture(),
serviceConnectionCaptor.capture(),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
CompletableFuture<Boolean> bindTimeout = mInCallController.getBindingFuture();
@@ -1213,7 +1275,7 @@
any(Intent.class),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
// Now switch to car mode.
// Enable car mode and enter car mode at default priority.
@@ -1225,7 +1287,7 @@
bindIntentCaptor.capture(),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
// Verify bind car mode ui
assertEquals(1, bindIntentCaptor.getAllValues().size());
verifyBinding(bindIntentCaptor, 0, CAR_PKG, CAR_CLASS);
@@ -1251,7 +1313,7 @@
any(Intent.class),
any(ServiceConnection.class),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
// Now switch to car mode.
// Enable car mode and enter car mode at default priority.
@@ -1268,7 +1330,7 @@
any(Intent.class),
serviceConnectionCaptor.capture(),
eq(serviceBindingFlags),
- eq(UserHandle.CURRENT));
+ eq(mUserHandle));
ServiceConnection serviceConnection = serviceConnectionCaptor.getValue();
ComponentName defDialerComponentName = new ComponentName(DEF_PKG, DEF_CLASS);
@@ -1284,6 +1346,59 @@
verify(mockInCallService, never()).addCall(any(ParcelableCall.class));
}
+ @Test
+ public void testSanitizeDndExtraFromParcelableCall() throws Exception {
+ setupMocks(false /* isExternalCall */);
+ setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
+ when(mMockPackageManager.checkPermission(
+ matches(Manifest.permission.READ_CONTACTS),
+ matches(DEF_PKG))).thenReturn(PackageManager.PERMISSION_DENIED);
+
+ when(mMockCall.getExtras()).thenReturn(null);
+ ParcelableCall parcelableCallNullExtras = Mockito.spy(
+ ParcelableCallUtils.toParcelableCall(mMockCall,
+ false /* includevideoProvider */,
+ null /* phoneAccountRegistrar */,
+ false /* supportsExternalCalls */,
+ false /* includeRttCall */,
+ false /* isForSystemDialer */));
+
+ when(parcelableCallNullExtras.getExtras()).thenReturn(null);
+ assertNull(parcelableCallNullExtras.getExtras());
+ when(mInCallServiceInfo.getComponentName())
+ .thenReturn(new ComponentName(DEF_PKG, DEF_CLASS));
+ // ensure sanitizeParcelableCallForService does not hit a NPE when Null extras are provided
+ mInCallController.sanitizeParcelableCallForService(mInCallServiceInfo,
+ parcelableCallNullExtras);
+
+
+ Bundle extras = new Bundle();
+ extras.putBoolean(android.telecom.Call.EXTRA_IS_SUPPRESSED_BY_DO_NOT_DISTURB, true);
+ when(mMockCall.getExtras()).thenReturn(extras);
+
+ ParcelableCall parcelableCallWithExtras = ParcelableCallUtils.toParcelableCall(mMockCall,
+ false /* includevideoProvider */,
+ null /* phoneAccountRegistrar */,
+ false /* supportsExternalCalls */,
+ false /* includeRttCall */,
+ false /* isForSystemDialer */);
+
+ // ensure sanitizeParcelableCallForService sanitizes the
+ // EXTRA_IS_SUPPRESSED_BY_DO_NOT_DISTURB from a ParcelableCall
+ // w/o Manifest.permission.READ_CONTACTS
+ ParcelableCall sanitizedCall =
+ mInCallController.sanitizeParcelableCallForService(mInCallServiceInfo,
+ parcelableCallWithExtras);
+
+ // sanitized call should not have the extra
+ assertFalse(sanitizedCall.getExtras().containsKey(
+ android.telecom.Call.EXTRA_IS_SUPPRESSED_BY_DO_NOT_DISTURB));
+
+ // root ParcelableCall should still have the extra
+ assertTrue(parcelableCallWithExtras.getExtras().containsKey(
+ android.telecom.Call.EXTRA_IS_SUPPRESSED_BY_DO_NOT_DISTURB));
+ }
+
private void setupMocks(boolean isExternalCall) {
setupMocks(isExternalCall, false /* isSelfManagedCall */);
}
@@ -1296,7 +1411,7 @@
when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID)).thenReturn(DEF_PKG);
when(mMockContext.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class),
- anyInt(), eq(UserHandle.CURRENT))).thenReturn(true);
+ anyInt(), any(UserHandle.class))).thenReturn(true);
when(mMockCall.isExternalCall()).thenReturn(isExternalCall);
when(mMockCall.isSelfManaged()).thenReturn(isSelfManagedCall);
when(mMockCall.visibleToInCallService()).thenReturn(isSelfManagedCall);
@@ -1487,7 +1602,7 @@
return resolveInfo;
}
}).when(mMockPackageManager).queryIntentServicesAsUser(
- any(Intent.class), anyInt(), eq(CURRENT_USER_ID));
+ any(Intent.class), anyInt(), anyInt());
if (useDefaultDialer) {
when(mMockPackageManager
diff --git a/tests/src/com/android/server/telecom/tests/InCallTonePlayerTest.java b/tests/src/com/android/server/telecom/tests/InCallTonePlayerTest.java
index eadda0d..f11afc1 100644
--- a/tests/src/com/android/server/telecom/tests/InCallTonePlayerTest.java
+++ b/tests/src/com/android/server/telecom/tests/InCallTonePlayerTest.java
@@ -140,13 +140,16 @@
@SmallTest
@Test
- public void testNoEndCallToneInSilence() {
+ public void testEndCallTonePlaysWhenRingIsSilent() {
when(mAudioManagerAdapter.isVolumeOverZero()).thenReturn(false);
- assertFalse(mInCallTonePlayer.startTone());
+ assertTrue(mInCallTonePlayer.startTone());
+ // Verify we did play a tone.
+ verify(mMediaPlayerFactory, timeout(TEST_TIMEOUT)).get(anyInt(), any());
+ verify(mCallAudioManager).setIsTonePlaying(eq(true));
- // Verify we didn't play a tone.
- verify(mCallAudioManager, never()).setIsTonePlaying(eq(true));
- verify(mMediaPlayerFactory, never()).get(anyInt(), any());
+ mInCallTonePlayer.stopTone();
+ // Timeouts due to threads!
+ verify(mCallAudioManager, timeout(TEST_TIMEOUT)).setIsTonePlaying(eq(false));
}
@SmallTest
diff --git a/tests/src/com/android/server/telecom/tests/IncomingCallNotifierTest.java b/tests/src/com/android/server/telecom/tests/IncomingCallNotifierTest.java
index a871b73..a38de94 100644
--- a/tests/src/com/android/server/telecom/tests/IncomingCallNotifierTest.java
+++ b/tests/src/com/android/server/telecom/tests/IncomingCallNotifierTest.java
@@ -17,9 +17,12 @@
package com.android.server.telecom.tests;
import android.app.NotificationManager;
+import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Build;
+import android.os.UserHandle;
+import android.telecom.PhoneAccountHandle;
import android.telecom.VideoProfile;
import android.test.suitebuilder.annotation.SmallTest;
@@ -72,6 +75,8 @@
when(mAudioCall.getVideoState()).thenReturn(VideoProfile.STATE_AUDIO_ONLY);
when(mAudioCall.getTargetPhoneAccountLabel()).thenReturn("Bar");
+ when(mAudioCall.getUserHandleFromTargetPhoneAccount()).
+ thenReturn(UserHandle.CURRENT);
when(mVideoCall.getVideoState()).thenReturn(VideoProfile.STATE_BIDIRECTIONAL);
when(mVideoCall.getTargetPhoneAccountLabel()).thenReturn("Bar");
when(mRingingCall.isSelfManaged()).thenReturn(true);
@@ -79,6 +84,8 @@
when(mRingingCall.getState()).thenReturn(CallState.RINGING);
when(mRingingCall.getVideoState()).thenReturn(VideoProfile.STATE_AUDIO_ONLY);
when(mRingingCall.getTargetPhoneAccountLabel()).thenReturn("Foo");
+ when(mRingingCall.getUserHandleFromTargetPhoneAccount()).
+ thenReturn(UserHandle.CURRENT);
when(mRingingCall.getHandoverState()).thenReturn(HandoverState.HANDOVER_NONE);
}
@@ -95,8 +102,10 @@
@Test
public void testSingleCall() {
mIncomingCallNotifier.onCallAdded(mAudioCall);
- verify(mNotificationManager, never()).notify(eq(IncomingCallNotifier.NOTIFICATION_TAG),
- eq(IncomingCallNotifier.NOTIFICATION_INCOMING_CALL), any());
+ verify(mNotificationManager, never()).notifyAsUser(
+ eq(IncomingCallNotifier.NOTIFICATION_TAG),
+ eq(IncomingCallNotifier.NOTIFICATION_INCOMING_CALL), any(),
+ eq(UserHandle.CURRENT));
}
/**
@@ -107,8 +116,10 @@
public void testIncomingDuringOngoingCall() {
when(mCallsManagerProxy.hasUnholdableCallsForOtherConnectionService(any())).thenReturn(false);
mIncomingCallNotifier.onCallAdded(mRingingCall);
- verify(mNotificationManager, never()).notify(eq(IncomingCallNotifier.NOTIFICATION_TAG),
- eq(IncomingCallNotifier.NOTIFICATION_INCOMING_CALL), any());
+ verify(mNotificationManager, never()).notifyAsUser(
+ eq(IncomingCallNotifier.NOTIFICATION_TAG),
+ eq(IncomingCallNotifier.NOTIFICATION_INCOMING_CALL), any(),
+ eq(UserHandle.CURRENT));
}
/**
@@ -123,8 +134,10 @@
mIncomingCallNotifier.onCallAdded(mAudioCall);
mIncomingCallNotifier.onCallAdded(mRingingCall);
- verify(mNotificationManager, never()).notify(eq(IncomingCallNotifier.NOTIFICATION_TAG),
- eq(IncomingCallNotifier.NOTIFICATION_INCOMING_CALL), any());;
+ verify(mNotificationManager, never()).notifyAsUser(
+ eq(IncomingCallNotifier.NOTIFICATION_TAG),
+ eq(IncomingCallNotifier.NOTIFICATION_INCOMING_CALL), any(),
+ eq(UserHandle.CURRENT));
}
/**
@@ -139,11 +152,13 @@
mIncomingCallNotifier.onCallAdded(mAudioCall);
mIncomingCallNotifier.onCallAdded(mRingingCall);
- verify(mNotificationManager).notify(eq(IncomingCallNotifier.NOTIFICATION_TAG),
- eq(IncomingCallNotifier.NOTIFICATION_INCOMING_CALL), any());
+ verify(mNotificationManager).notifyAsUser(
+ eq(IncomingCallNotifier.NOTIFICATION_TAG),
+ eq(IncomingCallNotifier.NOTIFICATION_INCOMING_CALL), any(),
+ eq(UserHandle.CURRENT));
mIncomingCallNotifier.onCallRemoved(mRingingCall);
- verify(mNotificationManager).cancel(eq(IncomingCallNotifier.NOTIFICATION_TAG),
- eq(IncomingCallNotifier.NOTIFICATION_INCOMING_CALL));
+ verify(mNotificationManager).cancelAsUser(eq(IncomingCallNotifier.NOTIFICATION_TAG),
+ eq(IncomingCallNotifier.NOTIFICATION_INCOMING_CALL), eq(UserHandle.CURRENT));
}
/**
@@ -161,8 +176,10 @@
mIncomingCallNotifier.onCallAdded(mRingingCall);
// Incoming call is in the middle of a handover, don't expect to be notified.
- verify(mNotificationManager, never()).notify(eq(IncomingCallNotifier.NOTIFICATION_TAG),
- eq(IncomingCallNotifier.NOTIFICATION_INCOMING_CALL), any());;
+ verify(mNotificationManager, never()).notifyAsUser(
+ eq(IncomingCallNotifier.NOTIFICATION_TAG),
+ eq(IncomingCallNotifier.NOTIFICATION_INCOMING_CALL), any(),
+ eq(UserHandle.CURRENT));
}
/**
@@ -180,7 +197,9 @@
mIncomingCallNotifier.onCallAdded(mRingingCall);
// Incoming call is done a handover, don't expect to be notified.
- verify(mNotificationManager, never()).notify(eq(IncomingCallNotifier.NOTIFICATION_TAG),
- eq(IncomingCallNotifier.NOTIFICATION_INCOMING_CALL), any());;
+ verify(mNotificationManager, never()).notifyAsUser(
+ eq(IncomingCallNotifier.NOTIFICATION_TAG),
+ eq(IncomingCallNotifier.NOTIFICATION_INCOMING_CALL), any(),
+ eq(UserHandle.CURRENT));
}
}
diff --git a/tests/src/com/android/server/telecom/tests/MissedInformationTest.java b/tests/src/com/android/server/telecom/tests/MissedInformationTest.java
index f2f0cd8..f28a781 100644
--- a/tests/src/com/android/server/telecom/tests/MissedInformationTest.java
+++ b/tests/src/com/android/server/telecom/tests/MissedInformationTest.java
@@ -147,6 +147,8 @@
public void testEmergencyCallPlacing() throws Exception {
Analytics.dumpToParcelableAnalytics();
setUpEmergencyCall();
+ when(mEmergencyCall.getUserHandleFromTargetPhoneAccount()).
+ thenReturn(mPhoneAccountA0.getAccountHandle().getUserHandle());
mCallsManager.addCall(mEmergencyCall);
assertTrue(mCallsManager.isInEmergencyCall());
@@ -354,6 +356,8 @@
doReturn(mNotificationManager).when(mSpyContext)
.getSystemService(Context.NOTIFICATION_SERVICE);
doReturn(false).when(mNotificationManager).matchesCallFilter(any(Bundle.class));
+ mCallsManager.getRinger().setNotificationManager(mNotificationManager);
+
CallFilteringResult result = new CallFilteringResult.Builder()
.setShouldAllowCall(true)
.build();
diff --git a/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java b/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
index e6c6bac..169aeb2 100644
--- a/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
+++ b/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
@@ -214,12 +214,25 @@
verifyNoCallPlaced();
}
+ @Test
+ public void testNoCallsPlacedWithContentUri() {
+ Uri handle = Uri.parse("content://com.android.contacts/data/1");
+ Intent intent = new Intent(Intent.ACTION_CALL, handle);
+
+ int result = processIntent(intent, true).disconnectCause;
+
+ assertEquals(DisconnectCause.NO_PHONE_NUMBER_SUPPLIED, result);
+ verify(mContext, never()).getContentResolver();
+ verifyNoBroadcastSent();
+ verifyNoCallPlaced();
+ }
+
@SmallTest
@Test
public void testEmergencyCallWithNonDefaultDialer() {
Uri handle = Uri.parse("tel:6505551911");
doReturn(true).when(mComponentContextFixture.getTelephonyManager())
- .isPotentialEmergencyNumber(eq(handle.getSchemeSpecificPart()));
+ .isEmergencyNumber(eq(handle.getSchemeSpecificPart()));
Intent intent = new Intent(Intent.ACTION_CALL, handle);
String ui_package_string = "sample_string_1";
@@ -290,7 +303,7 @@
public void testActionEmergencyWithNonEmergencyNumber() {
Uri handle = Uri.parse("tel:6505551911");
doReturn(false).when(mComponentContextFixture.getTelephonyManager())
- .isPotentialEmergencyNumber(eq(handle.getSchemeSpecificPart()));
+ .isEmergencyNumber(eq(handle.getSchemeSpecificPart()));
Intent intent = new Intent(Intent.ACTION_CALL_EMERGENCY, handle);
int result = processIntent(intent, true).disconnectCause;
@@ -304,7 +317,7 @@
int videoState = VideoProfile.STATE_BIDIRECTIONAL;
boolean isSpeakerphoneOn = true;
doReturn(true).when(mComponentContextFixture.getTelephonyManager())
- .isPotentialEmergencyNumber(eq(handle.getSchemeSpecificPart()));
+ .isEmergencyNumber(eq(handle.getSchemeSpecificPart()));
intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, isSpeakerphoneOn);
intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState);
@@ -426,7 +439,7 @@
result.receiver.setResultData(newEmergencyNumber);
doReturn(true).when(mComponentContextFixture.getTelephonyManager())
- .isPotentialEmergencyNumber(eq(newEmergencyNumber));
+ .isEmergencyNumber(eq(newEmergencyNumber));
result.receiver.onReceive(mContext, result.intent);
verify(mCall).disconnect(eq(0L));
}
diff --git a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
index ffa08e2..26f0f6d 100644
--- a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
+++ b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
@@ -99,6 +99,7 @@
private final String PACKAGE_1 = "PACKAGE_1";
private final String PACKAGE_2 = "PACKAGE_2";
private final String COMPONENT_NAME = "com.android.server.telecom.tests.MockConnectionService";
+ private final UserHandle USER_HANDLE_10 = new UserHandle(10);
private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };
private PhoneAccountRegistrar mRegistrar;
@Mock private SubscriptionManager mSubscriptionManager;
@@ -163,7 +164,7 @@
testBundle.putString("EXTRA_STR1", "Hello");
testBundle.putString("EXTRA_STR2", "There");
- PhoneAccount input = makeQuickAccountBuilder("id0", 0)
+ PhoneAccount input = makeQuickAccountBuilder("id0", 0, null)
.addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
.addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
.setExtras(testBundle)
@@ -271,7 +272,7 @@
// Put in something valid so the bundle exists.
testBundle.putString("EXTRA_OK", "OK");
- PhoneAccount input = makeQuickAccountBuilder("id0", 0)
+ PhoneAccount input = makeQuickAccountBuilder("id0", 0, null)
.addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
.addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
.setExtras(testBundle)
@@ -309,24 +310,33 @@
mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
Mockito.mock(IConnectionService.class));
- registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++)
+ registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++, null)
.setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER
| PhoneAccount.CAPABILITY_CALL_PROVIDER)
.build());
- registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++)
+ registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++, null)
.setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER
| PhoneAccount.CAPABILITY_CALL_PROVIDER)
.build());
- registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++)
+ registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++, null)
.setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER
| PhoneAccount.CAPABILITY_CALL_PROVIDER)
.build());
- registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++)
+ registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++, null)
+ .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
+ .build());
+ registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++, USER_HANDLE_10)
+ .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER
+ | PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .build());
+ registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++, USER_HANDLE_10)
.setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
.build());
- assertEquals(4, mRegistrar.getAllPhoneAccountsOfCurrentUser().size());
- assertEquals(3, mRegistrar.getCallCapablePhoneAccountsOfCurrentUser(null, false).size());
+ assertEquals(6, mRegistrar.
+ getAllPhoneAccounts(null, true).size());
+ assertEquals(4, mRegistrar.getCallCapablePhoneAccounts(null, false,
+ null, true).size());
assertEquals(null, mRegistrar.getSimCallManagerOfCurrentUser());
assertEquals(null, mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
PhoneAccount.SCHEME_TEL));
@@ -727,7 +737,7 @@
registerAndEnableAccount(nonSimAccount);
registerAndEnableAccount(simAccount);
- List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle());
+ List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle(), false);
assertTrue(accounts.get(0).getLabel().toString().equals("2"));
assertTrue(accounts.get(1).getLabel().toString().equals("1"));
}
@@ -770,7 +780,7 @@
registerAndEnableAccount(account2);
registerAndEnableAccount(account1);
- List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle());
+ List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle(), false);
assertTrue(accounts.get(0).getLabel().toString().equals("c"));
assertTrue(accounts.get(1).getLabel().toString().equals("b"));
assertTrue(accounts.get(2).getLabel().toString().equals("a"));
@@ -808,7 +818,7 @@
registerAndEnableAccount(account2);
registerAndEnableAccount(account3);
- List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle());
+ List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle(), false);
assertTrue(accounts.get(0).getLabel().toString().equals("a"));
assertTrue(accounts.get(1).getLabel().toString().equals("b"));
assertTrue(accounts.get(2).getLabel().toString().equals("c"));
@@ -886,7 +896,7 @@
registerAndEnableAccount(account5);
registerAndEnableAccount(account6);
- List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle());
+ List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle(), false);
// Sim accts ordered by sort order first
assertTrue(accounts.get(0).getLabel().toString().equals("z"));
assertTrue(accounts.get(1).getLabel().toString().equals("y"));
@@ -910,14 +920,14 @@
public void testGetByEnabledState() throws Exception {
mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
Mockito.mock(IConnectionService.class));
- mRegistrar.registerPhoneAccount(makeQuickAccountBuilder("id1", 1)
+ mRegistrar.registerPhoneAccount(makeQuickAccountBuilder("id1", 1, null)
.setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
.build());
assertEquals(0, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_TEL,
- false /* includeDisabled */, Process.myUserHandle()).size());
+ false /* includeDisabled */, Process.myUserHandle(), false).size());
assertEquals(1, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_TEL,
- true /* includeDisabled */, Process.myUserHandle()).size());
+ true /* includeDisabled */, Process.myUserHandle(), false).size());
}
/**
@@ -930,21 +940,21 @@
public void testGetByScheme() throws Exception {
mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
Mockito.mock(IConnectionService.class));
- registerAndEnableAccount(makeQuickAccountBuilder("id1", 1)
+ registerAndEnableAccount(makeQuickAccountBuilder("id1", 1, null)
.setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
.setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_SIP))
.build());
- registerAndEnableAccount(makeQuickAccountBuilder("id2", 2)
+ registerAndEnableAccount(makeQuickAccountBuilder("id2", 2, null)
.setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
.setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_TEL))
.build());
assertEquals(1, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_SIP,
- false /* includeDisabled */, Process.myUserHandle()).size());
+ false /* includeDisabled */, Process.myUserHandle(), false).size());
assertEquals(1, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_TEL,
- false /* includeDisabled */, Process.myUserHandle()).size());
+ false /* includeDisabled */, Process.myUserHandle(), false).size());
assertEquals(2, mRegistrar.getCallCapablePhoneAccounts(null, false /* includeDisabled */,
- Process.myUserHandle()).size());
+ Process.myUserHandle(), false).size());
}
/**
@@ -957,23 +967,24 @@
public void testGetByCapability() throws Exception {
mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
Mockito.mock(IConnectionService.class));
- registerAndEnableAccount(makeQuickAccountBuilder("id1", 1)
+ registerAndEnableAccount(makeQuickAccountBuilder("id1", 1, null)
.setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER
| PhoneAccount.CAPABILITY_VIDEO_CALLING)
.setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_SIP))
.build());
- registerAndEnableAccount(makeQuickAccountBuilder("id2", 2)
+ registerAndEnableAccount(makeQuickAccountBuilder("id2", 2, null)
.setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
.setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_SIP))
.build());
assertEquals(1, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_SIP,
- false /* includeDisabled */, Process.myUserHandle()).size(),
+ false /* includeDisabled */, Process.myUserHandle(), false).size(),
PhoneAccount.CAPABILITY_VIDEO_CALLING);
assertEquals(2, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_SIP,
- false /* includeDisabled */, Process.myUserHandle()).size(), 0 /* none extra */);
+ false /* includeDisabled */, Process.myUserHandle(), false)
+ .size(), 0 /* none extra */);
assertEquals(0, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_SIP,
- false /* includeDisabled */, Process.myUserHandle()).size(),
+ false /* includeDisabled */, Process.myUserHandle(), false).size(),
PhoneAccount.CAPABILITY_RTT);
}
@@ -1059,8 +1070,8 @@
registerAndEnableAccount(pa1);
registerAndEnableAccount(pa2);
- assertEquals(1, mRegistrar.getAllPhoneAccounts(users.get(0)).size());
- assertEquals(1, mRegistrar.getAllPhoneAccounts(users.get(1)).size());
+ assertEquals(1, mRegistrar.getAllPhoneAccounts(users.get(0), false).size());
+ assertEquals(1, mRegistrar.getAllPhoneAccounts(users.get(1), false).size());
// WHEN
@@ -1268,9 +1279,17 @@
return new PhoneAccountHandle(name, id, Process.myUserHandle());
}
- private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) {
+ private static PhoneAccountHandle makeQuickAccountHandleForUser(
+ String id, UserHandle userHandle) {
+ return new PhoneAccountHandle(makeQuickConnectionServiceComponentName(), id, userHandle);
+ }
+
+ private PhoneAccount.Builder makeQuickAccountBuilder(
+ String id, int idx, UserHandle userHandle) {
return new PhoneAccount.Builder(
- makeQuickAccountHandle(id),
+ userHandle == null
+ ? makeQuickAccountHandle(id)
+ : makeQuickAccountHandleForUser(id, userHandle),
"label" + idx);
}
@@ -1292,7 +1311,7 @@
}
private PhoneAccount makeQuickAccount(String id, int idx) {
- return makeQuickAccountBuilder(id, idx)
+ return makeQuickAccountBuilder(id, idx, null)
.setAddress(Uri.parse("http://foo.com/" + idx))
.setSubscriptionAddress(Uri.parse("tel:555-000" + idx))
.setCapabilities(idx)
@@ -1309,7 +1328,7 @@
*/
private PhoneAccount makeQuickSimAccount(int simId) {
PhoneAccount simAccount =
- makeQuickAccountBuilder("sim" + simId, simId)
+ makeQuickAccountBuilder("sim" + simId, simId, null)
.setCapabilities(
PhoneAccount.CAPABILITY_CALL_PROVIDER
| PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
diff --git a/tests/src/com/android/server/telecom/tests/RingerTest.java b/tests/src/com/android/server/telecom/tests/RingerTest.java
index 12420a8..16241b1 100644
--- a/tests/src/com/android/server/telecom/tests/RingerTest.java
+++ b/tests/src/com/android/server/telecom/tests/RingerTest.java
@@ -24,7 +24,6 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
@@ -35,6 +34,7 @@
import static org.mockito.Mockito.when;
import android.app.NotificationManager;
+import android.content.ComponentName;
import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
@@ -43,9 +43,11 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcel;
+import android.os.UserHandle;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.os.Vibrator;
+import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.test.suitebuilder.annotation.SmallTest;
@@ -66,6 +68,23 @@
import org.mockito.Mock;
import org.mockito.Spy;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
@@ -90,6 +109,11 @@
}
@Override
+ public long[] computeCreateWaveformOffOnTimingsOrNull() {
+ return null; // not needed
+ }
+
+ @Override
public void validate() {
// not needed
}
@@ -125,10 +149,14 @@
@Mock InCallTonePlayer mockTonePlayer;
@Mock Call mockCall1;
@Mock Call mockCall2;
+ @Mock NotificationManager mNotificationManager;
+
+ private static final PhoneAccountHandle PA_HANDLE =
+ new PhoneAccountHandle(new ComponentName("pa_pkg", "pa_cls"),
+ "pa_id");
Ringer mRingerUnderTest;
AudioManager mockAudioManager;
- CompletableFuture<Boolean> mFuture = new CompletableFuture<>();
CompletableFuture<Void> mRingCompletionFuture = new CompletableFuture<>();
@Override
@@ -143,6 +171,8 @@
when(mockPlayerFactory.createPlayer(anyInt())).thenReturn(mockTonePlayer);
mockAudioManager =
(AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ mNotificationManager = mContext.getSystemService(NotificationManager.class);
+
when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
when(mockSystemSettingsUtil.isHapticPlaybackSupported(any(Context.class))).thenReturn(true);
mockNotificationManager =
@@ -150,15 +180,15 @@
when(mockTonePlayer.startTone()).thenReturn(true);
when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true);
when(mockRingtoneFactory.hasHapticChannels(any(Ringtone.class))).thenReturn(false);
- when(mockRingtonePlayer.play(any(RingtoneFactory.class), any(Call.class),
- nullable(VolumeShaper.Configuration.class), anyBoolean(), anyBoolean()))
- .thenReturn(mFuture);
mRingerUnderTest = new Ringer(mockPlayerFactory, mContext, mockSystemSettingsUtil,
mockRingtonePlayer, mockRingtoneFactory, mockVibrator, spyVibrationEffectProxy,
- mockInCallController);
+ mockInCallController, mNotificationManager);
when(mockCall1.getState()).thenReturn(CallState.RINGING);
when(mockCall2.getState()).thenReturn(CallState.RINGING);
+ when(mockCall1.getUserHandleFromTargetPhoneAccount()).thenReturn(PA_HANDLE.getUserHandle());
+ when(mockCall2.getUserHandleFromTargetPhoneAccount()).thenReturn(PA_HANDLE.getUserHandle());
mRingerUnderTest.setBlockOnRingingFuture(mRingCompletionFuture);
+ mRingerUnderTest.setNotificationManager(mockNotificationManager);
}
@Override
@@ -171,13 +201,13 @@
@Test
public void testNoActionInTheaterMode() {
// Start call waiting to make sure that it doesn't stop when we start ringing
- mFuture.complete(false); // not using audio coupled haptics
mRingerUnderTest.startCallWaiting(mockCall1);
when(mockSystemSettingsUtil.isTheaterModeOn(any(Context.class))).thenReturn(true);
assertFalse(mRingerUnderTest.startRinging(mockCall2, false));
+ verify(mockRingtoneFactory, never())
+ .getRingtone(any(Call.class), nullable(VolumeShaper.Configuration.class), anyBoolean());
verify(mockTonePlayer, never()).stopTone();
- verify(mockRingtonePlayer, never()).play(any(RingtoneFactory.class), any(Call.class),
- nullable(VolumeShaper.Configuration.class), anyBoolean(), anyBoolean());
+ verify(mockRingtonePlayer, never()).play(any(Ringtone.class));
verify(mockVibrator, never())
.vibrate(any(VibrationEffect.class), any(VibrationAttributes.class));
}
@@ -185,7 +215,6 @@
@SmallTest
@Test
public void testNoActionWithExternalRinger() {
- mFuture.complete(false); // not using audio coupled haptics
Bundle externalRingerExtra = new Bundle();
externalRingerExtra.putBoolean(TelecomManager.EXTRA_CALL_HAS_IN_BAND_RINGTONE, true);
when(mockCall1.getIntentExtras()).thenReturn(externalRingerExtra);
@@ -193,9 +222,10 @@
// Start call waiting to make sure that it doesn't stop when we start ringing
mRingerUnderTest.startCallWaiting(mockCall1);
assertFalse(mRingerUnderTest.startRinging(mockCall2, false));
+ verify(mockRingtoneFactory, never())
+ .getRingtone(any(Call.class), nullable(VolumeShaper.Configuration.class), anyBoolean());
verify(mockTonePlayer, never()).stopTone();
- verify(mockRingtonePlayer, never()).play(any(RingtoneFactory.class), any(Call.class),
- nullable(VolumeShaper.Configuration.class), anyBoolean(), anyBoolean());
+ verify(mockRingtonePlayer, never()).play(any(Ringtone.class));
verify(mockVibrator, never())
.vibrate(any(VibrationEffect.class), any(VibrationAttributes.class));
}
@@ -203,15 +233,19 @@
@SmallTest
@Test
public void testNoActionWhenDialerRings() throws Exception {
- mFuture.complete(false); // not using audio coupled haptics
+ ensureRingtoneMocked();
+
// Start call waiting to make sure that it doesn't stop when we start ringing
mRingerUnderTest.startCallWaiting(mockCall1);
- when(mockInCallController.doesConnectedDialerSupportRinging()).thenReturn(true);
+ when(mockInCallController.doesConnectedDialerSupportRinging(
+ any(UserHandle.class))).thenReturn(true);
+ ensureRingerIsNotAudible();
assertFalse(mRingerUnderTest.startRinging(mockCall2, false));
+ verify(mockRingtoneFactory, never())
+ .getRingtone(any(Call.class), nullable(VolumeShaper.Configuration.class), anyBoolean());
mRingCompletionFuture.get();
verify(mockTonePlayer, never()).stopTone();
- verify(mockRingtonePlayer, never()).play(any(RingtoneFactory.class), any(Call.class),
- nullable(VolumeShaper.Configuration.class), anyBoolean(), anyBoolean());
+ verify(mockRingtonePlayer, never()).play(any(Ringtone.class));
verify(mockVibrator, never())
.vibrate(any(VibrationEffect.class), any(AudioAttributes.class));
}
@@ -219,16 +253,19 @@
@SmallTest
@Test
public void testAudioFocusStillAcquiredWhenDialerRings() throws Exception {
- mFuture.complete(false); // not using audio coupled haptics
+ ensureRingtoneMocked();
+
// Start call waiting to make sure that it doesn't stop when we start ringing
mRingerUnderTest.startCallWaiting(mockCall1);
- when(mockInCallController.doesConnectedDialerSupportRinging()).thenReturn(true);
+ when(mockInCallController.doesConnectedDialerSupportRinging(
+ any(UserHandle.class))).thenReturn(true);
ensureRingerIsAudible();
assertTrue(mRingerUnderTest.startRinging(mockCall2, false));
+ verify(mockRingtoneFactory, never())
+ .getRingtone(any(Call.class), nullable(VolumeShaper.Configuration.class), anyBoolean());
mRingCompletionFuture.get();
verify(mockTonePlayer, never()).stopTone();
- verify(mockRingtonePlayer, never()).play(any(RingtoneFactory.class), any(Call.class),
- nullable(VolumeShaper.Configuration.class), anyBoolean(), anyBoolean());
+ verify(mockRingtonePlayer, never()).play(any(Ringtone.class));
verify(mockVibrator, never())
.vibrate(any(VibrationEffect.class), any(VibrationAttributes.class));
}
@@ -236,15 +273,13 @@
@SmallTest
@Test
public void testNoActionWhenCallIsSelfManaged() {
- mFuture.complete(false); // not using audio coupled haptics
// Start call waiting to make sure that it doesn't stop when we start ringing
mRingerUnderTest.startCallWaiting(mockCall1);
when(mockCall2.isSelfManaged()).thenReturn(true);
// We do want to acquire audio focus when self-managed
assertTrue(mRingerUnderTest.startRinging(mockCall2, true));
verify(mockTonePlayer, never()).stopTone();
- verify(mockRingtonePlayer, never()).play(any(RingtoneFactory.class), any(Call.class),
- nullable(VolumeShaper.Configuration.class), anyBoolean(), anyBoolean());
+ verify(mockRingtonePlayer, never()).play(any(Ringtone.class));
verify(mockVibrator, never())
.vibrate(any(VibrationEffect.class), any(VibrationAttributes.class));
}
@@ -252,7 +287,6 @@
@SmallTest
@Test
public void testCallWaitingButNoRingForSpecificContacts() {
- mFuture.complete(false); // not using audio coupled haptics
when(mockNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(false);
// Start call waiting to make sure that it does stop when we start ringing
mRingerUnderTest.startCallWaiting(mockCall1);
@@ -260,8 +294,7 @@
assertFalse(mRingerUnderTest.startRinging(mockCall2, false));
verify(mockTonePlayer).stopTone();
- verify(mockRingtonePlayer, never()).play(any(RingtoneFactory.class), any(Call.class),
- nullable(VolumeShaper.Configuration.class), anyBoolean(), anyBoolean());
+ verify(mockRingtonePlayer, never()).play(any(Ringtone.class));
verify(mockVibrator, never())
.vibrate(any(VibrationEffect.class), any(VibrationAttributes.class));
}
@@ -269,16 +302,19 @@
@SmallTest
@Test
public void testNoVibrateDueToAudioCoupledHaptics() throws Exception {
+ Ringtone mockRingtone = ensureRingtoneMocked();
+
mRingerUnderTest.startCallWaiting(mockCall1);
ensureRingerIsAudible();
enableVibrationWhenRinging();
// Pretend we're using audio coupled haptics.
- mFuture.complete(true);
- assertTrue(mRingerUnderTest.startRinging(mockCall2, false));
+ setIsUsingHaptics(mockRingtone, true);
+ assertTrue(mRingerUnderTest.startRinging(mockCall1, false));
mRingCompletionFuture.get();
+ verify(mockRingtoneFactory, times(1))
+ .getRingtone(any(Call.class), nullable(VolumeShaper.Configuration.class), anyBoolean());
verify(mockTonePlayer).stopTone();
- verify(mockRingtonePlayer).play(any(RingtoneFactory.class), any(Call.class), isNull(),
- eq(true) /* isRingerAudible */, eq(true) /* isVibrationEnabled */);
+ verify(mockRingtonePlayer).play(any(Ringtone.class));
verify(mockVibrator, never()).vibrate(any(VibrationEffect.class),
any(VibrationAttributes.class));
}
@@ -286,17 +322,19 @@
@SmallTest
@Test
public void testVibrateButNoRingForNullRingtone() throws Exception {
+ when(mockRingtoneFactory.getRingtone(
+ any(Call.class), nullable(VolumeShaper.Configuration.class), anyBoolean()))
+ .thenReturn(null);
+
mRingerUnderTest.startCallWaiting(mockCall1);
- when(mockRingtoneFactory.getRingtone(any(Call.class))).thenReturn(null);
when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
- mFuture.complete(false); // not using audio coupled haptics
enableVibrationWhenRinging();
assertFalse(mRingerUnderTest.startRinging(mockCall2, false));
mRingCompletionFuture.get();
verify(mockTonePlayer).stopTone();
- // Try to play a silent haptics ringtone
- verify(mockRingtonePlayer).play(any(RingtoneFactory.class), any(Call.class), isNull(),
- eq(false) /* isRingerAudible */, eq(true) /* isVibrationEnabled */);
+ // Ringtone does not exist, make sure it does not try to play it
+ verify(mockRingtonePlayer, never()).play(any(Ringtone.class));
+
// Play default vibration when future completes with no audio coupled haptics
verify(mockVibrator).vibrate(eq(mRingerUnderTest.mDefaultVibrationEffect),
any(VibrationAttributes.class));
@@ -305,19 +343,23 @@
@SmallTest
@Test
public void testVibrateButNoRingForSilentRingtone() throws Exception {
+ Ringtone mockRingtone = ensureRingtoneMocked();
+
mRingerUnderTest.startCallWaiting(mockCall1);
- Ringtone mockRingtone = mock(Ringtone.class);
- when(mockRingtoneFactory.getRingtone(any(Call.class))).thenReturn(mockRingtone);
+ when(mockRingtoneFactory.getRingtone(any(Call.class), eq(null), anyBoolean()))
+ .thenReturn(mockRingtone);
when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
when(mockAudioManager.getStreamVolume(AudioManager.STREAM_RING)).thenReturn(0);
- mFuture.complete(false); // not using audio coupled haptics
enableVibrationWhenRinging();
assertFalse(mRingerUnderTest.startRinging(mockCall2, false));
mRingCompletionFuture.get();
verify(mockTonePlayer).stopTone();
// Try to play a silent haptics ringtone
- verify(mockRingtonePlayer).play(any(RingtoneFactory.class), any(Call.class), isNull(),
- eq(false) /* isRingerAudible */, eq(true) /* isVibrationEnabled */);
+ verify(mockRingtonePlayer).play(any(Ringtone.class));
+ verify(mockRingtoneFactory, times(1)).getHapticOnlyRingtone();
+ verify(mockRingtoneFactory, never())
+ .getRingtone(any(Call.class), nullable(VolumeShaper.Configuration.class), anyBoolean());
+
// Play default vibration when future completes with no audio coupled haptics
verify(mockVibrator).vibrate(eq(mRingerUnderTest.mDefaultVibrationEffect),
any(VibrationAttributes.class));
@@ -326,19 +368,21 @@
@SmallTest
@Test
public void testAudioCoupledHapticsForSilentRingtone() throws Exception {
+ Ringtone mockRingtone = ensureRingtoneMocked();
+
mRingerUnderTest.startCallWaiting(mockCall1);
- Ringtone mockRingtone = mock(Ringtone.class);
- when(mockRingtoneFactory.getRingtone(any(Call.class))).thenReturn(mockRingtone);
when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
when(mockAudioManager.getStreamVolume(AudioManager.STREAM_RING)).thenReturn(0);
- mFuture.complete(true); // using audio coupled haptics
+ setIsUsingHaptics(mockRingtone, true);
enableVibrationWhenRinging();
assertFalse(mRingerUnderTest.startRinging(mockCall2, false));
+ verify(mockRingtoneFactory, times(1)).getHapticOnlyRingtone();
+ verify(mockRingtoneFactory, never())
+ .getRingtone(any(Call.class), nullable(VolumeShaper.Configuration.class), anyBoolean());
mRingCompletionFuture.get();
verify(mockTonePlayer).stopTone();
// Try to play a silent haptics ringtone
- verify(mockRingtonePlayer).play(any(RingtoneFactory.class), any(Call.class), isNull(),
- eq(false) /* isRingerAudible */, eq(true) /* isVibrationEnabled */);
+ verify(mockRingtonePlayer).play(any(Ringtone.class));
// Skip vibration for audio coupled haptics
verify(mockVibrator, never()).vibrate(any(VibrationEffect.class),
any(VibrationAttributes.class));
@@ -346,44 +390,20 @@
@SmallTest
@Test
- public void testStopRingingBeforeHapticsLookupComplete() throws Exception {
- enableVibrationWhenRinging();
- Ringtone mockRingtone = mock(Ringtone.class);
- when(mockRingtoneFactory.getRingtone(nullable(Call.class))).thenReturn(mockRingtone);
- when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
-
- mRingerUnderTest.startRinging(mockCall1, false);
- // Make sure we haven't started the vibrator yet, but have started ringing.
- verify(mockRingtonePlayer).play(nullable(RingtoneFactory.class), nullable(Call.class),
- nullable(VolumeShaper.Configuration.class), anyBoolean(), anyBoolean());
- verify(mockVibrator, never()).vibrate(nullable(VibrationEffect.class),
- nullable(VibrationAttributes.class));
- // Simulate something stopping the ringer
- mRingerUnderTest.stopRinging();
- verify(mockRingtonePlayer).stop();
- verify(mockVibrator, never()).cancel();
- // Simulate the haptics computation finishing
- mFuture.complete(false);
- // Then make sure that we don't actually start vibrating.
- verify(mockVibrator, never()).vibrate(nullable(VibrationEffect.class),
- nullable(VibrationAttributes.class));
- }
-
- @SmallTest
- @Test
public void testCustomVibrationForRingtone() throws Exception {
mRingerUnderTest.startCallWaiting(mockCall1);
Ringtone mockRingtone = mock(Ringtone.class);
when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
- when(mockRingtoneFactory.getRingtone(any(Call.class))).thenReturn(mockRingtone);
+ when(mockRingtoneFactory.getRingtone(any(Call.class), eq(null), anyBoolean()))
+ .thenReturn(mockRingtone);
when(mockRingtone.getUri()).thenReturn(FAKE_RINGTONE_URI);
- mFuture.complete(false); // not using audio coupled haptics
enableVibrationWhenRinging();
assertTrue(mRingerUnderTest.startRinging(mockCall2, false));
mRingCompletionFuture.get();
verify(mockTonePlayer).stopTone();
- verify(mockRingtonePlayer).play(any(RingtoneFactory.class), any(Call.class), eq(null),
- eq(true) /* isRingerAudible */, eq(true) /* isVibrationEnabled */);
+ verify(mockRingtonePlayer).play(any(Ringtone.class));
+ verify(mockRingtoneFactory, times(1))
+ .getRingtone(any(Call.class), nullable(VolumeShaper.Configuration.class), anyBoolean());
verify(mockVibrator).vibrate(eq(spyVibrationEffectProxy.get(FAKE_RINGTONE_URI, mContext)),
any(VibrationAttributes.class));
}
@@ -391,15 +411,17 @@
@SmallTest
@Test
public void testRingAndNoVibrate() throws Exception {
+ ensureRingtoneMocked();
+
mRingerUnderTest.startCallWaiting(mockCall1);
ensureRingerIsAudible();
- mFuture.complete(false); // not using audio coupled haptics
enableVibrationOnlyWhenNotRinging();
assertTrue(mRingerUnderTest.startRinging(mockCall2, false));
mRingCompletionFuture.get();
+ verify(mockRingtoneFactory, times(1))
+ .getRingtone(any(Call.class), nullable(VolumeShaper.Configuration.class), anyBoolean());
verify(mockTonePlayer).stopTone();
- verify(mockRingtonePlayer).play(any(RingtoneFactory.class), any(Call.class), eq(null),
- eq(true) /* isRingerAudible */, eq(false) /* isVibrationEnabled */);
+ verify(mockRingtonePlayer).play(any(Ringtone.class));
verify(mockVibrator, never())
.vibrate(any(VibrationEffect.class), any(VibrationAttributes.class));
}
@@ -407,34 +429,32 @@
@SmallTest
@Test
public void testRingWithRampingRinger() throws Exception {
+ ensureRingtoneMocked();
+
mRingerUnderTest.startCallWaiting(mockCall1);
ensureRingerIsAudible();
enableRampingRinger();
- mFuture.complete(false); // not using audio coupled haptics
enableVibrationWhenRinging();
assertTrue(mRingerUnderTest.startRinging(mockCall2, false));
+ verify(mockRingtoneFactory, times(1))
+ .getRingtone(any(Call.class), nullable(VolumeShaper.Configuration.class), anyBoolean());
mRingCompletionFuture.get();
verify(mockTonePlayer).stopTone();
- verify(mockRingtonePlayer).play(
- any(RingtoneFactory.class), any(Call.class), any(VolumeShaper.Configuration.class),
- eq(true) /* isRingerAudible */, eq(true) /* isVibrationEnabled */);
+ verify(mockRingtonePlayer).play(any(Ringtone.class));
}
@SmallTest
@Test
public void testSilentRingWithHfpStillAcquiresFocus1() throws Exception {
mRingerUnderTest.startCallWaiting(mockCall1);
- Ringtone mockRingtone = mock(Ringtone.class);
- when(mockRingtoneFactory.getRingtone(any(Call.class))).thenReturn(mockRingtone);
+ ensureRingtoneMocked();
when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
when(mockAudioManager.getStreamVolume(AudioManager.STREAM_RING)).thenReturn(0);
- mFuture.complete(false); // not using audio coupled haptics
enableVibrationOnlyWhenNotRinging();
assertTrue(mRingerUnderTest.startRinging(mockCall2, true));
mRingCompletionFuture.get();
verify(mockTonePlayer).stopTone();
- verify(mockRingtonePlayer, never()).play(any(RingtoneFactory.class), any(Call.class),
- nullable(VolumeShaper.Configuration.class), anyBoolean(), anyBoolean());
+ verify(mockRingtonePlayer, never()).play(any(Ringtone.class));
verify(mockVibrator, never())
.vibrate(any(VibrationEffect.class), any(VibrationAttributes.class));
}
@@ -443,16 +463,16 @@
@Test
public void testSilentRingWithHfpStillAcquiresFocus2() throws Exception {
mRingerUnderTest.startCallWaiting(mockCall1);
- when(mockRingtoneFactory.getRingtone(any(Call.class))).thenReturn(null);
+ when(mockRingtoneFactory.getRingtone(
+ any(Call.class), nullable(VolumeShaper.Configuration.class), anyBoolean()))
+ .thenReturn(null);
when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
when(mockAudioManager.getStreamVolume(AudioManager.STREAM_RING)).thenReturn(0);
- mFuture.complete(false); // not using audio coupled haptics
enableVibrationOnlyWhenNotRinging();
assertTrue(mRingerUnderTest.startRinging(mockCall2, true));
mRingCompletionFuture.get();
verify(mockTonePlayer).stopTone();
- verify(mockRingtonePlayer, never()).play(any(RingtoneFactory.class), any(Call.class),
- nullable(VolumeShaper.Configuration.class), anyBoolean(), anyBoolean());
+ verify(mockRingtonePlayer, never()).play(any(Ringtone.class));
verify(mockVibrator, never())
.vibrate(any(VibrationEffect.class), any(VibrationAttributes.class));
}
@@ -462,26 +482,77 @@
public void testRingAndVibrateForAllowedCallInDndMode() throws Exception {
mRingerUnderTest.startCallWaiting(mockCall1);
Ringtone mockRingtone = mock(Ringtone.class);
- when(mockRingtoneFactory.getRingtone(any(Call.class))).thenReturn(mockRingtone);
when(mockNotificationManager.getZenMode()).thenReturn(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+ when(mockRingtoneFactory.getRingtone(any(Call.class), eq(null), anyBoolean()))
+ .thenReturn(mockRingtone);
when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_SILENT);
when(mockAudioManager.getStreamVolume(AudioManager.STREAM_RING)).thenReturn(100);
- mFuture.complete(true); // using audio coupled haptics
enableVibrationWhenRinging();
assertTrue(mRingerUnderTest.startRinging(mockCall2, true));
+ verify(mockRingtoneFactory, times(1))
+ .getRingtone(any(Call.class), nullable(VolumeShaper.Configuration.class), anyBoolean());
mRingCompletionFuture.get();
verify(mockTonePlayer).stopTone();
- verify(mockRingtonePlayer).play(any(RingtoneFactory.class), any(Call.class), eq(null),
- eq(true) /* isRingerAudible */, eq(true) /* isVibrationEnabled */);
+ verify(mockRingtonePlayer).play(any(Ringtone.class));
+ }
+
+ private Ringtone ensureRingtoneMocked() {
+ Ringtone mockRingtone = mock(Ringtone.class);
+ when(mockRingtoneFactory.getRingtone(
+ any(Call.class), nullable(VolumeShaper.Configuration.class), anyBoolean()))
+ .thenReturn(mockRingtone);
+ when(mockRingtoneFactory.getHapticOnlyRingtone()).thenReturn(mockRingtone);
+ return mockRingtone;
+ }
+
+ /**
+ * assert {@link Ringer#shouldRingForContact(Call, Context) } sets the Call object with suppress
+ * caller
+ *
+ * @throws Exception; should not throw exception.
+ */
+ @Test
+ public void testShouldRingForContact_CallSuppressed() throws Exception {
+ // WHEN
+ when(mockCall1.wasDndCheckComputedForCall()).thenReturn(false);
+ when(mockCall1.getHandle()).thenReturn(Uri.parse(""));
+
+ when(mContext.getSystemService(NotificationManager.class)).thenReturn(mNotificationManager);
+ when(mNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(false);
+
+ // THEN
+ assertFalse(mRingerUnderTest.shouldRingForContact(mockCall1));
+ verify(mockCall1, atLeastOnce()).setCallIsSuppressedByDoNotDisturb(true);
+ }
+
+ /**
+ * assert {@link Ringer#shouldRingForContact(Call, Context) } sets the Call object with ring
+ * caller
+ *
+ * @throws Exception; should not throw exception.
+ */
+ @Test
+ public void testShouldRingForContact_CallShouldRing() throws Exception {
+ // WHEN
+ when(mockCall1.wasDndCheckComputedForCall()).thenReturn(false);
+ when(mockCall1.getHandle()).thenReturn(Uri.parse(""));
+ when(mNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true);
+
+ // THEN
+ assertTrue(mRingerUnderTest.shouldRingForContact(mockCall1));
+ verify(mockCall1, atLeastOnce()).setCallIsSuppressedByDoNotDisturb(false);
}
private void ensureRingerIsAudible() {
- Ringtone mockRingtone = mock(Ringtone.class);
- when(mockRingtoneFactory.getRingtone(any(Call.class))).thenReturn(mockRingtone);
when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
when(mockAudioManager.getStreamVolume(AudioManager.STREAM_RING)).thenReturn(100);
}
+ private void ensureRingerIsNotAudible() {
+ when(mockAudioManager.getRingerMode()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
+ when(mockAudioManager.getStreamVolume(AudioManager.STREAM_RING)).thenReturn(0);
+ }
+
private void enableVibrationWhenRinging() {
when(mockVibrator.hasVibrator()).thenReturn(true);
when(mockSystemSettingsUtil.isRingVibrationEnabled(any(Context.class))).thenReturn(true);
@@ -495,4 +566,12 @@
private void enableRampingRinger() {
when(mockSystemSettingsUtil.isRampingRingerEnabled(any(Context.class))).thenReturn(true);
}
+
+ private void setIsUsingHaptics(Ringtone mockRingtone, boolean useHaptics) {
+ when(mockSystemSettingsUtil.isHapticPlaybackSupported(any(Context.class)))
+ .thenReturn(useHaptics);
+ when(mockSystemSettingsUtil.isAudioCoupledVibrationForRampingRingerEnabled())
+ .thenReturn(useHaptics);
+ when(mockRingtone.hasHapticChannels()).thenReturn(useHaptics);
+ }
}
diff --git a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
index 9e64aec..a5aa936 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
@@ -102,6 +102,7 @@
@RunWith(JUnit4.class)
public class TelecomServiceImplTest extends TelecomTestCase {
+ private static final String CALLING_PACKAGE = TelecomServiceImplTest.class.getPackageName();
public static final String TEST_PACKAGE = "com.test";
public static final String PACKAGE_NAME = "test";
@@ -379,11 +380,11 @@
// Returns all phone accounts when getCallCapablePhoneAccounts is called.
when(mFakePhoneAccountRegistrar
.getCallCapablePhoneAccounts(nullable(String.class), eq(true),
- nullable(UserHandle.class))).thenReturn(fullPHList);
+ nullable(UserHandle.class), eq(true))).thenReturn(fullPHList);
// Returns only enabled phone accounts when getCallCapablePhoneAccounts is called.
when(mFakePhoneAccountRegistrar
.getCallCapablePhoneAccounts(nullable(String.class), eq(false),
- nullable(UserHandle.class))).thenReturn(smallPHList);
+ nullable(UserHandle.class), eq(true))).thenReturn(smallPHList);
makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_16, SIP_PA_HANDLE_17);
assertEquals(fullPHList,
@@ -410,7 +411,8 @@
}
assertNull(result);
verify(mFakePhoneAccountRegistrar, never())
- .getCallCapablePhoneAccounts(anyString(), anyBoolean(), any(UserHandle.class));
+ .getCallCapablePhoneAccounts(anyString(), anyBoolean(),
+ any(UserHandle.class), anyBoolean());
}
@SmallTest
@@ -420,10 +422,12 @@
List<PhoneAccountHandle> telPHList = List.of(TEL_PA_HANDLE_16);
when(mFakePhoneAccountRegistrar
- .getCallCapablePhoneAccounts(eq("tel"), anyBoolean(), any(UserHandle.class)))
+ .getCallCapablePhoneAccounts(eq("tel"), anyBoolean(),
+ any(UserHandle.class), anyBoolean()))
.thenReturn(telPHList);
when(mFakePhoneAccountRegistrar
- .getCallCapablePhoneAccounts(eq("sip"), anyBoolean(), any(UserHandle.class)))
+ .getCallCapablePhoneAccounts(eq("sip"), anyBoolean(),
+ any(UserHandle.class), anyBoolean()))
.thenReturn(sipPHList);
makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_16, SIP_PA_HANDLE_17);
@@ -472,7 +476,7 @@
makePhoneAccount(TEL_PA_HANDLE_16).build(),
makePhoneAccount(SIP_PA_HANDLE_17).build());
- when(mFakePhoneAccountRegistrar.getAllPhoneAccounts(any(UserHandle.class)))
+ when(mFakePhoneAccountRegistrar.getAllPhoneAccounts(any(UserHandle.class), anyBoolean()))
.thenReturn(phoneAccountList);
assertEquals(2, mTSIBinder.getAllPhoneAccounts().getList().size());
@@ -590,7 +594,7 @@
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
boolean didExceptionOccur = false;
try {
- mTSIBinder.registerPhoneAccount(testPhoneAccount);
+ mTSIBinder.registerPhoneAccount(testPhoneAccount, CALLING_PACKAGE);
} catch (Exception e) {
didExceptionOccur = true;
}
@@ -616,7 +620,7 @@
doReturn(PackageManager.PERMISSION_GRANTED)
.when(mContext).checkCallingOrSelfPermission(MODIFY_PHONE_STATE);
- mTSIBinder.unregisterPhoneAccount(phHandle);
+ mTSIBinder.unregisterPhoneAccount(phHandle, CALLING_PACKAGE);
verify(mFakePhoneAccountRegistrar).unregisterPhoneAccount(phHandle);
}
@@ -633,7 +637,7 @@
when(pm.hasSystemFeature(PackageManager.FEATURE_TELECOM)).thenReturn(false);
try {
- mTSIBinder.unregisterPhoneAccount(phHandle);
+ mTSIBinder.unregisterPhoneAccount(phHandle, CALLING_PACKAGE);
} catch (UnsupportedOperationException e) {
// expected behavior
}
@@ -646,24 +650,27 @@
@SmallTest
@Test
public void testAddNewIncomingCall() throws Exception {
- PhoneAccount phoneAccount = makePhoneAccount(TEL_PA_HANDLE_CURRENT).build();
+ PhoneAccount phoneAccount = makePhoneAccount(TEL_PA_HANDLE_16).build();
phoneAccount.setIsEnabled(true);
doReturn(phoneAccount).when(mFakePhoneAccountRegistrar).getPhoneAccount(
- eq(TEL_PA_HANDLE_CURRENT), any(UserHandle.class));
+ eq(TEL_PA_HANDLE_16), any(UserHandle.class));
doNothing().when(mAppOpsManager).checkPackage(anyInt(), anyString());
Bundle extras = createSampleExtras();
- mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_CURRENT, extras);
+ mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, extras, CALLING_PACKAGE);
+ verify(mFakePhoneAccountRegistrar).getPhoneAccount(
+ TEL_PA_HANDLE_16, TEL_PA_HANDLE_16.getUserHandle());
addCallTestHelper(TelecomManager.ACTION_INCOMING_CALL,
- CallIntentProcessor.KEY_IS_INCOMING_CALL, extras, false);
+ CallIntentProcessor.KEY_IS_INCOMING_CALL, extras,
+ TEL_PA_HANDLE_16, false);
}
@SmallTest
@Test
public void testAddNewIncomingCallFailure() throws Exception {
try {
- mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, null);
+ mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, null, CALLING_PACKAGE);
} catch (SecurityException e) {
// expected
}
@@ -671,7 +678,7 @@
doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString());
try {
- mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_CURRENT, null);
+ mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_CURRENT, null, CALLING_PACKAGE);
} catch (SecurityException e) {
// expected
}
@@ -694,7 +701,7 @@
mTSIBinder.addNewUnknownCall(TEL_PA_HANDLE_CURRENT, extras);
addCallTestHelper(TelecomManager.ACTION_NEW_UNKNOWN_CALL,
- CallIntentProcessor.KEY_IS_UNKNOWN_CALL, extras, true);
+ CallIntentProcessor.KEY_IS_UNKNOWN_CALL, extras, TEL_PA_HANDLE_CURRENT, true);
}
@SmallTest
@@ -720,7 +727,8 @@
}
private void addCallTestHelper(String expectedAction, String extraCallKey,
- Bundle expectedExtras, boolean isUnknown) {
+ Bundle expectedExtras, PhoneAccountHandle expectedPhoneAccountHandle,
+ boolean isUnknown) {
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
if (isUnknown) {
verify(mCallIntentProcessorAdapter).processUnknownCallIntent(any(CallsManager.class),
@@ -732,7 +740,7 @@
Intent capturedIntent = intentCaptor.getValue();
assertEquals(expectedAction, capturedIntent.getAction());
Bundle intentExtras = capturedIntent.getExtras();
- assertEquals(TEL_PA_HANDLE_CURRENT,
+ assertEquals(expectedPhoneAccountHandle,
intentExtras.get(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE));
assertTrue(intentExtras.getBoolean(extraCallKey));
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index d6ff196..eeb65c7 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -119,6 +119,7 @@
*/
public class TelecomSystemTest extends TelecomTestCase {
+ private static final String CALLING_PACKAGE = TelecomSystemTest.class.getPackageName();
static final int TEST_POLL_INTERVAL = 10; // milliseconds
static final int TEST_TIMEOUT = 1000; // milliseconds
@@ -904,7 +905,7 @@
TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null));
mTelecomSystem.getTelecomServiceImpl().getBinder()
- .addNewIncomingCall(phoneAccountHandle, extras);
+ .addNewIncomingCall(phoneAccountHandle, extras, CALLING_PACKAGE);
verify(connectionServiceFixture.getTestDouble())
.createConnection(any(PhoneAccountHandle.class), anyString(),
diff --git a/tests/src/com/android/server/telecom/tests/VoipCallTransactionTest.java b/tests/src/com/android/server/telecom/tests/VoipCallTransactionTest.java
new file mode 100644
index 0000000..d57a163
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/VoipCallTransactionTest.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.telecom.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.os.OutcomeReceiver;
+import android.util.Log;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.telecom.voip.ParallelTransaction;
+import com.android.server.telecom.voip.SerialTransaction;
+import com.android.server.telecom.voip.TransactionManager;
+import com.android.server.telecom.voip.VoipCallTransaction;
+import com.android.server.telecom.voip.VoipCallTransactionResult;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+@RunWith(JUnit4.class)
+public class VoipCallTransactionTest extends TelecomTestCase {
+ private StringBuilder mLog;
+ private TransactionManager mTransactionManager;
+
+ private class TestVoipCallTransaction extends VoipCallTransaction {
+ public static final int SUCCESS = 0;
+ public static final int FAILED = 1;
+ public static final int TIMEOUT = 2;
+
+ private long mSleepTime;
+ private String mName;
+ private int mType;
+
+ public TestVoipCallTransaction(String name, long sleepTime, int type) {
+ super();
+ mName = name;
+ mSleepTime = sleepTime;
+ mType = type;
+ }
+
+ @Override
+ public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ CompletableFuture<VoipCallTransactionResult> resultFuture = new CompletableFuture<>();
+ mHandler.postDelayed(() -> {
+ if (mType == SUCCESS) {
+ mLog.append(mName).append(" success;\n");
+ resultFuture.complete(
+ new VoipCallTransactionResult(VoipCallTransactionResult.RESULT_SUCCEED,
+ null));
+ } else if (mType == FAILED) {
+ mLog.append(mName).append(" failed;\n");
+ resultFuture.complete(
+ new VoipCallTransactionResult(VoipCallTransactionResult.RESULT_FAILED,
+ null));
+ } else {
+ mLog.append(mName).append(" timeout;\n");
+ resultFuture.complete(
+ new VoipCallTransactionResult(VoipCallTransactionResult.RESULT_FAILED,
+ "timeout"));
+ }
+ }, mSleepTime);
+ return resultFuture;
+ }
+ }
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ mTransactionManager = TransactionManager.getTestInstance();
+ mLog = new StringBuilder();
+ }
+
+ @Override
+ @After
+ public void tearDown() throws Exception {
+ Log.i("Grace", mLog.toString());
+ mTransactionManager.clear();
+ super.tearDown();
+ }
+
+ @SmallTest
+ @Test
+ public void testSerialTransactionSuccess()
+ throws ExecutionException, InterruptedException, TimeoutException {
+ List<VoipCallTransaction> subTransactions = new ArrayList<>();
+ VoipCallTransaction t1 = new TestVoipCallTransaction("t1", 1000L,
+ TestVoipCallTransaction.SUCCESS);
+ VoipCallTransaction t2 = new TestVoipCallTransaction("t2", 1000L,
+ TestVoipCallTransaction.SUCCESS);
+ VoipCallTransaction t3 = new TestVoipCallTransaction("t3", 1000L,
+ TestVoipCallTransaction.SUCCESS);
+ subTransactions.add(t1);
+ subTransactions.add(t2);
+ subTransactions.add(t3);
+ CompletableFuture<VoipCallTransactionResult> resultFuture = new CompletableFuture<>();
+ OutcomeReceiver<VoipCallTransactionResult, Exception> outcomeReceiver =
+ resultFuture::complete;
+ String expectedLog = "t1 success;\nt2 success;\nt3 success;\n";
+ mTransactionManager.addTransaction(new SerialTransaction(subTransactions), outcomeReceiver);
+ assertEquals(VoipCallTransactionResult.RESULT_SUCCEED,
+ resultFuture.get(5000L, TimeUnit.MILLISECONDS).getResult());
+ assertEquals(expectedLog, mLog.toString());
+ }
+
+ @SmallTest
+ @Test
+ public void testSerialTransactionFailed()
+ throws ExecutionException, InterruptedException, TimeoutException {
+ List<VoipCallTransaction> subTransactions = new ArrayList<>();
+ VoipCallTransaction t1 = new TestVoipCallTransaction("t1", 1000L,
+ TestVoipCallTransaction.SUCCESS);
+ VoipCallTransaction t2 = new TestVoipCallTransaction("t2", 1000L,
+ TestVoipCallTransaction.FAILED);
+ VoipCallTransaction t3 = new TestVoipCallTransaction("t3", 1000L,
+ TestVoipCallTransaction.SUCCESS);
+ subTransactions.add(t1);
+ subTransactions.add(t2);
+ subTransactions.add(t3);
+ CompletableFuture<String> exceptionFuture = new CompletableFuture<>();
+ OutcomeReceiver<VoipCallTransactionResult, Exception> outcomeReceiver =
+ new OutcomeReceiver<VoipCallTransactionResult, Exception>() {
+ @Override
+ public void onResult(VoipCallTransactionResult result) {
+
+ }
+
+ @Override
+ public void onError(Exception e) {
+ exceptionFuture.complete(e.getMessage());
+ }
+ };
+ mTransactionManager.addTransaction(new SerialTransaction(subTransactions),
+ outcomeReceiver);
+ exceptionFuture.get(5000L, TimeUnit.MILLISECONDS);
+ String expectedLog = "t1 success;\nt2 failed;\n";
+ assertEquals(expectedLog, mLog.toString());
+ }
+
+ @SmallTest
+ @Test
+ public void testParallelTransactionSuccess()
+ throws ExecutionException, InterruptedException, TimeoutException {
+ List<VoipCallTransaction> subTransactions = new ArrayList<>();
+ VoipCallTransaction t1 = new TestVoipCallTransaction("t1", 1000L,
+ TestVoipCallTransaction.SUCCESS);
+ VoipCallTransaction t2 = new TestVoipCallTransaction("t2", 500L,
+ TestVoipCallTransaction.SUCCESS);
+ VoipCallTransaction t3 = new TestVoipCallTransaction("t3", 200L,
+ TestVoipCallTransaction.SUCCESS);
+ subTransactions.add(t1);
+ subTransactions.add(t2);
+ subTransactions.add(t3);
+ CompletableFuture<VoipCallTransactionResult> resultFuture = new CompletableFuture<>();
+ OutcomeReceiver<VoipCallTransactionResult, Exception> outcomeReceiver =
+ resultFuture::complete;
+ mTransactionManager.addTransaction(new ParallelTransaction(subTransactions),
+ outcomeReceiver);
+ assertEquals(VoipCallTransactionResult.RESULT_SUCCEED,
+ resultFuture.get(5000L, TimeUnit.MILLISECONDS).getResult());
+ String log = mLog.toString();
+ assertTrue(log.contains("t1 success;\n"));
+ assertTrue(log.contains("t2 success;\n"));
+ assertTrue(log.contains("t3 success;\n"));
+ }
+
+ @SmallTest
+ @Test
+ public void testParallelTransactionFailed()
+ throws ExecutionException, InterruptedException, TimeoutException {
+ List<VoipCallTransaction> subTransactions = new ArrayList<>();
+ VoipCallTransaction t1 = new TestVoipCallTransaction("t1", 1000L,
+ TestVoipCallTransaction.SUCCESS);
+ VoipCallTransaction t2 = new TestVoipCallTransaction("t2", 500L,
+ TestVoipCallTransaction.FAILED);
+ VoipCallTransaction t3 = new TestVoipCallTransaction("t3", 200L,
+ TestVoipCallTransaction.SUCCESS);
+ subTransactions.add(t1);
+ subTransactions.add(t2);
+ subTransactions.add(t3);
+ CompletableFuture<String> exceptionFuture = new CompletableFuture<>();
+ OutcomeReceiver<VoipCallTransactionResult, Exception> outcomeReceiver =
+ new OutcomeReceiver<VoipCallTransactionResult, Exception>() {
+ @Override
+ public void onResult(VoipCallTransactionResult result) {
+
+ }
+
+ @Override
+ public void onError(Exception e) {
+ exceptionFuture.complete(e.getMessage());
+ }
+ };
+ mTransactionManager.addTransaction(new ParallelTransaction(subTransactions),
+ outcomeReceiver);
+ exceptionFuture.get(5000L, TimeUnit.MILLISECONDS);
+ assertTrue(mLog.toString().contains("t2 failed;\n"));
+ }
+
+ @SmallTest
+ @Test
+ public void testTransactionTimeout()
+ throws ExecutionException, InterruptedException, TimeoutException {
+ VoipCallTransaction t = new TestVoipCallTransaction("t", 10000L,
+ TestVoipCallTransaction.SUCCESS);
+ CompletableFuture<VoipCallTransactionResult> resultFuture = new CompletableFuture<>();
+ OutcomeReceiver<VoipCallTransactionResult, Exception> outcomeReceiver =
+ resultFuture::complete;
+ mTransactionManager.addTransaction(t, outcomeReceiver);
+ VoipCallTransactionResult result = resultFuture.get(7000L, TimeUnit.MILLISECONDS);
+ assertEquals(VoipCallTransactionResult.RESULT_FAILED, result.getResult());
+ assertTrue(result.getMessage().contains("timeout"));
+ }
+}