Merge "Sync phoneAccountHandle when phone is changed"
diff --git a/Android.bp b/Android.bp
index 1887a8a..e7ca068 100644
--- a/Android.bp
+++ b/Android.bp
@@ -35,6 +35,7 @@
"com.android.phone.common-lib",
"guava",
"PlatformProperties",
+ "modules-utils-os",
],
srcs: [
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index cf20002..e38ea00 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -24,7 +24,6 @@
<original-package android:name="com.android.phone" />
- <protected-broadcast android:name="android.telecom.action.TTY_PREFERRED_MODE_CHANGED" />
<protected-broadcast android:name="android.telecom.action.CURRENT_TTY_MODE_CHANGED" />
<protected-broadcast android:name="android.intent.action.SERVICE_STATE" />
<protected-broadcast android:name="android.intent.action.RADIO_TECHNOLOGY" />
@@ -83,6 +82,7 @@
<protected-broadcast android:name= "com.android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO" />
<protected-broadcast android:name= "com.android.internal.telephony.ACTION_CARRIER_CERTIFICATE_DOWNLOAD" />
<protected-broadcast android:name= "com.android.internal.telephony.OPEN_DEFAULT_SMS_APP" />
+ <protected-broadcast android:name= "com.android.internal.telephony.ACTION_TEST_OVERRIDE_CARRIER_ID" />
<protected-broadcast android:name= "android.telephony.action.SIM_CARD_STATE_CHANGED" />
<protected-broadcast android:name= "android.telephony.action.SIM_APPLICATION_STATE_CHANGED" />
<protected-broadcast android:name= "android.telephony.action.SIM_SLOT_STATUS_CHANGED" />
@@ -218,6 +218,9 @@
from the background. -->
<uses-permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" />
<uses-permission android:name="android.permission.NETWORK_STATS_PROVIDER" />
+ <uses-permission android:name="android.permission.HANDLE_CAR_MODE_CHANGES"/>
+ <uses-permission android:name="android.permission.MANAGE_SUBSCRIPTION_PLANS"/>
+ <uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS"/>
<application android:name="PhoneApp"
android:persistent="true"
@@ -236,6 +239,10 @@
android:readPermission="android.permission.READ_CONTACTS"
android:writePermission="android.permission.WRITE_CONTACTS" />
+ <provider android:name="com.android.ims.rcs.uce.eab.EabProvider"
+ android:authorities="eab"
+ android:exported="false"/>
+
<!-- Dialer UI that only allows emergency calls -->
<activity android:name="EmergencyDialer"
android:label="@string/emergencyDialerIconLabel"
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 2c01787..cb0ec8b 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -96,7 +96,7 @@
<string name="sum_loading_settings" msgid="434063780286688775">"Laai tans instellings..."</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"Nommer versteek in uitgaande oproepe"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"Nommer wat vertoon in uitgaande oproepe"</string>
- <string name="sum_default_caller_id" msgid="1767070797135682959">"Gebruik verstek beheerinstellings om my nommer te vertoon in uitgaande oproepe"</string>
+ <string name="sum_default_caller_id" msgid="1767070797135682959">"Gebruik verstekbeheerinstellings om my nommer te vertoon in uitgaande oproepe"</string>
<string name="labelCW" msgid="8449327023861428622">"Oproep wag"</string>
<string name="sum_cw_enabled" msgid="3977308526187139996">"Stel my tydens \'n oproep in kennis van inkomende oproepe"</string>
<string name="sum_cw_disabled" msgid="3658094589461768637">"Stel my tydens \'n oproep in kennis van inkomende oproepe"</string>
@@ -149,7 +149,7 @@
<string name="close_dialog" msgid="1074977476136119408">"OK"</string>
<string name="enable" msgid="2636552299455477603">"Skakel aan"</string>
<string name="disable" msgid="1122698860799462116">"Skakel af"</string>
- <string name="change_num" msgid="6982164494063109334">"Opdateer"</string>
+ <string name="change_num" msgid="6982164494063109334">"Dateer op"</string>
<string-array name="clir_display_values">
<item msgid="8477364191403806960">"Netwerkverstek"</item>
<item msgid="6813323051965618926">"Versteek nommer"</item>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Sub-ID van verstekdata-SIM:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Aflaaibandwydte (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Oplaaibandwydte (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Selligginginligting (opgeskort):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Fisieke LTE-kanaalopstelling:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Herlaaikoers van selinligting:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Alle selmetingsinligting:"</string>
diff --git a/res/values-am/arrays.xml b/res/values-am/arrays.xml
index f5cfebf..9d43d58 100644
--- a/res/values-am/arrays.xml
+++ b/res/values-am/arrays.xml
@@ -18,7 +18,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string-array name="preferred_network_mode_choices_world_mode">
- <item msgid="8359756926680194770">"አለምአቀፍ"</item>
+ <item msgid="8359756926680194770">"ዓለምአቀፍ"</item>
<item msgid="7497128470871581354">"LTE / CDMA"</item>
<item msgid="1732367262765147258">"LTE / GSM / UMTS"</item>
</string-array>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 21b2417..a2ebdf5 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -75,7 +75,7 @@
<string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"የመለያ ቅንብሮችን ይውቀሩ"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"የሁሉም ደዋይ መለያዎች"</string>
<string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"የትኛዎቹ መለያዎች ጥሪዎችን ማድረግ እንደሚችሉ ይምረጡ"</string>
- <string name="wifi_calling" msgid="3650509202851355742">"የWi-Fi ጥሪ ማድረጊያ"</string>
+ <string name="wifi_calling" msgid="3650509202851355742">"የWi-Fi ጥሪ"</string>
<string name="connection_service_default_label" msgid="7332739049855715584">"አብሮ የተገነባ የግንኙነት አገልግሎት"</string>
<string name="voicemail" msgid="7697769412804195032">"የድምፅ መልዕክት"</string>
<string name="voicemail_settings_with_label" msgid="4228431668214894138">"የድምጽ መልዕክት (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -244,7 +244,7 @@
<string name="preferred_network_mode_lte_gsm_wcdma_summary" msgid="2217794334331254936">"ተመራጭ የአውታረመረብ ሁኔታ: GSM/WCDMA/LTE"</string>
<string name="preferred_network_mode_lte_cdma_evdo_summary" msgid="5559198623419981805">"ተመራጭ የአውታረመረብ ሁኔታ ፡ CDMA+LTE/EVDO"</string>
<string name="preferred_network_mode_lte_cdma_evdo_gsm_wcdma_summary" msgid="6707224437925495615">"የተመረጠው የአውታረ መረብ ሁነታ፦ LTE/CDMA/EvDo/GSM/WCDMA"</string>
- <string name="preferred_network_mode_global_summary" msgid="3847086258439582411">"ተመራጭ የአውታረመረብ ፡ አለምአቀፍ"</string>
+ <string name="preferred_network_mode_global_summary" msgid="3847086258439582411">"ተመራጭ የአውታረመረብ ፡ ዓለምአቀፍ"</string>
<string name="preferred_network_mode_lte_wcdma_summary" msgid="7001804022020813865">"ተመራጭ የአውታረመረብ ሁኔታ፡ LTE / WCDMA"</string>
<string name="preferred_network_mode_lte_gsm_umts_summary" msgid="6484203890156282179">"ተመራጭ የአውታረ መረብ ሁነታ፦ LTE / GSM / UMTS"</string>
<string name="preferred_network_mode_lte_cdma_summary" msgid="8187929456614068518">"ተመራጭ የአውታረመረብ ፡LTE / CDMA ሁነታ"</string>
@@ -411,7 +411,7 @@
<string name="network_recommended" msgid="3444321100580250926">" (የሚመከር)"</string>
<string name="network_lte" msgid="7206879277095094280">"LTE (የሚመከር)"</string>
<string name="network_4G" msgid="6800527815504223913">"4G (የሚመከር)"</string>
- <string name="network_global" msgid="3289646154407617631">"አለምአቀፍ"</string>
+ <string name="network_global" msgid="3289646154407617631">"ዓለምአቀፍ"</string>
<string name="cdma_system_select_title" msgid="614165233552656431">"የሥርዓት ምርጫ"</string>
<string name="cdma_system_select_summary" msgid="3840420390242060407">"የCDMA በእንቅስቃሴ ላይ ሁኔታ ለውጥ"</string>
<string name="cdma_system_select_dialogtitle" msgid="5524639510676501802">"የሥርዓት ምርጫ"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"የነባሪ ውሂብ ሲም SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL መተላለፊያ ይዘት (ኪቢ/ሴ)፡"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"የUL መተላለፊያ ይዘት (ኪቢ/ሴ)፡"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"የሕዋስ የአካባቢ መረጃ (የተቋረጠ)፦"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"የLTE አካላዊ ሰርጥ ውቅረት:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"የሕዋስ መረጃ እድሳት ፍጥነት፡"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ሁሉም የሕዋስ መለኪያ መረጃ፡"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index c1596cb..cce064f 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -50,8 +50,7 @@
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"يمكن تعديل إعدادات البريد الصوتي عن طريق المستخدم الأساسي فقط."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"تم إلغاء حظر شريحة SIM. جارٍ فتح قفل الهاتف..."</string>
<string name="label_ndp" msgid="7617392683877410341">"رمز PIN لإلغاء تأمين شبكة SIM"</string>
- <!-- no translation found for label_phoneid (8775611434123577808) -->
- <skip />
+ <string name="label_phoneid" msgid="8775611434123577808">"شريحة SIM مقيدَّة إلى مشغّل الشبكة"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"فتح قفل"</string>
<string name="sim_ndp_dismiss_text" msgid="89667342248929777">"استبعاد"</string>
<string name="requesting_unlock" msgid="930512210309437741">"جارٍ طلب فتح قفل الشبكة..."</string>
@@ -73,7 +72,7 @@
<string name="phone_accounts_choose_accounts" msgid="4748805293314824974">"اختيار الحسابات"</string>
<string name="phone_accounts_selection_header" msgid="2945830843104108440">"حسابات الهاتف"</string>
<string name="phone_accounts_add_sip_account" msgid="1437634802033309305">"إضافة حساب SIP"</string>
- <string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"تهيئة إعدادات الحساب"</string>
+ <string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"ضبط إعدادات الحساب"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"كل حسابات الاتصال"</string>
<string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"حدد الحسابات التي يمكنها إجراء مكالمات"</string>
<string name="wifi_calling" msgid="3650509202851355742">"الاتصال عبر Wi-Fi"</string>
@@ -120,7 +119,7 @@
<string name="sum_cfnry_enabled" msgid="3000500837493854799">"إعادة التوجيه إلى <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfnry_disabled" msgid="1990563512406017880">"غير مفعّل"</string>
<string name="disable_cfnry_forbidden" msgid="3174731413216550689">"لا يتيح مشغل شبكة الجوال إيقاف اعادة توجيه المكالمة عند عدم رد هاتفك."</string>
- <string name="labelCFNRc" msgid="4163399350778066013">"عند عدم الوصول"</string>
+ <string name="labelCFNRc" msgid="4163399350778066013">"عند تعذر الوصول"</string>
<string name="messageCFNRc" msgid="6980340731313007250">"الرقم عند عدم الوصول"</string>
<string name="sum_cfnrc_enabled" msgid="1799069234006073477">"إعادة التوجيه إلى <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfnrc_disabled" msgid="739289696796917683">"غير مفعّل"</string>
@@ -137,7 +136,7 @@
<string name="call_settings_with_label" msgid="8460230435361579511">"الإعدادات (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="error_updating_title" msgid="2024290892676808965">"خطأ في إعدادات الاتصال"</string>
<string name="reading_settings" msgid="1605904432450871183">"جارٍ قراءة الإعدادات..."</string>
- <string name="updating_settings" msgid="3650396734816028808">"جارٍ تحديث الإعدادات..."</string>
+ <string name="updating_settings" msgid="3650396734816028808">"جارٍ تعديل الإعدادات..."</string>
<string name="reverting_settings" msgid="7378668837291012205">"جارٍ إعادة الإعدادات..."</string>
<string name="response_error" msgid="3904481964024543330">"رد غير متوقع من الشبكة."</string>
<string name="exception_error" msgid="330994460090467">"خطأ في الشبكة أو في شريحة SIM"</string>
@@ -353,7 +352,7 @@
<string name="international_enable" msgid="8943466745792690340">"تم تفعيل الأخبار الدولية"</string>
<string name="international_disable" msgid="4803498658100318265">"تم إيقاف الأخبار الدولية"</string>
<string name="list_language_title" msgid="1850167908665485738">"اللغة"</string>
- <string name="list_language_summary" msgid="7921756070782277559">"حدد لغة الأخبار"</string>
+ <string name="list_language_summary" msgid="7921756070782277559">"اختَر لغة الأخبار"</string>
<string-array name="list_language_entries">
<item msgid="2347238508726934281">"الإنجليزية"</item>
<item msgid="5172468397620875174">"الفرنسية"</item>
@@ -480,7 +479,7 @@
<string name="simContacts_emptyLoading" msgid="4989040293858675483">"جارٍ القراءة من شريحة SIM..."</string>
<string name="simContacts_empty" msgid="1135632055473689521">"ليس هناك جهات اتصال على شريحة SIM."</string>
<string name="simContacts_title" msgid="2714029230160136647">"حدد جهات اتصال لاستيرادها"</string>
- <string name="simContacts_airplaneMode" msgid="4654884030631503808">"عليك إيقاف وضع الطائرة لاستيراد جهات الاتصال من شريحة SIM."</string>
+ <string name="simContacts_airplaneMode" msgid="4654884030631503808">"عليك إيقاف وضع الطيران لاستيراد جهات الاتصال من شريحة SIM."</string>
<string name="enable_pin" msgid="967674051730845376">"تفعيل/إيقاف رمز PIN لبطاقة SIM"</string>
<string name="change_pin" msgid="3657869530942905790">"تغيير رمز PIN لبطاقة SIM"</string>
<string name="enter_pin_text" msgid="3182311451978663356">"رمز PIN لبطاقة SIM:"</string>
@@ -493,7 +492,7 @@
<string name="disable_sim_pin" msgid="3112303905548613752">"محو رقم التعريف الشخصي لبطاقة SIM"</string>
<string name="enable_sim_pin" msgid="445461050748318980">"تعيين رقم التعريف الشخصي لبطاقة SIM"</string>
<string name="enable_in_progress" msgid="4135305985717272592">"جارٍ تعيين رقم التعريف الشخصي…"</string>
- <string name="enable_pin_ok" msgid="2877428038280804256">"تم تعيين رقم التعريف الشخصي"</string>
+ <string name="enable_pin_ok" msgid="2877428038280804256">"تم ضبط رقم التعريف الشخصي"</string>
<string name="disable_pin_ok" msgid="888505244389647754">"تم محو رقم التعريف الشخصي"</string>
<string name="pin_failed" msgid="4527347792881939652">"رقم التعريف الشخصي غير صحيح"</string>
<string name="pin_changed" msgid="7291153750090452808">"تم تحديث رقم التعريف الشخصي"</string>
@@ -531,9 +530,9 @@
<string name="notification_voicemail_no_vm_number" msgid="3423686009815186750">"رقم البريد الصوتي غير معروف"</string>
<string name="notification_network_selection_title" msgid="255595526707809121">"لا خدمة"</string>
<string name="notification_network_selection_text" msgid="553288408722427659">"الشبكة المحدّدة (<xliff:g id="OPERATOR_NAME">%s</xliff:g>) غير مُتاحة"</string>
- <string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"شغَّل شبكة الجوال، ثم أوقف تفعيل وضع الطائرة أو أوقف تفعيل وضع توفير شحن البطارية لإجراء مكالمة."</string>
- <string name="incall_error_power_off" product="default" msgid="8131672264311208673">"عليك إيقاف وضع الطائرة لإجراء مكالمة."</string>
- <string name="incall_error_power_off_wfc" msgid="9125661184694727052">"عليك إيقاف وضع الطائرة أو الاتصال بشبكة لاسلكية لإجراء مكالمة."</string>
+ <string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"شغَّل شبكة الجوال، ثم أوقف تفعيل وضع الطيران أو أوقف تفعيل وضع توفير شحن البطارية لإجراء مكالمة."</string>
+ <string name="incall_error_power_off" product="default" msgid="8131672264311208673">"عليك إيقاف وضع الطيران لإجراء مكالمة."</string>
+ <string name="incall_error_power_off_wfc" msgid="9125661184694727052">"عليك إيقاف وضع الطيران أو الاتصال بشبكة لاسلكية لإجراء مكالمة."</string>
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"ينبغي الخروج من وضع معاودة الاتصال بالطوارئ لإجراء مكالمة غير طارئة."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"غير مسجل على الشبكة."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"شبكة الجوال غير متاحة."</string>
@@ -561,7 +560,7 @@
<string name="emergency_call_shortcut_hint" msgid="1290485125107779500">"انقر مجددًا للاتصال بالرقم <xliff:g id="EMERGENCY_NUMBER">%s</xliff:g>"</string>
<string name="emergency_enable_radio_dialog_message" msgid="1695305158151408629">"جارٍ تفعيل اللاسلكي..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="4329131876852608587">"لا تتوفر خدمة. جارٍ إعادة المحاولة…"</string>
- <string name="radio_off_during_emergency_call" msgid="8011154134040481609">"لا يمكن دخول وضع الطائرة أثناء إجراء مكالمة طوارئ."</string>
+ <string name="radio_off_during_emergency_call" msgid="8011154134040481609">"لا يمكن دخول وضع الطيران أثناء إجراء مكالمة طوارئ."</string>
<string name="dial_emergency_error" msgid="825822413209026039">"يتعذر الاتصال. لا يعد <xliff:g id="NON_EMERGENCY_NUMBER">%s</xliff:g> رقم طوارئ."</string>
<string name="dial_emergency_empty_error" msgid="2785803395047793634">"يتعذر الاتصال. يمكنك طلب رقم طوارئ."</string>
<string name="dial_emergency_calling_not_available" msgid="6485846193794727823">"مكالمة الطوارئ غير متوفرة"</string>
@@ -666,12 +665,12 @@
</plurals>
<string name="voicemail_provider" msgid="4158806657253745294">"الخدمة"</string>
<string name="voicemail_settings" msgid="4451045613238972776">"الإعداد"</string>
- <string name="voicemail_number_not_set" msgid="8831561283386938155">"<لم يتم التعيين>"</string>
+ <string name="voicemail_number_not_set" msgid="8831561283386938155">"<لم يتم الضبط>"</string>
<string name="other_settings" msgid="8895088007393598447">"اعدادات المكالمات الاخرى"</string>
<string name="calling_via_template" msgid="1791323450703751750">"الاتصال عبر <xliff:g id="PROVIDER_NAME">%s</xliff:g>"</string>
<string name="contactPhoto" msgid="7885089213135154834">"صورة جهة الاتصال"</string>
<string name="goPrivate" msgid="4645108311382209551">"انتقال إلى مكالمة خاصة"</string>
- <string name="selectContact" msgid="1527612842599767382">"تحديد جهة اتصال"</string>
+ <string name="selectContact" msgid="1527612842599767382">"اختيار جهة اتصال"</string>
<string name="not_voice_capable" msgid="2819996734252084253">"الاتصال الصوتي غير معتمد"</string>
<string name="description_dial_button" msgid="8614631902795087259">"طلب"</string>
<string name="description_dialpad_button" msgid="7395114120463883623">"عرض لوحة الاتصال"</string>
@@ -688,7 +687,7 @@
<string name="sim_label_emergency_calls" msgid="9078241989421522310">"مكالمات الطوارئ"</string>
<string name="sim_description_emergency_calls" msgid="5146872803938897296">"مكالمات الطوارئ فقط"</string>
<string name="sim_description_default" msgid="7474671114363724971">"شريحة SIM، المنفذ: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
- <string name="accessibility_settings_activity_title" msgid="7883415189273700298">"إمكانية الوصول"</string>
+ <string name="accessibility_settings_activity_title" msgid="7883415189273700298">"إعدادات تمكين الوصول"</string>
<string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"مكالمة Wi-Fi من"</string>
<string name="status_hint_label_wifi_call" msgid="942993035689809853">"مكالمة عبر Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="2762016865340891314">"انقر مرة أخرى للفتح."</string>
@@ -728,7 +727,7 @@
<string name="mobile_data_activate_button" msgid="1139792516354374612">"إضافة بيانات"</string>
<string name="mobile_data_activate_cancel_button" msgid="3530174817572005860">"إلغاء"</string>
<string name="clh_card_title_call_ended_txt" msgid="5977978317527299698">"تم إنهاء الاتصال"</string>
- <string name="clh_callFailed_powerOff_txt" msgid="8279934912560765361">"تفعيل وضع الطائرة"</string>
+ <string name="clh_callFailed_powerOff_txt" msgid="8279934912560765361">"تفعيل وضع الطيران"</string>
<string name="clh_callFailed_simError_txt" msgid="5128538525762326413">"تعذر الوصول إلى شريحة SIM"</string>
<string name="clh_incall_error_out_of_service_txt" msgid="2736010617446749869">"شبكة الجوّال غير متوفرة"</string>
<string name="clh_callFailed_unassigned_number_txt" msgid="141967660286695682">"حدثت مشكلة في رقم الهاتف الذي تحاول الاتصال به. رمز الخطأ 1."</string>
@@ -888,7 +887,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"المعرّف الفرعي لشريحة SIM التلقائية للبيانات:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"معدّل نقل بيانات DL (كيلوبت في الثانية):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"معدّل نقل بيانات UL (كيلوبت في الثانية):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"معلومات الموقع الخلوية (تم الإيقاف):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"ضبط قناة LTE Physical:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"معدّل إعادة تحميل المعلومات الخلوية:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"جميع معلومات القياس الخلوية:"</string>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index f8972b3..6c653bd 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ডিফ’ল্ট ডেটা ছিমৰ ছাবআইডি:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL বেণ্ডৱিথ (কেবিপিএছ):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL বেণ্ডৱিথ (কেবিপিএছ):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"চেল অৱস্থানৰ তথ্য (অনুমোদিত নহয়):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ফিজিকেল চেনেলৰ কনফিগাৰেশ্বন:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"চেল তথ্য ৰিফ্ৰেশ্বৰ হাৰ:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"সকলো চেল পৰিমাপৰ তথ্য:"</string>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 433ede2..c5bbc87 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Defolt data SIM üçün alt Id:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL Buraxılışı (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL Buraxılışı (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Xananın məkan məlumatı (ləğv edilib):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE Fiziki Kanal Konfiqurasiyası:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobil məlumatın yenilənmə göstəricisi:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Operatorun bütün mobil ölçü məlumatı:"</string>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 73325cf..0c0aad3 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -75,7 +75,7 @@
<string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"Konfigurisanje podešavanja naloga"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"Svi nalozi za pozivanje"</string>
<string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"Izaberite koji nalozi mogu da obavljaju pozive"</string>
- <string name="wifi_calling" msgid="3650509202851355742">"Pozivanje preko Wi-Fi-ja"</string>
+ <string name="wifi_calling" msgid="3650509202851355742">"Pozivanje preko WiFi-a"</string>
<string name="connection_service_default_label" msgid="7332739049855715584">"Ugrađena usluga povezivanja"</string>
<string name="voicemail" msgid="7697769412804195032">"Govorna pošta"</string>
<string name="voicemail_settings_with_label" msgid="4228431668214894138">"Glasovna pošta (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -119,7 +119,7 @@
<string name="sum_cfnry_enabled" msgid="3000500837493854799">"Prosleđuje se na <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfnry_disabled" msgid="1990563512406017880">"Isključeno"</string>
<string name="disable_cfnry_forbidden" msgid="3174731413216550689">"Operater ne podržava onemogućavanje preusmeravanja poziva kada se na poziv ne odgovori."</string>
- <string name="labelCFNRc" msgid="4163399350778066013">"Kad sam nedostupan/a"</string>
+ <string name="labelCFNRc" msgid="4163399350778066013">"Kad sam nedostupan/na"</string>
<string name="messageCFNRc" msgid="6980340731313007250">"Broj kad je nedostupno"</string>
<string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Prosleđuje se na <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfnrc_disabled" msgid="739289696796917683">"Isključeno"</string>
@@ -306,7 +306,7 @@
<string name="sim_selection_required_pref" msgid="6985901872978341314">"Potrebno je da izaberete nešto"</string>
<string name="sim_change_data_title" msgid="9142726786345906606">"Da promenimo SIM za podatke?"</string>
<string name="sim_change_data_message" msgid="3567358694255933280">"Želite li da za mobilne podatke koristite <xliff:g id="NEW_SIM">%1$s</xliff:g> umesto <xliff:g id="OLD_SIM">%2$s</xliff:g>?"</string>
- <string name="wifi_calling_settings_title" msgid="5800018845662016507">"Pozivanje preko Wi-Fi-ja"</string>
+ <string name="wifi_calling_settings_title" msgid="5800018845662016507">"Pozivanje preko WiFi-a"</string>
<string name="video_calling_settings_title" msgid="342829454913266078">"Video pozivanje preko operatera"</string>
<string name="gsm_umts_options" msgid="4968446771519376808">"Opcije za GSM/UMTS"</string>
<string name="cdma_options" msgid="3669592472226145665">"CDMA opcije"</string>
@@ -550,7 +550,7 @@
<string name="incall_error_supp_service_hangup" msgid="836524952243836735">"Uspostavljanje poziva nije uspelo."</string>
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Nije moguće stavljati pozive na čekanje."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Povežite se na bežičnu mrežu da biste uputili poziv."</string>
- <string name="incall_error_promote_wfc" msgid="9164896813931363415">"Omogućite pozivanje preko Wi-Fi-ja da biste uputili poziv."</string>
+ <string name="incall_error_promote_wfc" msgid="9164896813931363415">"Omogućite pozivanje preko WiFi-a da biste uputili poziv."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Informacije za hitne slučajeve"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Vlasnik"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Dodirnite ponovo da biste videli informacije"</string>
@@ -572,7 +572,7 @@
<string name="dialerKeyboardHintText" msgid="1115266533703764049">"Koristite tastaturu za pozivanje"</string>
<string name="onscreenHoldText" msgid="4025348842151665191">"Čekanje"</string>
<string name="onscreenEndCallText" msgid="6138725377654842757">"Završi"</string>
- <string name="onscreenShowDialpadText" msgid="658465753816164079">"Numerička tastatura"</string>
+ <string name="onscreenShowDialpadText" msgid="658465753816164079">"Brojčanik"</string>
<string name="onscreenMuteText" msgid="5470306116733843621">"Isključi zvuk"</string>
<string name="onscreenAddCallText" msgid="9075675082903611677">"Dodaj poziv"</string>
<string name="onscreenMergeCallsText" msgid="3692389519611225407">"Objedini pozive"</string>
@@ -612,7 +612,7 @@
<string name="ota_hfa_activation_title" msgid="3300556778212729671">"Aktiviranje..."</string>
<string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"Telefon aktivira uslugu mobilnog prenosa podataka.\n\nTo može da potraje i do 5 minuta."</string>
<string name="ota_skip_activation_dialog_title" msgid="7666611236789203797">"Želite li da preskočite aktivaciju?"</string>
- <string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"Ako preskočite aktivaciju, ne možete da upućujete pozive ili da se povezujete sa mrežama za mobilni prenos podataka (iako možete da se povežete sa Wi-Fi mrežama). Sve dok ne aktivirate svoj telefon, bićete upitani da to učinite svaki put kada ga uključite."</string>
+ <string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"Ako preskočite aktivaciju, ne možete da upućujete pozive ili da se povezujete sa mrežama za mobilni prenos podataka (iako možete da se povežete sa WiFi mrežama). Sve dok ne aktivirate svoj telefon, bićete upitani da to učinite svaki put kada ga uključite."</string>
<string name="ota_skip_activation_dialog_skip_label" msgid="5908029466817825633">"Preskoči"</string>
<string name="ota_activate" msgid="7939695753665438357">"Aktiviraj"</string>
<string name="ota_title_activate_success" msgid="1272135024761004889">"Telefon je aktiviran."</string>
@@ -665,7 +665,7 @@
<string name="not_voice_capable" msgid="2819996734252084253">"Audio pozivi nisu podržani"</string>
<string name="description_dial_button" msgid="8614631902795087259">"biranje"</string>
<string name="description_dialpad_button" msgid="7395114120463883623">"prikažite numeričku tastaturu"</string>
- <string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"Numerička tastatura za hitne pozive"</string>
+ <string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"Brojčanik za hitne pozive"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="6610414098912832120">"Vizuelna govorna pošta"</string>
<string name="voicemail_set_pin_dialog_title" msgid="7005128605986960003">"Podesite PIN"</string>
<string name="voicemail_change_pin_dialog_title" msgid="4633077715231764435">"Promenite PIN"</string>
@@ -679,18 +679,18 @@
<string name="sim_description_emergency_calls" msgid="5146872803938897296">"Samo za hitne pozive"</string>
<string name="sim_description_default" msgid="7474671114363724971">"SIM kartica, otvor: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="7883415189273700298">"Pristupačnost"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"Wi-Fi poziv od"</string>
- <string name="status_hint_label_wifi_call" msgid="942993035689809853">"Wi-Fi poziv"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"WiFi poziv od"</string>
+ <string name="status_hint_label_wifi_call" msgid="942993035689809853">"WiFi poziv"</string>
<string name="emergency_action_launch_hint" msgid="2762016865340891314">"Dodirnite ponovo da biste otvorili"</string>
<string name="message_decode_error" msgid="1061856591500290887">"Došlo je do greške pri dekodiranju poruke."</string>
<string name="callFailed_cdma_activation" msgid="5392057031552253550">"SIM kartica je aktivirala uslugu i ažurirala funkcije rominga na telefonu."</string>
<string name="callFailed_cdma_call_limit" msgid="1074219746093031412">"Ima previše aktivnih poziva. Završite ili objedinite postojeće pozive pre nego što uputite novi."</string>
<string name="callFailed_imei_not_accepted" msgid="7257903653685147251">"Povezivanje nije uspelo, ubacite važeću SIM karticu."</string>
- <string name="callFailed_wifi_lost" msgid="1788036730589163141">"Wi-Fi veza je prekinuta. Poziv je završen."</string>
+ <string name="callFailed_wifi_lost" msgid="1788036730589163141">"WiFi veza je prekinuta. Poziv je završen."</string>
<string name="dialFailed_low_battery" msgid="6857904237423407056">"Ne možete da uputite poziv jer je baterija skoro prazna."</string>
<string name="callFailed_low_battery" msgid="4056828320214416182">"Video poziv je prekinut jer je baterija skoro prazna."</string>
- <string name="callFailed_emergency_call_over_wfc_not_available" msgid="5944309590693432042">"Hitni pozivi pomoću funkcije Pozivanje preko Wi-Fi-ja nisu dostupni na ovoj lokaciji."</string>
- <string name="callFailed_wfc_service_not_available_in_this_location" msgid="3624536608369524988">"Pozivanje preko Wi-Fi-ja nije dostupno na ovoj lokaciji."</string>
+ <string name="callFailed_emergency_call_over_wfc_not_available" msgid="5944309590693432042">"Hitni pozivi pomoću funkcije Pozivanje preko WiFi-a nisu dostupni na ovoj lokaciji."</string>
+ <string name="callFailed_wfc_service_not_available_in_this_location" msgid="3624536608369524988">"Pozivanje preko WiFi-a nije dostupno na ovoj lokaciji."</string>
<string name="change_pin_title" msgid="3564254326626797321">"Promenite PIN kôd govorne pošte"</string>
<string name="change_pin_continue_label" msgid="5177011752453506371">"Nastavi"</string>
<string name="change_pin_cancel_label" msgid="2301711566758827936">"Otkaži"</string>
@@ -835,7 +835,7 @@
<string name="radio_info_data_connection_disable" msgid="6404751291511368706">"Onemogući vezu za prenos podataka"</string>
<string name="volte_provisioned_switch_string" msgid="4812874990480336178">"Dodeljeno za VoLTE"</string>
<string name="vt_provisioned_switch_string" msgid="8295542122512195979">"Video pozivi su dodeljeni"</string>
- <string name="wfc_provisioned_switch_string" msgid="3835004640321078988">"Pozivanje preko Wi-Fi-ja je dodeljeno"</string>
+ <string name="wfc_provisioned_switch_string" msgid="3835004640321078988">"Pozivanje preko WiFi-a je dodeljeno"</string>
<string name="eab_provisioned_switch_string" msgid="4449676720736033035">"Dodeljen je EAB/prisustvo"</string>
<string name="cbrs_data_switch_string" msgid="6060356430838077653">"Podaci CBRS-a"</string>
<string name="dsds_switch_string" msgid="7564769822086764796">"Omogući DSDS"</string>
@@ -853,7 +853,7 @@
<string name="radio_info_ims_reg_status_not_registered" msgid="8045821447288876085">"Nije registrovano"</string>
<string name="radio_info_ims_feature_status_available" msgid="6493200914756969292">"Dostupno"</string>
<string name="radio_info_ims_feature_status_unavailable" msgid="8930391136839759778">"Nije dostupno"</string>
- <string name="radio_info_ims_reg_status" msgid="25582845222446390">"Registracija IMS-a: <xliff:g id="STATUS">%1$s</xliff:g>\nGlas preko LTE-a: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nGlas preko Wi-Fi-ja: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nVideo poziv: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nUT interfejs: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
+ <string name="radio_info_ims_reg_status" msgid="25582845222446390">"Registracija IMS-a: <xliff:g id="STATUS">%1$s</xliff:g>\nGlas preko LTE-a: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nGlas preko WiFi-a: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nVideo poziv: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nUT interfejs: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
<string name="radioInfo_service_in" msgid="45753418231446400">"Radi"</string>
<string name="radioInfo_service_out" msgid="287972405416142312">"Ne radi"</string>
<string name="radioInfo_service_emergency" msgid="4763879891415016848">"Samo hitni pozivi"</string>
@@ -878,7 +878,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubID podrazumevanog SIM-a za podatke:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL propusni opseg (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL propusni opseg (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informacije o lokaciji predajnika (zastarelo):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguracija LTE fizičkog kanala:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Učestalost osvežavanja informacija o predajniku:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Sve informacije o merenju za predajnik:"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 119de53..49891f6 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -30,7 +30,7 @@
<string name="mmiStarted" msgid="9212975136944568623">"Пачалося выкананне MMI кода"</string>
<string name="ussdRunning" msgid="1163586813106772717">"Запускаецца USSD-код..."</string>
<string name="mmiCancelled" msgid="5339191899200678272">"Код MMI адменены"</string>
- <string name="cancel" msgid="8984206397635155197">"Адмяніць"</string>
+ <string name="cancel" msgid="8984206397635155197">"Скасаваць"</string>
<string name="enter_input" msgid="6193628663039958990">"Паведамленне USSD павінна складацца з наступнай колькасцi знакаў: ад <xliff:g id="MIN_LEN">%1$d</xliff:g> да <xliff:g id="MAX_LEN">%2$d</xliff:g>. Паспрабуйце яшчэ раз."</string>
<string name="manageConferenceLabel" msgid="8415044818156353233">"Кіраванне канферэнц-выклікам"</string>
<string name="ok" msgid="7818974223666140165">"ОК"</string>
@@ -310,11 +310,11 @@
<string name="video_calling_settings_title" msgid="342829454913266078">"Відэавыклікі праз аператара"</string>
<string name="gsm_umts_options" msgid="4968446771519376808">"Параметры GSM/UMTS"</string>
<string name="cdma_options" msgid="3669592472226145665">"Параметры CDMA"</string>
- <string name="throttle_data_usage" msgid="1944145350660420711">"Выкарыстанне трафіку"</string>
+ <string name="throttle_data_usage" msgid="1944145350660420711">"Выкарыстанне трафіка"</string>
<string name="throttle_current_usage" msgid="7483859109708658613">"Выкарыстанне даных у бягучы перыяд"</string>
<string name="throttle_time_frame" msgid="1813452485948918791">"Перыяд выкарыстання дадзеных"</string>
<string name="throttle_rate" msgid="7641913901133634905">"Палітыка хуткасці перадачы дадзеных"</string>
- <string name="throttle_help" msgid="2624535757028809735">"Дадатковая iнфармацыя"</string>
+ <string name="throttle_help" msgid="2624535757028809735">"Даведацца больш"</string>
<string name="throttle_status_subtext" msgid="1110276415078236687">"Выкарыстана <xliff:g id="USED_0">%1$s</xliff:g> (<xliff:g id="USED_1">%2$d</xliff:g>٪) з максімальнага перыяду (<xliff:g id="USED_2">%3$s</xliff:g>)\nНаступны перыяд пачнецца праз <xliff:g id="USED_3">%4$d</xliff:g> сут (<xliff:g id="USED_4">%5$s</xliff:g>)"</string>
<string name="throttle_data_usage_subtext" msgid="3185429653996709840">"Выкарыстана <xliff:g id="USED_0">%1$s</xliff:g> (<xliff:g id="USED_1">%2$d</xliff:g>??) з максімуму перыяду (<xliff:g id="USED_2">%3$s</xliff:g>)"</string>
<string name="throttle_data_rate_reduced_subtext" msgid="8369839346277847725">"Максімум <xliff:g id="USED_0">%1$s</xliff:g> перавышаны\nХуткасць перадачы дадзеных зніжана да <xliff:g id="USED_1">%2$d</xliff:g> Кб/с"</string>
@@ -450,7 +450,7 @@
<string name="sum_fdn_manage_list" msgid="3311397063233992907">"Кіраванне спісам тэлефонных нумароў"</string>
<string name="voice_privacy" msgid="7346935172372181951">"Палiтыка прыватнасцi Voice"</string>
<string name="voice_privacy_summary" msgid="3556460926168473346">"Уключыць пашыраны рэжым прыватнасці"</string>
- <string name="tty_mode_option_title" msgid="3843817710032641703">"Рэжым тэлетайпа"</string>
+ <string name="tty_mode_option_title" msgid="3843817710032641703">"Рэжым TTY"</string>
<string name="tty_mode_option_summary" msgid="4770510287236494371">"Задаць рэжым TTY"</string>
<string name="auto_retry_mode_title" msgid="2985801935424422340">"Аўтаматычны паўтор"</string>
<string name="auto_retry_mode_summary" msgid="2863919925349511402">"Уключыць рэжым аўтаматычнага паўтору"</string>
@@ -594,10 +594,10 @@
<string name="rtt_mode_more_information" msgid="587500128658756318">"Функцыя RTT дапамагае абанентам з парушэннямі слыху і маўлення.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>Даведацца больш</a>\n <br><br> - RTT-выклікі захоўваюцца ў выглядзе расшыфроўкі паведамленняў\n <br> - Функцыя RTT недаступная для відэавыклікаў"</string>
<string name="no_rtt_when_roaming" msgid="5268008247378355389">"Заўвага. Функцыя RTT недаступная ў роўмінгу."</string>
<string-array name="tty_mode_entries">
- <item msgid="3238070884803849303">"Тэлетайп выключаны"</item>
- <item msgid="1449091874731375214">"Поўнафункцыянальны тэлетайп"</item>
- <item msgid="1044179293199519425">"Тэлетайп HCO"</item>
- <item msgid="2131559553795606483">"Тэлетайп VCO"</item>
+ <item msgid="3238070884803849303">"TTY выключаны"</item>
+ <item msgid="1449091874731375214">"Поўнафункцыянальны TTY"</item>
+ <item msgid="1044179293199519425">"TTY з магчымасцю чуць суразмоўніка"</item>
+ <item msgid="2131559553795606483">"TTY з магчымасцю перадачы голасу"</item>
</string-array>
<string name="dtmf_tones_title" msgid="7874845461117175236">"Сігналы DTMF"</string>
<string name="dtmf_tones_summary" msgid="2294822239899471201">"Задаць даўжыню тонаў DTMF"</string>
@@ -881,7 +881,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubID стандартнай SIM-карты для перадачы даных:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Прапускная здольнасць канала спампоўвання (кбіт/с):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Прапускная здольнасць канала запампоўвання (кбіт/с):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Інфармацыя пра месцазнаходжанне сотавай ячэйкі (састарэлая):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Канфігурацыя фізічнага канала LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Частата абнаўлення даных сотавай сеткі:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Усе паказчыкі сотавай сеткі:"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index d35cd0a..4f69827 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Идентификационен подномер на SIM картата за данни по подразбиране:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Пропускателна способност при изтегляне (кб/сек):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Пропускателна способност при качване (кб/сек):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Информация за местоположението на клетката (оттеглено):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Конфигурация на физическия канал на LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Честота на опресняване на информацията за клетките:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Цялата измервателна информация за клетките:"</string>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 76b5d81..893d8a8 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ডিফল্ট ডেটা সিমের SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"ডিএল ব্যান্ডউইথ (কেবিপিএস):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"ইউএল ব্যান্ডউইথ (কেবিপিএস):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"সেল লোকেশন তথ্য (বন্ধ করা হয়েছে):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ফিজিক্যাল চ্যানেল কনফিগারেশন:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"সেল তথ্যে রিফ্রেশ রেট:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"সমস্ত সেল পরিমাপ তথ্য:"</string>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 3bb0e48..286b69d 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -106,7 +106,7 @@
<string name="labelCFU" msgid="8870170873036279706">"Uvijek proslijedi"</string>
<string name="messageCFU" msgid="1361806450979589744">"Uvijek koristi ovaj broj"</string>
<string name="sum_cfu_enabled_indicator" msgid="9030139213402432776">"Prosljeđivanje svih poziva"</string>
- <string name="sum_cfu_enabled" msgid="5806923046528144526">"Preusmjeravaju se svi pozivi na <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
+ <string name="sum_cfu_enabled" msgid="5806923046528144526">"Prosljeđivanje svih poziva na <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfu_enabled_no_number" msgid="7287752761743377930">"Broj je nedostupan"</string>
<string name="sum_cfu_disabled" msgid="5010617134210809853">"Isključeno"</string>
<string name="labelCFB" msgid="615265213360512768">"Kada je zauzeto"</string>
@@ -135,8 +135,8 @@
<string name="call_settings_admin_user_only" msgid="7238947387649986286">"Postavke poziva može promijeniti samo administrator."</string>
<string name="call_settings_with_label" msgid="8460230435361579511">"Postavke (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="error_updating_title" msgid="2024290892676808965">"Greška u postavkama poziva"</string>
- <string name="reading_settings" msgid="1605904432450871183">"Čitanje postavki u toku…"</string>
- <string name="updating_settings" msgid="3650396734816028808">"Ažuriranje postavki u toku…"</string>
+ <string name="reading_settings" msgid="1605904432450871183">"Čitanje postavki…"</string>
+ <string name="updating_settings" msgid="3650396734816028808">"Ažuriranje postavki…"</string>
<string name="reverting_settings" msgid="7378668837291012205">"Vraćanje postavki u toku…"</string>
<string name="response_error" msgid="3904481964024543330">"Neočekivani odgovor mreže."</string>
<string name="exception_error" msgid="330994460090467">"Greška na mreži ili SIM kartici."</string>
@@ -612,7 +612,7 @@
<string name="ota_hfa_activation_title" msgid="3300556778212729671">"Aktivacija u toku..."</string>
<string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"Telefon aktivira uslugu prijenosa mobilnih podataka.\n\nTo može potrajati do 5 minuta."</string>
<string name="ota_skip_activation_dialog_title" msgid="7666611236789203797">"Preskočiti aktivaciju?"</string>
- <string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"Ako preskočite aktivaciju, nećete moći upućivati pozive niti se povezati na mobilne podatkovne mreže (iako se možete povezati na WiFi mreže). Dok ne aktivirate telefon, prikazivat će se upit za aktivaciju svaki put kada upalite telefon."</string>
+ <string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"Ako preskočite aktivaciju, nećete moći upućivati pozive niti se povezati na mobilne podatkovne mreže (iako se možete povezati s WiFi mrežama). Dok ne aktivirate telefon, prikazivat će se upit za aktivaciju svaki put kada upalite telefon."</string>
<string name="ota_skip_activation_dialog_skip_label" msgid="5908029466817825633">"Preskoči"</string>
<string name="ota_activate" msgid="7939695753665438357">"Aktiviraj"</string>
<string name="ota_title_activate_success" msgid="1272135024761004889">"Telefon je aktiviran."</string>
@@ -866,7 +866,7 @@
<string name="radioInfo_data_disconnected" msgid="8085447971880814541">"Veza je prekinuta"</string>
<string name="radioInfo_data_connecting" msgid="925092271092152472">"Povezivanje"</string>
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Povezano"</string>
- <string name="radioInfo_data_suspended" msgid="8695262782642002785">"Suspendirano"</string>
+ <string name="radioInfo_data_suspended" msgid="8695262782642002785">"Obustavljeno"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Nepoznato"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"paketi"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bajtova"</string>
@@ -878,7 +878,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Pomoćni ID za zadani SIM za prijenos podataka:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL propusnost (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL propusnost (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informacije o lokaciji ćelije (zastarjele):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguracija LTE fizičkog kanala:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Interval osvježavanja informacija o ćeliji:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Sve informacije o mjerenju ćelije:"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 73e9fae..e40d4af 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -63,7 +63,7 @@
<string name="labelCdmaMore_with_label" msgid="7759692829160238152">"Configuració de trucades CDMA (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="apn_settings" msgid="1978652203074756623">"Noms dels punts d\'accés"</string>
<string name="settings_label" msgid="9101778088412567956">"Configuració de xarxa"</string>
- <string name="phone_accounts" msgid="1216879437523774604">"Comptes de trucades"</string>
+ <string name="phone_accounts" msgid="1216879437523774604">"Comptes de trucada"</string>
<string name="phone_accounts_make_calls_with" msgid="16747814788918145">"Truca amb"</string>
<string name="phone_accounts_make_sip_calls_with" msgid="4691221006731847255">"Fes trucades SIP amb"</string>
<string name="phone_accounts_ask_every_time" msgid="6192347582666047168">"Pregunta primer"</string>
@@ -96,7 +96,7 @@
<string name="sum_loading_settings" msgid="434063780286688775">"Carregant la configuració..."</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"Número amagat en trucades sortints"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"Número mostrat a les trucades de sortida"</string>
- <string name="sum_default_caller_id" msgid="1767070797135682959">"Utilitza la configuració predeterminada de l\'operador per mostrar el meu número a les trucades de sortida"</string>
+ <string name="sum_default_caller_id" msgid="1767070797135682959">"Utilitza la configuració predeterminada de l\'operador per mostrar el meu número a les trucades sortints"</string>
<string name="labelCW" msgid="8449327023861428622">"Trucada en espera"</string>
<string name="sum_cw_enabled" msgid="3977308526187139996">"Durant una trucada, avisa\'m de les trucades entrants"</string>
<string name="sum_cw_disabled" msgid="3658094589461768637">"Durant una trucada, avisa\'m de les trucades entrants"</string>
@@ -591,7 +591,7 @@
<string name="hac_mode_summary" msgid="7774989500136009881">"Activa la compatibilitat amb audiòfons"</string>
<string name="rtt_mode_title" msgid="3075948111362818043">"Trucada de text en temps real (RTT)"</string>
<string name="rtt_mode_summary" msgid="8631541375609989562">"Permet l\'ús de missatges en una trucada de veu"</string>
- <string name="rtt_mode_more_information" msgid="587500128658756318">"La funció RTT ofereix assistència als usuaris que són sords, tenen problemes d\'audició o alteracions de la parla, o bé que necessiten un text a banda de la veu.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>Més informació</a>\n <br><br> - Les trucades RTT es desen en forma de transcripció.\n <br> - Aquesta funció no està disponible per a videotrucades."</string>
+ <string name="rtt_mode_more_information" msgid="587500128658756318">"La funció RTT ofereix assistència als usuaris que són sords, tenen deficiències auditives o alteracions de la parla, o bé que necessiten un text a banda de la veu.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>Més informació</a>\n <br><br> - Les trucades RTT es desen en forma de transcripció.\n <br> - Aquesta funció no està disponible per a videotrucades."</string>
<string name="no_rtt_when_roaming" msgid="5268008247378355389">"Nota: la funció RTT no està disponible en itinerància"</string>
<string-array name="tty_mode_entries">
<item msgid="3238070884803849303">"TTY desactivat"</item>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Subidentificador de la SIM de dades predeterminada:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Amplada de banda de baixada (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Amplada de banda de pujada (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informació d\'ubicació del mòbil (obsoleta):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuració del canal físic de LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Freqüència d\'actualització de la informació del mòbil:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Tota la informació de mesures del mòbil:"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 9b151b3..3bddac6 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -149,7 +149,7 @@
<string name="close_dialog" msgid="1074977476136119408">"OK"</string>
<string name="enable" msgid="2636552299455477603">"Zapnout"</string>
<string name="disable" msgid="1122698860799462116">"Vypnout"</string>
- <string name="change_num" msgid="6982164494063109334">"Aktualiz."</string>
+ <string name="change_num" msgid="6982164494063109334">"Aktualizovat"</string>
<string-array name="clir_display_values">
<item msgid="8477364191403806960">"Výchozí nastavení sítě"</item>
<item msgid="6813323051965618926">"Skrýt číslo"</item>
@@ -881,7 +881,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId výchozí datové SIM karty:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Rychlost stahování (kB/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Rychlost nahrávání (kB/s):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informace o poloze mobilní sítě (podpora ukončena):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurace fyzického kanálu LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Interval obnovení informací o mobilní síti:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Všechny údaje o měření mobilní sítě:"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index a4167a7..a57b744 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -578,7 +578,7 @@
<string name="onscreenMergeCallsText" msgid="3692389519611225407">"Slå opkald sammen"</string>
<string name="onscreenSwapCallsText" msgid="2682542150803377991">"Skift"</string>
<string name="onscreenManageCallsText" msgid="1162047856081836469">"Administrer opkald"</string>
- <string name="onscreenManageConferenceText" msgid="4700574060601755137">"Admin. konference"</string>
+ <string name="onscreenManageConferenceText" msgid="4700574060601755137">"Admin. møde"</string>
<string name="onscreenAudioText" msgid="7224226735052019986">"Lyd"</string>
<string name="onscreenVideoCallText" msgid="1743992456126258698">"Videoopkald"</string>
<string name="importSimEntry" msgid="3892354284082689894">"Importer"</string>
@@ -812,7 +812,7 @@
<string name="supp_service_additional_call_forwarded" msgid="8772753260008398632">"Det andet opkald er videresendt."</string>
<string name="supp_service_additional_ect_connected" msgid="8525934162945220237">"Opkaldet blev tilsluttet ECT."</string>
<string name="supp_service_additional_ect_connecting" msgid="7046240728781222753">"Opkaldet tilsluttes ECT."</string>
- <string name="supp_service_call_on_hold" msgid="2836811319594503059">"Parkeret opkald."</string>
+ <string name="supp_service_call_on_hold" msgid="2836811319594503059">"Opkald på hold."</string>
<string name="supp_service_call_resumed" msgid="3786864005920743546">"Opkaldet er genoptaget."</string>
<string name="supp_service_deflected_call" msgid="7565979024562921707">"Opkaldet blev viderestillet."</string>
<string name="supp_service_forwarded_call" msgid="6475776013771821457">"Videresendt opkald."</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Under-id for standard-SIM-kort til data:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Båndbredde til download (kB/sek.):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Båndbredde til upload (kB/sek.):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Oplysning om placering af celle (udfaset):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Fysisk kanalkonfiguration for LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Opdateringsfrekvens for celleoplysninger:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Alle oplysninger om cellemåling:"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 7b45d81..09d5143 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Unter-ID der standardmäßigen Daten-SIM:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL-Bandbreite (kbit/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL-Bandbreite (kbit/s):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Standortinformationen des Mobiltelefons (eingestellt):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguration des physischen LTE-Kanals:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Aktualisierungsrate der Mobiltelefoninformationen:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Alle Informationen zu Zellenmesswerten:"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 1eb71c9..d7f72bb 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -50,8 +50,7 @@
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Οι ρυθμίσεις αυτόματου τηλεφωνητή μπορούν να αλλάξουν μόνο από τον κύριο χρήστη."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"Καταργήθηκε ο αποκλεισμός της κάρτας SIM. Το τηλέφωνό σας ξεκλειδώνεται..."</string>
<string name="label_ndp" msgid="7617392683877410341">"Αριθμός PIN ξεκλειδώματος δικτύου κάρτας SIM"</string>
- <!-- no translation found for label_phoneid (8775611434123577808) -->
- <skip />
+ <string name="label_phoneid" msgid="8775611434123577808">"Η κάρτα SIM κλειδώθηκε για τον πάροχο"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Ξεκλείδωμα"</string>
<string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Παράβλεψη"</string>
<string name="requesting_unlock" msgid="930512210309437741">"Αίτηση ξεκλειδώματος δικτύου..."</string>
@@ -876,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId προεπιλεγμένης SIM δεδομένων:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Εύρος ζώνης DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Εύρος ζώνης UL (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Πληροφορίες τοποθεσίας κινητής τηλεφωνίας (καταργήθηκε):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Διαμόρφωση φυσικού καναλιού LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Ρυθμός ανανέωσης στοιχείων κινητής τηλεφωνίας:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Όλα τα στοιχεία μετρήσεων κινητής τηλεφωνίας:"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index f9826ed..146f292 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -75,7 +75,7 @@
<string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"Configure account settings"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"All calling accounts"</string>
<string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"Select which accounts can make calls"</string>
- <string name="wifi_calling" msgid="3650509202851355742">"Wi-Fi Calling"</string>
+ <string name="wifi_calling" msgid="3650509202851355742">"Wi-Fi calling"</string>
<string name="connection_service_default_label" msgid="7332739049855715584">"Built-in connection service"</string>
<string name="voicemail" msgid="7697769412804195032">"Voicemail"</string>
<string name="voicemail_settings_with_label" msgid="4228431668214894138">"Voicemail (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId of default data SIM:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL bandwidth (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL bandwidth (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Mobile location info (deprecated):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE physical channel configuration:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobile info refresh rate:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All mobile measurement info:"</string>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index 0112853..fa87216 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -75,7 +75,7 @@
<string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"Configure account settings"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"All calling accounts"</string>
<string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"Select which accounts can make calls"</string>
- <string name="wifi_calling" msgid="3650509202851355742">"Wi-Fi Calling"</string>
+ <string name="wifi_calling" msgid="3650509202851355742">"Wi-Fi calling"</string>
<string name="connection_service_default_label" msgid="7332739049855715584">"Built-in connection service"</string>
<string name="voicemail" msgid="7697769412804195032">"Voicemail"</string>
<string name="voicemail_settings_with_label" msgid="4228431668214894138">"Voicemail (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -479,7 +479,7 @@
<string name="simContacts_emptyLoading" msgid="4989040293858675483">"Reading from SIM card…"</string>
<string name="simContacts_empty" msgid="1135632055473689521">"No contacts on your SIM card."</string>
<string name="simContacts_title" msgid="2714029230160136647">"Select contacts to import"</string>
- <string name="simContacts_airplaneMode" msgid="4654884030631503808">"Turn off aeroplane mode to import contacts from the SIM card."</string>
+ <string name="simContacts_airplaneMode" msgid="4654884030631503808">"Turn off Airplane mode to import contacts from the SIM card."</string>
<string name="enable_pin" msgid="967674051730845376">"Enable/disable SIM PIN"</string>
<string name="change_pin" msgid="3657869530942905790">"Change SIM PIN"</string>
<string name="enter_pin_text" msgid="3182311451978663356">"SIM PIN:"</string>
@@ -531,8 +531,8 @@
<string name="notification_network_selection_title" msgid="255595526707809121">"No service"</string>
<string name="notification_network_selection_text" msgid="553288408722427659">"Selected network<xliff:g id="OPERATOR_NAME">%s</xliff:g> unavailable"</string>
<string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"Turn on mobile network, turn off airplane mode or turn off battery saver mode to make a call."</string>
- <string name="incall_error_power_off" product="default" msgid="8131672264311208673">"Turn off aeroplane mode to make a call."</string>
- <string name="incall_error_power_off_wfc" msgid="9125661184694727052">"Turn off aeroplane mode or connect to a wireless network to make a call."</string>
+ <string name="incall_error_power_off" product="default" msgid="8131672264311208673">"Turn off Airplane mode to make a call."</string>
+ <string name="incall_error_power_off_wfc" msgid="9125661184694727052">"Turn off Airplane mode or connect to a wireless network to make a call."</string>
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Exit emergency callback mode to make a non-emergency call."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Not registered on network."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobile network not available."</string>
@@ -560,7 +560,7 @@
<string name="emergency_call_shortcut_hint" msgid="1290485125107779500">"Tap again to call <xliff:g id="EMERGENCY_NUMBER">%s</xliff:g>"</string>
<string name="emergency_enable_radio_dialog_message" msgid="1695305158151408629">"Turning on radio…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="4329131876852608587">"No service. Trying again…"</string>
- <string name="radio_off_during_emergency_call" msgid="8011154134040481609">"Cannot enter aeroplane mode during an emergency call."</string>
+ <string name="radio_off_during_emergency_call" msgid="8011154134040481609">"Cannot enter Airplane mode during an emergency call."</string>
<string name="dial_emergency_error" msgid="825822413209026039">"Can\'t call. <xliff:g id="NON_EMERGENCY_NUMBER">%s</xliff:g> is not an emergency number."</string>
<string name="dial_emergency_empty_error" msgid="2785803395047793634">"Can\'t call. Dial an emergency number."</string>
<string name="dial_emergency_calling_not_available" msgid="6485846193794727823">"Emergency calling not available"</string>
@@ -715,7 +715,7 @@
<string name="mobile_data_activate_button" msgid="1139792516354374612">"ADD DATA"</string>
<string name="mobile_data_activate_cancel_button" msgid="3530174817572005860">"CANCEL"</string>
<string name="clh_card_title_call_ended_txt" msgid="5977978317527299698">"Call ended"</string>
- <string name="clh_callFailed_powerOff_txt" msgid="8279934912560765361">"Aeroplane mode is on"</string>
+ <string name="clh_callFailed_powerOff_txt" msgid="8279934912560765361">"Airplane mode is on"</string>
<string name="clh_callFailed_simError_txt" msgid="5128538525762326413">"Can\'t access SIM card"</string>
<string name="clh_incall_error_out_of_service_txt" msgid="2736010617446749869">"Mobile network not available"</string>
<string name="clh_callFailed_unassigned_number_txt" msgid="141967660286695682">"Issue with phone number you are trying to dial. Error code 1."</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId of default data SIM:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL bandwidth (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL bandwidth (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Mobile location info (deprecated):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE physical channel configuration:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobile info refresh rate:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All mobile measurement info:"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index f9826ed..146f292 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -75,7 +75,7 @@
<string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"Configure account settings"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"All calling accounts"</string>
<string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"Select which accounts can make calls"</string>
- <string name="wifi_calling" msgid="3650509202851355742">"Wi-Fi Calling"</string>
+ <string name="wifi_calling" msgid="3650509202851355742">"Wi-Fi calling"</string>
<string name="connection_service_default_label" msgid="7332739049855715584">"Built-in connection service"</string>
<string name="voicemail" msgid="7697769412804195032">"Voicemail"</string>
<string name="voicemail_settings_with_label" msgid="4228431668214894138">"Voicemail (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId of default data SIM:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL bandwidth (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL bandwidth (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Mobile location info (deprecated):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE physical channel configuration:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobile info refresh rate:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All mobile measurement info:"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index f9826ed..146f292 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -75,7 +75,7 @@
<string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"Configure account settings"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"All calling accounts"</string>
<string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"Select which accounts can make calls"</string>
- <string name="wifi_calling" msgid="3650509202851355742">"Wi-Fi Calling"</string>
+ <string name="wifi_calling" msgid="3650509202851355742">"Wi-Fi calling"</string>
<string name="connection_service_default_label" msgid="7332739049855715584">"Built-in connection service"</string>
<string name="voicemail" msgid="7697769412804195032">"Voicemail"</string>
<string name="voicemail_settings_with_label" msgid="4228431668214894138">"Voicemail (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId of default data SIM:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL bandwidth (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL bandwidth (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Mobile location info (deprecated):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE physical channel configuration:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobile info refresh rate:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All mobile measurement info:"</string>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index b9ac0e2..beff7ad 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId of default data SIM:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL Bandwidth (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL Bandwidth (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Cell Location Info (deprecated):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE Physical Channel Configuration:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Cell Info Refresh Rate:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All Cell Measurement Info:"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 9b78c53..406ce56 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -50,8 +50,7 @@
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Solo el usuario principal puede cambiar la configuración del buzón de voz."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"Tu tarjeta SIM ha sido desbloqueada. Tu dispositivo está desbloqueando..."</string>
<string name="label_ndp" msgid="7617392683877410341">"PIN de desbloqueo de red de tarjeta SIM"</string>
- <!-- no translation found for label_phoneid (8775611434123577808) -->
- <skip />
+ <string name="label_phoneid" msgid="8775611434123577808">"SIM bloqueada para el operador"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Desbloquear"</string>
<string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Descartar"</string>
<string name="requesting_unlock" msgid="930512210309437741">"Solicitando desbloqueo de red..."</string>
@@ -97,7 +96,7 @@
<string name="sum_loading_settings" msgid="434063780286688775">"Cargando la configuración…"</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"Número escondido en llamadas salientes"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"Número visualizado en llamadas salientes"</string>
- <string name="sum_default_caller_id" msgid="1767070797135682959">"Utilizar configuración del operador predeterminada para visualizar mi número en las llamadas salientes"</string>
+ <string name="sum_default_caller_id" msgid="1767070797135682959">"Utilizar configuración predeterminada del operador para visualizar mi número en las llamadas salientes"</string>
<string name="labelCW" msgid="8449327023861428622">"Llamada en espera"</string>
<string name="sum_cw_enabled" msgid="3977308526187139996">"Durante una llamada, notificarme sobre las llamadas entrantes"</string>
<string name="sum_cw_disabled" msgid="3658094589461768637">"Durante una llamada, notificarme sobre las llamadas entrantes"</string>
@@ -876,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ID secundario de SIM de datos predeterminada:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Ancho de banda de descarga (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Ancho de banda de carga (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Datos de ubicación del celular (obsoleto):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuración del canal físico de LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frecuencia de actualización de datos del celular:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Información sobre las dimensiones del celular:"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 841003f..49cea79 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -43,7 +43,7 @@
<string name="send_button" msgid="5070379600779031932">"Enviar"</string>
<string name="pause_prompt_yes" msgid="8184132073048369575">"Sí"</string>
<string name="pause_prompt_no" msgid="2145264674774138579">"No"</string>
- <string name="wild_prompt_str" msgid="5858910969703305375">"Sustituir el carácter comodín por"</string>
+ <string name="wild_prompt_str" msgid="5858910969703305375">"Reemplazar el carácter comodín por"</string>
<string name="no_vm_number" msgid="6623853880546176930">"Falta el número del buzón de voz."</string>
<string name="no_vm_number_msg" msgid="5165161462411372504">"No se ha almacenado ningún número de buzón de voz en la tarjeta SIM."</string>
<string name="add_vm_number_str" msgid="7368168964435881637">"Añadir número"</string>
@@ -63,7 +63,7 @@
<string name="labelCdmaMore_with_label" msgid="7759692829160238152">"Ajustes de llamada de CDMA (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="apn_settings" msgid="1978652203074756623">"Nombres de puntos de acceso"</string>
<string name="settings_label" msgid="9101778088412567956">"Ajustes de red"</string>
- <string name="phone_accounts" msgid="1216879437523774604">"Cuentas de llamadas"</string>
+ <string name="phone_accounts" msgid="1216879437523774604">"Cuentas de llamada"</string>
<string name="phone_accounts_make_calls_with" msgid="16747814788918145">"Realizar llamadas con"</string>
<string name="phone_accounts_make_sip_calls_with" msgid="4691221006731847255">"Realizar llamadas SIP con"</string>
<string name="phone_accounts_ask_every_time" msgid="6192347582666047168">"Preguntar primero"</string>
@@ -192,7 +192,7 @@
<string name="forbidden_network" msgid="5081729819561333023">"(prohibida)"</string>
<string name="choose_network_title" msgid="5335832663422653082">"Elegir red"</string>
<string name="network_disconnected" msgid="8844141106841160825">"Desconectado"</string>
- <string name="network_connected" msgid="2760235679963580224">"Conectada"</string>
+ <string name="network_connected" msgid="2760235679963580224">"Conectado"</string>
<string name="network_connecting" msgid="160901383582774987">"Conectando..."</string>
<string name="network_could_not_connect" msgid="6547460848093727998">"No se ha podido conectar"</string>
<string-array name="preferred_network_mode_choices">
@@ -625,7 +625,7 @@
<string name="ota_unsuccessful" msgid="8531037653803955754">"El teléfono no se ha activado. \nEs posible que tengas que situarte en una zona con más cobertura (cerca de una ventana o en el exterior). \n\nInténtalo de nuevo o ponte en contacto con el servicio de atención al cliente para consultar otras opciones."</string>
<string name="ota_spc_failure" msgid="904092035241370080">"EXCESO DE ERRORES DE SPC"</string>
<string name="ota_call_end" msgid="8657746378290737034">"Atrás"</string>
- <string name="ota_try_again" msgid="6914781945599998550">"Volver a intentarlo"</string>
+ <string name="ota_try_again" msgid="6914781945599998550">"Reintentar"</string>
<string name="ota_next" msgid="2041016619313475914">"Siguiente"</string>
<string name="ecm_exit_dialog" msgid="4200691880721429078">"EcmExitDialog"</string>
<string name="phone_entered_ecm_text" msgid="8431238297843035842">"Se ha activado el modo de devolución de llamada de emergencia."</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ID secundario de la SIM de datos predeterminada:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Ancho de banda de bajada (Kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Ancho de banda de subida (Kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Información sobre la ubicación del teléfono (obsoleto):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuración del canal físico de LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frecuencia de actualización de la información del teléfono:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Información sobre las dimensiones de los teléfonos:"</string>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index fcd6b77..21c637e 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Andmete vaike-SIM-kaardi alam-ID:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL-i ribalaius (kbit/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL-i ribalaius (kbit/s):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Kärje asukohateave (tugi on katkestatud):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE füüsilise kanali konfiguratsioon:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Kärje teabe värskendamissagedus:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Kõik kärje mõõteandmed:"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 936dfd0..6b0678d 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -75,7 +75,7 @@
<string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"Konfiguratu kontuaren ezarpenak"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"Deiak egiteko kontu guztiak"</string>
<string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"Hautatu zein kontutatik egin daitezkeen deiak"</string>
- <string name="wifi_calling" msgid="3650509202851355742">"Wi-Fi bidezko deiak"</string>
+ <string name="wifi_calling" msgid="3650509202851355742">"Wifi bidezko deiak"</string>
<string name="connection_service_default_label" msgid="7332739049855715584">"Konektatzeko zerbitzu integratua"</string>
<string name="voicemail" msgid="7697769412804195032">"Erantzungailua"</string>
<string name="voicemail_settings_with_label" msgid="4228431668214894138">"Erantzungailua (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -96,32 +96,32 @@
<string name="sum_loading_settings" msgid="434063780286688775">"Ezarpenak kargatzen…"</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"Ezkutatu zenbakia irteerako deietan"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"Erakutsi zenbakia irteerako deietan"</string>
- <string name="sum_default_caller_id" msgid="1767070797135682959">"Erabili operadorearen ezarpen lehenetsiak irteerako deietan nire zenbakia erakusteko"</string>
+ <string name="sum_default_caller_id" msgid="1767070797135682959">"Erabili operadorearen ezarpen lehenetsiak, egiten ditudan deietan nire zenbakia erakusteko"</string>
<string name="labelCW" msgid="8449327023861428622">"Deiak zain"</string>
- <string name="sum_cw_enabled" msgid="3977308526187139996">"Deiak abian dauden bitartean, eman sarrerako deien berri"</string>
- <string name="sum_cw_disabled" msgid="3658094589461768637">"Deiak abian dauden bitartean, eman sarrerako deien berri"</string>
+ <string name="sum_cw_enabled" msgid="3977308526187139996">"Deiak abian dauden bitartean, eman jasotzen ditudan deien berri"</string>
+ <string name="sum_cw_disabled" msgid="3658094589461768637">"Deiak abian dauden bitartean, eman jasotzen ditudan deien berri"</string>
<string name="call_forwarding_settings" msgid="8937130467468257671">"Dei-desbideratzearen ezarpenak"</string>
<string name="call_forwarding_settings_with_label" msgid="2345432813399564272">"Deiak desbideratzeko ezarpenak (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="labelCF" msgid="3578719437928476078">"Dei-desbideratzea"</string>
<string name="labelCFU" msgid="8870170873036279706">"Desbideratu beti"</string>
<string name="messageCFU" msgid="1361806450979589744">"Erabili beti zenbaki hau"</string>
<string name="sum_cfu_enabled_indicator" msgid="9030139213402432776">"Dei guztiak desbideratzen"</string>
- <string name="sum_cfu_enabled" msgid="5806923046528144526">"Dei guztiak <xliff:g id="PHONENUMBER">{0}</xliff:g> zenbakira desbideratzen"</string>
+ <string name="sum_cfu_enabled" msgid="5806923046528144526">"Dei guztiak <xliff:g id="PHONENUMBER">{0}</xliff:g> zenbakira desbideratzen dira"</string>
<string name="sum_cfu_enabled_no_number" msgid="7287752761743377930">"Zenbakia ez dago eskuragarri"</string>
<string name="sum_cfu_disabled" msgid="5010617134210809853">"Desaktibatuta"</string>
<string name="labelCFB" msgid="615265213360512768">"Okupatuta nagoenean"</string>
<string name="messageCFB" msgid="1958017270393563388">"Okupatuta dagoenerako zenbakia"</string>
- <string name="sum_cfb_enabled" msgid="332037613072049492">"<xliff:g id="PHONENUMBER">{0}</xliff:g> zenbakira desbideratzen"</string>
+ <string name="sum_cfb_enabled" msgid="332037613072049492">"<xliff:g id="PHONENUMBER">{0}</xliff:g> zenbakira desbideratzen dira"</string>
<string name="sum_cfb_disabled" msgid="3589913334164866035">"Desaktibatuta"</string>
<string name="disable_cfb_forbidden" msgid="4831494744351633961">"Operadoreak ez du dei-desbideratzeak desgaitzea onartzen telefonoa okupatuta dagoen bitartean."</string>
<string name="labelCFNRy" msgid="3403533792248457946">"Erantzuten ez dudanean"</string>
<string name="messageCFNRy" msgid="7644434155765359009">"Erantzunik jasotzen ez denerako zenbakia"</string>
- <string name="sum_cfnry_enabled" msgid="3000500837493854799">"<xliff:g id="PHONENUMBER">{0}</xliff:g> zenbakira desbideratzen"</string>
+ <string name="sum_cfnry_enabled" msgid="3000500837493854799">"<xliff:g id="PHONENUMBER">{0}</xliff:g> zenbakira desbideratzen dira"</string>
<string name="sum_cfnry_disabled" msgid="1990563512406017880">"Desaktibatuta"</string>
<string name="disable_cfnry_forbidden" msgid="3174731413216550689">"Operadoreak ez du dei-desbideratzeak desgaitzea onartzen telefonoak erantzuten ez duenean."</string>
- <string name="labelCFNRc" msgid="4163399350778066013">"Konektatu gabe nagoenean"</string>
+ <string name="labelCFNRc" msgid="4163399350778066013">"Telefonoa itzalita edo estalduratik at dagoenean"</string>
<string name="messageCFNRc" msgid="6980340731313007250">"Eskuragarri ez dagoenerako zenbakia"</string>
- <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"<xliff:g id="PHONENUMBER">{0}</xliff:g> zenbakira desbideratzen"</string>
+ <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"<xliff:g id="PHONENUMBER">{0}</xliff:g> zenbakira desbideratzen dira"</string>
<string name="sum_cfnrc_disabled" msgid="739289696796917683">"Desaktibatuta"</string>
<string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Operadoreak ez du dei-desbideratzeak desgaitzea onartzen telefonoa eskuragarri ez dagoen bitartean."</string>
<string name="registration_cf_forbidden" msgid="4386482610771190420">"Operadoreak ez du onartzen dei-desbideratzea."</string>
@@ -306,7 +306,7 @@
<string name="sim_selection_required_pref" msgid="6985901872978341314">"Hautatu egin behar da"</string>
<string name="sim_change_data_title" msgid="9142726786345906606">"Datuetarako SIMa aldatu nahi duzu?"</string>
<string name="sim_change_data_message" msgid="3567358694255933280">"Datu-konexiorako, <xliff:g id="NEW_SIM">%1$s</xliff:g> txartela erabili nahi duzu <xliff:g id="OLD_SIM">%2$s</xliff:g> txartelaren ordez?"</string>
- <string name="wifi_calling_settings_title" msgid="5800018845662016507">"Wi-Fi bidezko deiak"</string>
+ <string name="wifi_calling_settings_title" msgid="5800018845662016507">"Wifi bidezko deiak"</string>
<string name="video_calling_settings_title" msgid="342829454913266078">"Operadorearen bideo-deiak"</string>
<string name="gsm_umts_options" msgid="4968446771519376808">"GSM/UMTS aukerak"</string>
<string name="cdma_options" msgid="3669592472226145665">"CDMA aukerak"</string>
@@ -574,7 +574,7 @@
<string name="onscreenEndCallText" msgid="6138725377654842757">"Amaitu"</string>
<string name="onscreenShowDialpadText" msgid="658465753816164079">"Markagailua"</string>
<string name="onscreenMuteText" msgid="5470306116733843621">"Desaktibatu audioa"</string>
- <string name="onscreenAddCallText" msgid="9075675082903611677">"Gehitu deia"</string>
+ <string name="onscreenAddCallText" msgid="9075675082903611677">"Gehitu dei bat"</string>
<string name="onscreenMergeCallsText" msgid="3692389519611225407">"Bateratu deiak"</string>
<string name="onscreenSwapCallsText" msgid="2682542150803377991">"Trukatu"</string>
<string name="onscreenManageCallsText" msgid="1162047856081836469">"Kudeatu deiak"</string>
@@ -622,7 +622,7 @@
<string name="ota_progress" msgid="8837259285255700132">"Telefonoa programatzen…"</string>
<string name="ota_failure" msgid="5674217489921481576">"Ezin izan da programatu telefonoa"</string>
<string name="ota_successful" msgid="1106825981548107774">"Telefonoa aktibatu egin da. Zerbitzua hasteko 15 minutu ere behar izan daitezke."</string>
- <string name="ota_unsuccessful" msgid="8531037653803955754">"Ez duzu telefonoa aktibatu.\nBaliteke estaldura gehiago duen eremu bat aurkitu behar izatea (leiho baten ondoan edo kanpoan).\n\nSaiatu berriro edo, aukera gehiago ezagutzeko, deitu bezeroarentzako zerbitzura."</string>
+ <string name="ota_unsuccessful" msgid="8531037653803955754">"Ez duzu telefonoa aktibatu.\nBaliteke estaldura gehiago duen eremu bat aurkitu behar izatea (leiho baten ondoan edo kanpoan).\n\nSaiatu berriro edo, aukera gehiago ezagutzeko, deitu bezeroarentzako laguntza-zerbitzura."</string>
<string name="ota_spc_failure" msgid="904092035241370080">"SPC HUTSEGITE GEHIEGI"</string>
<string name="ota_call_end" msgid="8657746378290737034">"Atzera"</string>
<string name="ota_try_again" msgid="6914781945599998550">"Saiatu berriro"</string>
@@ -683,7 +683,7 @@
<string name="callFailed_cdma_activation" msgid="5392057031552253550">"SIM txartel batek zerbitzua aktibatu du eta telefonoaren ibiltaritza-gaitasunak eguneratu ditu."</string>
<string name="callFailed_cdma_call_limit" msgid="1074219746093031412">"Dei gehiegi daude aktibo. Amaitu edo bateratu abian diren deiak beste bat egin aurretik."</string>
<string name="callFailed_imei_not_accepted" msgid="7257903653685147251">"Ezin da konektatu. Erabili balio duen SIM txartel bat."</string>
- <string name="callFailed_wifi_lost" msgid="1788036730589163141">"Galdu egin da wifi bidezko konexioa. Amaitu da deia."</string>
+ <string name="callFailed_wifi_lost" msgid="1788036730589163141">"Galdu egin da wifi-konexioa. Amaitu da deia."</string>
<string name="dialFailed_low_battery" msgid="6857904237423407056">"Ezin da egin deia, bateria gutxi gelditzen delako."</string>
<string name="callFailed_low_battery" msgid="4056828320214416182">"Bideo-deia amaitu egin da bateria gutxi gelditzen delako."</string>
<string name="callFailed_emergency_call_over_wfc_not_available" msgid="5944309590693432042">"Ez daude erabilgarri wifi bidezko larrialdi-deiak kokapen honetan."</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Datu-konexioetarako SIM lehenetsiaren azpiIDa:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Deskargatzeko banda-zabalera (Kb/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Kargen banda-zabalera (Kb/s):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Sare mugikorraren kokapenaren informazioa (zaharkitua):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE kanal fisikoaren konfigurazioa:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Sare mugikorraren informazioa eguneratzeko maiztasuna:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Sare mugikorraren neurketa guztien informazioa:"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index d605014..daa3eab 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -143,7 +143,7 @@
<string name="stk_cc_ss_to_dial_error" msgid="5147693491690618704">"درخواست SS به تماس معمولی تغییر کرد"</string>
<string name="stk_cc_ss_to_ussd_error" msgid="8330749347425752192">"درخواست SS بهدرخواست USSD تغییر کرد"</string>
<string name="stk_cc_ss_to_ss_error" msgid="8297155544652134278">"بهدرخواست SS جدید تغییر کرد"</string>
- <string name="stk_cc_ss_to_dial_video_error" msgid="4255261231466032505">"درخواست SS به تماس ویدیویی تغییر کرد"</string>
+ <string name="stk_cc_ss_to_dial_video_error" msgid="4255261231466032505">"درخواست SS به تماس تصویری تغییر کرد"</string>
<string name="fdn_check_failure" msgid="1833769746374185247">"تنظیم اعداد شمارهگیری ثابت برنامههای تلفن شما غیرفعال است. درنتیجه، برخی از ویژگیهای مربوط به تماس کار نمیکند."</string>
<string name="radio_off_error" msgid="8321564164914232181">"قبل از مشاهدهٔ این تنظیمات، رادیو را روشن کنید."</string>
<string name="close_dialog" msgid="1074977476136119408">"تأیید"</string>
@@ -307,7 +307,7 @@
<string name="sim_change_data_title" msgid="9142726786345906606">"سیمکارت داده تغییر کند؟"</string>
<string name="sim_change_data_message" msgid="3567358694255933280">"برای داده تلفن همراه، از <xliff:g id="NEW_SIM">%1$s</xliff:g> بهجای <xliff:g id="OLD_SIM">%2$s</xliff:g> استفاده شود؟"</string>
<string name="wifi_calling_settings_title" msgid="5800018845662016507">"تماس ازطریق Wi-Fi"</string>
- <string name="video_calling_settings_title" msgid="342829454913266078">"تماس ویدیویی با شرکت مخابراتی"</string>
+ <string name="video_calling_settings_title" msgid="342829454913266078">"تماس تصویری با شرکت مخابراتی"</string>
<string name="gsm_umts_options" msgid="4968446771519376808">"گزینههای GSM/UMTS"</string>
<string name="cdma_options" msgid="3669592472226145665">"گزینههای CDMA"</string>
<string name="throttle_data_usage" msgid="1944145350660420711">"مصرف داده"</string>
@@ -448,13 +448,13 @@
<string name="sum_fdn" msgid="6152246141642323582">"مدیریت شمارههای شمارهگیری ثابت"</string>
<string name="sum_fdn_change_pin" msgid="3510994280557335727">"تغییر پین برای دسترسی FDN"</string>
<string name="sum_fdn_manage_list" msgid="3311397063233992907">"مدیریت فهرست شماره تلفن"</string>
- <string name="voice_privacy" msgid="7346935172372181951">"حریم خصوصی صوتی"</string>
+ <string name="voice_privacy" msgid="7346935172372181951">"حریمخصوصی صوتی"</string>
<string name="voice_privacy_summary" msgid="3556460926168473346">"فعال کردن حالت رازداری پیشرفته"</string>
<string name="tty_mode_option_title" msgid="3843817710032641703">"حالت TTY"</string>
<string name="tty_mode_option_summary" msgid="4770510287236494371">"تنظیم حالت TTY"</string>
<string name="auto_retry_mode_title" msgid="2985801935424422340">"سعی مجدد خودکار"</string>
<string name="auto_retry_mode_summary" msgid="2863919925349511402">"فعال کردن حالت سعی مجدد خودکار"</string>
- <string name="tty_mode_not_allowed_video_call" msgid="6551976083652752815">"تغییر حالت TTY در طول تماس ویدئویی مجاز نیست"</string>
+ <string name="tty_mode_not_allowed_video_call" msgid="6551976083652752815">"تغییر حالت TTY در طول تماس تصویری مجاز نیست"</string>
<string name="menu_add" msgid="5616487894975773141">"افزودن مخاطب"</string>
<string name="menu_edit" msgid="3593856941552460706">"ویرایش مخاطب"</string>
<string name="menu_delete" msgid="6326861853830546488">"حذف مخاطب"</string>
@@ -580,7 +580,7 @@
<string name="onscreenManageCallsText" msgid="1162047856081836469">"مدیریت تماسها"</string>
<string name="onscreenManageConferenceText" msgid="4700574060601755137">"مدیریت کنفرانس"</string>
<string name="onscreenAudioText" msgid="7224226735052019986">"صوتی"</string>
- <string name="onscreenVideoCallText" msgid="1743992456126258698">"تماس ویدئویی"</string>
+ <string name="onscreenVideoCallText" msgid="1743992456126258698">"تماس تصویری"</string>
<string name="importSimEntry" msgid="3892354284082689894">"وارد کردن"</string>
<string name="importAllSimEntries" msgid="2628391505643564007">"وارد کردن همه"</string>
<string name="importingSimContacts" msgid="4995457122107888932">"وارد کردن مخاطبین سیم"</string>
@@ -668,8 +668,8 @@
<string name="voicemail_change_pin_dialog_title" msgid="4633077715231764435">"تغییر پین"</string>
<string name="preference_category_ringtone" msgid="8787281191375434976">"آهنگ زنگ و لرزش"</string>
<string name="pstn_connection_service_label" msgid="9200102709997537069">"سیمکارتهای داخلی"</string>
- <string name="enable_video_calling_title" msgid="7246600931634161830">"روشن کردن تماس ویدئویی"</string>
- <string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"برای روشن کردن تماس ویدئویی، باید حالت پیشرفته 4G LTE را در تنظیمات شبکه فعال کنید."</string>
+ <string name="enable_video_calling_title" msgid="7246600931634161830">"روشن کردن تماس تصویری"</string>
+ <string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"برای روشن کردن تماس تصویری، باید حالت پیشرفته 4G LTE را در تنظیمات شبکه فعال کنید."</string>
<string name="enable_video_calling_dialog_settings" msgid="8697890611305307110">"تنظیمات شبکه"</string>
<string name="enable_video_calling_dialog_close" msgid="4298929725917045270">"بستن"</string>
<string name="sim_label_emergency_calls" msgid="9078241989421522310">"تماسهای اضطراری"</string>
@@ -685,7 +685,7 @@
<string name="callFailed_imei_not_accepted" msgid="7257903653685147251">"مرتبط نشد، لطفاً سیم کارت معتبری را وارد کنید."</string>
<string name="callFailed_wifi_lost" msgid="1788036730589163141">"اتصال وایفای قطع شد. تماس پایان یافت."</string>
<string name="dialFailed_low_battery" msgid="6857904237423407056">"به دلیل شارژ کم باتری، نمیتوان تماسی برقرار کرد."</string>
- <string name="callFailed_low_battery" msgid="4056828320214416182">"تماس ویدیویی بهدلیل شارژ کم باتری پایان یافت."</string>
+ <string name="callFailed_low_battery" msgid="4056828320214416182">"تماس تصویری بهدلیل شارژ کم باتری پایان یافت."</string>
<string name="callFailed_emergency_call_over_wfc_not_available" msgid="5944309590693432042">"در این مکان تماس اضطراری با «تماس ازطریق Wi-Fi» امکانپذیر نیست."</string>
<string name="callFailed_wfc_service_not_available_in_this_location" msgid="3624536608369524988">"در این مکان تماس ازطریق Wi-Fi امکانپذیر نیست."</string>
<string name="change_pin_title" msgid="3564254326626797321">"تغییر پین پست صوتی"</string>
@@ -850,7 +850,7 @@
<string name="radio_info_ims_reg_status_not_registered" msgid="8045821447288876085">"ثبتنشده"</string>
<string name="radio_info_ims_feature_status_available" msgid="6493200914756969292">"دردسترس"</string>
<string name="radio_info_ims_feature_status_unavailable" msgid="8930391136839759778">"دردسترس نیست"</string>
- <string name="radio_info_ims_reg_status" msgid="25582845222446390">"ثبت IMS: <xliff:g id="STATUS">%1$s</xliff:g>\nصدا ازطریق LTE: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nصدا ازطریق WiFi: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nتماس ویدیویی: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nواسط UT: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
+ <string name="radio_info_ims_reg_status" msgid="25582845222446390">"ثبت IMS: <xliff:g id="STATUS">%1$s</xliff:g>\nصدا ازطریق LTE: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nصدا ازطریق WiFi: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nتماس تصویری: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nواسط UT: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
<string name="radioInfo_service_in" msgid="45753418231446400">"سرویس دارد"</string>
<string name="radioInfo_service_out" msgid="287972405416142312">"خارج از سرویس"</string>
<string name="radioInfo_service_emergency" msgid="4763879891415016848">"فقط تماسهای اضطراری"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId مربوط به سیمکارت داده پیشفرض:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"پهنای باند DL (کیلوبیت بر ثانیه):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"پهنای باند UL (کیلوبیت بر ثانیه):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"اطلاعات مکان شبکه همراه (منسوخ شده):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"پیکربندی کانال فیزیکی LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"نرخ بازخوانی اطلاعات شبکه همراه:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"همه اطلاعات اندازهگیری شبکه همراه:"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 8663a4e..c402f87 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -108,21 +108,21 @@
<string name="sum_cfu_enabled_indicator" msgid="9030139213402432776">"Kaikki puhelut siirretään"</string>
<string name="sum_cfu_enabled" msgid="5806923046528144526">"Siirretään kaikki puhelut numeroon <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfu_enabled_no_number" msgid="7287752761743377930">"Numeroon ei saada yhteyttä"</string>
- <string name="sum_cfu_disabled" msgid="5010617134210809853">"Ei käytössä"</string>
+ <string name="sum_cfu_disabled" msgid="5010617134210809853">"Ei päällä"</string>
<string name="labelCFB" msgid="615265213360512768">"Kun olen varattu"</string>
<string name="messageCFB" msgid="1958017270393563388">"Soita, kun numero on varattu:"</string>
<string name="sum_cfb_enabled" msgid="332037613072049492">"Puhelu siirretään numeroon <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
- <string name="sum_cfb_disabled" msgid="3589913334164866035">"Ei käytössä"</string>
+ <string name="sum_cfb_disabled" msgid="3589913334164866035">"Ei päällä"</string>
<string name="disable_cfb_forbidden" msgid="4831494744351633961">"Operaattorisi ei tue soitonsiirtojen poistamista käytöstä, kun puhelimesi on varattuna."</string>
<string name="labelCFNRy" msgid="3403533792248457946">"Kun en vastaa"</string>
<string name="messageCFNRy" msgid="7644434155765359009">"Soita, kun numero ei vastaa:"</string>
<string name="sum_cfnry_enabled" msgid="3000500837493854799">"Puhelu siirretään numeroon <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
- <string name="sum_cfnry_disabled" msgid="1990563512406017880">"Ei käytössä"</string>
+ <string name="sum_cfnry_disabled" msgid="1990563512406017880">"Ei päällä"</string>
<string name="disable_cfnry_forbidden" msgid="3174731413216550689">"Operaattorisi ei tue soitonsiirtojen poistamista käytöstä, kun puhelimesi ei vastaa."</string>
<string name="labelCFNRc" msgid="4163399350778066013">"Kun en ole tavoitettavissa"</string>
<string name="messageCFNRc" msgid="6980340731313007250">"Soita, kun numeroon ei saada yhteyttä:"</string>
<string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Puhelu siirretään numeroon <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
- <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Ei käytössä"</string>
+ <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Ei päällä"</string>
<string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Operaattorisi ei tue soitonsiirtojen poistamista käytöstä puhelimesi ollessa saavuttamattomissa."</string>
<string name="registration_cf_forbidden" msgid="4386482610771190420">"Operaattorisi ei tue soitonsiirtoa."</string>
<string name="cdma_call_waiting" msgid="4565070960879673216">"Otetaanko koputus käyttöön?"</string>
@@ -302,7 +302,7 @@
<string name="carrier_settings_euicc_summary" msgid="2027941166597330117">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g> – <xliff:g id="PHONE_NUMBER">%2$s</xliff:g>"</string>
<string name="mobile_data_settings_title" msgid="7228249980933944101">"Mobiilidata"</string>
<string name="mobile_data_settings_summary" msgid="5012570152029118471">"Käytä dataa mobiiliverkon kautta."</string>
- <string name="data_usage_disable_mobile" msgid="5669109209055988308">"Poistetaanko mobiilidata käytöstä?"</string>
+ <string name="data_usage_disable_mobile" msgid="5669109209055988308">"Laitetaanko mobiilidata pois päältä?"</string>
<string name="sim_selection_required_pref" msgid="6985901872978341314">"Valinta on pakollinen"</string>
<string name="sim_change_data_title" msgid="9142726786345906606">"Vaihdetaanko tied.siirto-SIM?"</string>
<string name="sim_change_data_message" msgid="3567358694255933280">"Käytetäänkö SIM-kortin <xliff:g id="NEW_SIM">%1$s</xliff:g> mobiilidataa kortin <xliff:g id="OLD_SIM">%2$s</xliff:g> sijaan?"</string>
@@ -551,7 +551,7 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Puhelujen pito ei onnistu."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Yhdistä langattomaan verkkoon, jos haluat soittaa puhelun."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Ota Wi-Fi-puhelut käyttöön soittaaksesi."</string>
- <string name="emergency_information_hint" msgid="9208897544917793012">"Hätätilannetiedot"</string>
+ <string name="emergency_information_hint" msgid="9208897544917793012">"Vaaratiedot"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Omistaja"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Katso tiedot napauttamalla uudelleen"</string>
<string name="emergency_enable_radio_dialog_title" msgid="2667568200755388829">"Hätäpuhelu"</string>
@@ -656,7 +656,7 @@
<string name="voicemail_number_not_set" msgid="8831561283386938155">"<Ei asetettu>"</string>
<string name="other_settings" msgid="8895088007393598447">"Muut puheluasetukset"</string>
<string name="calling_via_template" msgid="1791323450703751750">"Operaattorilla <xliff:g id="PROVIDER_NAME">%s</xliff:g>"</string>
- <string name="contactPhoto" msgid="7885089213135154834">"yhteyshenkilön valokuva"</string>
+ <string name="contactPhoto" msgid="7885089213135154834">"yhteyshenkilön kuva"</string>
<string name="goPrivate" msgid="4645108311382209551">"muuta yksityiseksi"</string>
<string name="selectContact" msgid="1527612842599767382">"valitse yhteystieto"</string>
<string name="not_voice_capable" msgid="2819996734252084253">"Äänipuheluita ei tueta"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Oletusarvoisen data-SIM-kortin alitunnus:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL-kaistanleveys (kt/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL-kaistanleveys (kt/s):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Matkapuhelimen sijaintitiedot (poistettu käytöstä):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Fyysisen LTE-kanavan kokoonpano:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Matkapuhelintietojen päivitysaikaväli:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Matkapuhelimen kaikki mittaustiedot:"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 4f1a17f..93f797c 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -50,8 +50,7 @@
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Seul l\'utilisateur principal peut modifier les paramètres de la messagerie vocale."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"Votre carte SIM a été déverrouillée. Votre téléphone est en cours de déverrouillage..."</string>
<string name="label_ndp" msgid="7617392683877410341">"NIP de déblocage du réseau SIM"</string>
- <!-- no translation found for label_phoneid (8775611434123577808) -->
- <skip />
+ <string name="label_phoneid" msgid="8775611434123577808">"Carte SIM verrouillée pour le fournisseur de services :"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Déverrouiller"</string>
<string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Ignorer"</string>
<string name="requesting_unlock" msgid="930512210309437741">"Demande de déblocage du réseau…"</string>
@@ -589,7 +588,7 @@
<string name="singleContactImportedMsg" msgid="3619804066300998934">"Contacts importés"</string>
<string name="failedToImportSingleContactMsg" msgid="228095510489830266">"Impossible d\'importer le contact"</string>
<string name="hac_mode_title" msgid="4127986689621125468">"Assistance auditive"</string>
- <string name="hac_mode_summary" msgid="7774989500136009881">"Activer la compatibilité du service d\'assistance auditive"</string>
+ <string name="hac_mode_summary" msgid="7774989500136009881">"Activer la compatibilité des prothèses auditives"</string>
<string name="rtt_mode_title" msgid="3075948111362818043">"Appel texte en temps réel (TTR)"</string>
<string name="rtt_mode_summary" msgid="8631541375609989562">"Autoriser l\'utilisation de la messagerie lors des appels vocaux"</string>
<string name="rtt_mode_more_information" msgid="587500128658756318">"La fonctionnalité TTR aide les appelants qui sont sourds ou malentendants, qui ont un trouble de la parole ou pour qui la voix ne suffit pas.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>En savoir plus</a>\n <br><br> - Les appels TTR sont enregistrés en tant que transcriptions de messages\n <br> - La fonctionnalité TTR n\'est pas disponible pour les appels vidéo"</string>
@@ -635,10 +634,12 @@
<string name="phone_in_ecm_notification_complete_time" msgid="7341624337163082759">"Aucune connexion de données avant <xliff:g id="COMPLETETIME">%s</xliff:g>"</string>
<plurals name="alert_dialog_exit_ecm" formatted="false" msgid="5425906903766466743">
<item quantity="one">Le téléphone sera en mode de rappel d\'urgence pendant <xliff:g id="COUNT_1">%s</xliff:g> minute. Lorsque ce mode est activé, vous ne pouvez pas utiliser d\'applications nécessitant une connexion à Internet. Voulez-vous quitter l\'écran maintenant?</item>
+ <item quantity="many">The phone will be in Emergency Callback mode for <xliff:g id="COUNT_1">%s</xliff:g> minutes. While in this mode no applications using a data connection can be used. Do you want to exit now?</item>
<item quantity="other"> Le téléphone sera en mode de rappel d\'urgence pendant <xliff:g id="COUNT_1">%s</xliff:g> minutes. Lorsque ce mode est activé, vous ne pouvez pas utiliser d\'applications nécessitant une connexion à Internet. Voulez-vous quitter l\'écran maintenant?</item>
</plurals>
<plurals name="alert_dialog_not_avaialble_in_ecm" formatted="false" msgid="1152682528741457004">
<item quantity="one">L\'action sélectionnée n\'est pas disponible lorsque le mode de rappel d\'urgence est activé. Ce mode restera activé sur ce téléphone pendant <xliff:g id="COUNT_1">%s</xliff:g> minute. Voulez-vous quitter l\'écran maintenant?</item>
+ <item quantity="many">The selected action isn\'t available while in the Emergency Callback mode. The phone will be in this mode for <xliff:g id="COUNT_1">%s</xliff:g> minutes. Do you want to exit now?</item>
<item quantity="other">L\'action sélectionnée n\'est pas disponible lorsque le mode de rappel d\'urgence est activé. Ce mode restera activé sur ce téléphone pendant <xliff:g id="COUNT_1">%s</xliff:g> minutes. Voulez-vous quitter l\'écran maintenant?</item>
</plurals>
<string name="alert_dialog_in_ecm_call" msgid="1207545603149771978">"L\'action sélectionnée n\'est pas disponible pendant un appel d\'urgence."</string>
@@ -650,6 +651,7 @@
<string name="phone_in_ecm_notification_complete_time_without_data_restriction_hint" msgid="3690292264812050858">"Jusqu\'à <xliff:g id="COMPLETETIME">%s</xliff:g>"</string>
<plurals name="alert_dialog_exit_ecm_without_data_restriction_hint" formatted="false" msgid="6477733043040328640">
<item quantity="one">Le mode de rappel d\'urgence sera activé sur le téléphone pour une durée de <xliff:g id="COUNT_1">%s</xliff:g> minute.\nVoulez-vous quitter ce mode maintenant?</item>
+ <item quantity="many">The phone will be in emergency callback mode for <xliff:g id="COUNT_1">%s</xliff:g> minutes.\nDo you want to exit now?</item>
<item quantity="other">Le mode de rappel d\'urgence sera activé sur le téléphone pour une durée de <xliff:g id="COUNT_1">%s</xliff:g> minutes.\nVoulez-vous quitter ce mode maintenant?</item>
</plurals>
<string name="voicemail_provider" msgid="4158806657253745294">"Service"</string>
@@ -876,7 +878,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Sous-identifiant de la carte SIM par défaut :"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Bande passante de téléchargement (kb/s) :"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Bande passante de téléversement (kb/s) :"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Données de la position de la cellule (obsolètes) :"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuration du canal physique LTE :"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Taux d\'actualisation des données de la cellule :"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Données des mesures de toutes les cellules :"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index c6712ab..93c013a 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -36,7 +36,7 @@
<string name="ok" msgid="7818974223666140165">"OK"</string>
<string name="audio_mode_speaker" msgid="243689733219312360">"Haut-parleur"</string>
<string name="audio_mode_earpiece" msgid="2823700267171134282">"Écouteur du combiné"</string>
- <string name="audio_mode_wired_headset" msgid="5028010823105817443">"Écouteurs filaires"</string>
+ <string name="audio_mode_wired_headset" msgid="5028010823105817443">"Casque filaire"</string>
<string name="audio_mode_bluetooth" msgid="25732183428018809">"Bluetooth"</string>
<string name="wait_prompt_str" msgid="5136209532150094910">"Envoyer les tonalités suivantes ?\n"</string>
<string name="pause_prompt_str" msgid="2308897950360272213">"Envoi des tonalités\n"</string>
@@ -634,10 +634,12 @@
<string name="phone_in_ecm_notification_complete_time" msgid="7341624337163082759">"Aucune connexion Internet mobile jusqu\'à <xliff:g id="COMPLETETIME">%s</xliff:g>"</string>
<plurals name="alert_dialog_exit_ecm" formatted="false" msgid="5425906903766466743">
<item quantity="one">Le téléphone sera en mode de rappel d\'urgence pendant <xliff:g id="COUNT_1">%s</xliff:g> minute. Lorsque ce mode est activé, vous ne pouvez pas utiliser d\'applications nécessitant une connexion à Internet. Voulez-vous quitter l\'écran maintenant ?</item>
+ <item quantity="many">The phone will be in Emergency Callback mode for <xliff:g id="COUNT_1">%s</xliff:g> minutes. While in this mode no applications using a data connection can be used. Do you want to exit now?</item>
<item quantity="other">Le téléphone sera en mode de rappel d\'urgence pendant <xliff:g id="COUNT_1">%s</xliff:g> minutes. Lorsque ce mode est activé, vous ne pouvez pas utiliser d\'applications nécessitant une connexion à Internet. Voulez-vous quitter l\'écran maintenant ?</item>
</plurals>
<plurals name="alert_dialog_not_avaialble_in_ecm" formatted="false" msgid="1152682528741457004">
<item quantity="one">L\'action sélectionnée n\'est pas disponible lorsque le mode de rappel d\'urgence est activé. Ce mode restera activé sur ce téléphone pendant <xliff:g id="COUNT_1">%s</xliff:g> minute. Voulez-vous quitter l\'écran maintenant ?</item>
+ <item quantity="many">The selected action isn\'t available while in the Emergency Callback mode. The phone will be in this mode for <xliff:g id="COUNT_1">%s</xliff:g> minutes. Do you want to exit now?</item>
<item quantity="other">L\'action sélectionnée n\'est pas disponible lorsque le mode de rappel d\'urgence est activé. Ce mode restera activé sur ce téléphone pendant <xliff:g id="COUNT_1">%s</xliff:g> minute. Voulez-vous quitter l\'écran maintenant ?</item>
</plurals>
<string name="alert_dialog_in_ecm_call" msgid="1207545603149771978">"L\'action sélectionnée n\'est pas disponible pendant un appel d\'urgence."</string>
@@ -649,6 +651,7 @@
<string name="phone_in_ecm_notification_complete_time_without_data_restriction_hint" msgid="3690292264812050858">"Jusqu\'à <xliff:g id="COMPLETETIME">%s</xliff:g>"</string>
<plurals name="alert_dialog_exit_ecm_without_data_restriction_hint" formatted="false" msgid="6477733043040328640">
<item quantity="one">Le téléphone sera en mode de rappel d\'urgence pendant <xliff:g id="COUNT_1">%s</xliff:g> minutes.\nSouhaitez-vous quitter ce mode maintenant ?</item>
+ <item quantity="many">The phone will be in emergency callback mode for <xliff:g id="COUNT_1">%s</xliff:g> minutes.\nDo you want to exit now?</item>
<item quantity="other">Le téléphone sera en mode de rappel d\'urgence pendant <xliff:g id="COUNT_1">%s</xliff:g> minutes.\nSouhaitez-vous quitter ce mode maintenant ?</item>
</plurals>
<string name="voicemail_provider" msgid="4158806657253745294">"Service"</string>
@@ -875,7 +878,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Sous-identifiant de la carte SIM par défaut pour les données :"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Bande passante de téléchargement (kbit/s) :"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Bande passante d\'importation (kbit/s) :"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informations de géolocalisation mobiles (obsolètes) :"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuration de la chaîne physique LTE :"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Fréquence d\'actualisation des informations mobiles :"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Toutes les informations mobiles liées aux mesures :"</string>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 6ade32b..1876244 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Código de identificación secundario da SIM de datos predeterminada:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Largura de banda de descarga (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Largura de banda de carga (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Información da localización para móbiles (obsoleto):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuración de canle física de LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Taxa de actualización da información para móbiles:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Toda a información de medición para móbiles:"</string>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index e964a8d..c767c67 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -181,8 +181,8 @@
<string name="not_allowed" msgid="8541221928746104798">"તમારું SIM કાર્ડ આ નેટવર્કથી કનેક્શનને મંજૂરી આપતું નથી."</string>
<string name="connect_later" msgid="1950138106010005425">"હમણાં આ નેટવર્કથી કનેક્ટ કરી શકાતું નથી. પછીથી ફરી પ્રયાસ કરો."</string>
<string name="registration_done" msgid="5337407023566953292">"નેટવર્ક પર નોંધણી કરી."</string>
- <string name="already_auto" msgid="8607068290733079336">"પહેલેથી જ આપમેળે પસંદગીમાં."</string>
- <string name="select_automatically" msgid="779750291257872651">"નેટવર્ક આપમેળે પસંદ કરો"</string>
+ <string name="already_auto" msgid="8607068290733079336">"પહેલેથી જ ઑટોમૅટિક પસંદગીમાં."</string>
+ <string name="select_automatically" msgid="779750291257872651">"નેટવર્ક ઑટોમૅટિક રીતે પસંદ કરો"</string>
<string name="manual_mode_disallowed_summary" msgid="3970048592179890197">"%1$s સાથે કનેક્ટ કરેલું હોય ત્યારે અનુપલબ્ધ"</string>
<string name="network_select_title" msgid="4117305053881611988">"નેટવર્ક"</string>
<string name="register_automatically" msgid="3907580547590554834">"સ્વયંચાલિત નોંધણી…"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ડિફૉલ્ટ ડેટા સિમનું SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL બૅન્ડવિડ્થ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL બૅન્ડવિડ્થ (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"સેલ સ્થાન માહિતી (ટાળેલ):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ભૌતિક ચૅનલની ગોઠવણી:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"સેલ માહિતી રિફ્રેશ થવાનો રેટ:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"તમામ સેલ માપ માહિતી:"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index b0e7685..e9b1283 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -656,7 +656,7 @@
<string name="voicemail_number_not_set" msgid="8831561283386938155">"<सेट नहीं है>"</string>
<string name="other_settings" msgid="8895088007393598447">"अन्य कॉल सेटिंग"</string>
<string name="calling_via_template" msgid="1791323450703751750">"कॉल <xliff:g id="PROVIDER_NAME">%s</xliff:g> से जा रही है"</string>
- <string name="contactPhoto" msgid="7885089213135154834">"संपर्क का फ़ोटो"</string>
+ <string name="contactPhoto" msgid="7885089213135154834">"संपर्क की फ़ोटो"</string>
<string name="goPrivate" msgid="4645108311382209551">"निजी हो जाएं"</string>
<string name="selectContact" msgid="1527612842599767382">"संपर्क को चुनें"</string>
<string name="not_voice_capable" msgid="2819996734252084253">"ध्वनि कॉल करना समर्थित नहीं है"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"डिफ़ॉल्ट डेटा सिम का सब-आईडी:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"डीएल बैंडविड्थ (केबीपीएस):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"यूएल बैंडविड्थ (केबीपीएस):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"सेल की जगह की जानकारी (रोकी गयी है):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"एलटीई की फ़िज़िकल चैनल कॉन्फ़िगरेशन:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"सेल की जानकारी रीफ़्रेश होने की दर:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"सभी सेल के माप की पूरी जानकारी:"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 5361562..091147b 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -96,17 +96,17 @@
<string name="sum_loading_settings" msgid="434063780286688775">"Učitavanje postavki…"</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"Broj je skriven u izlaznim pozivima"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"Broj prikazan za izlazne pozive"</string>
- <string name="sum_default_caller_id" msgid="1767070797135682959">"Koristiti zadane postavke operatera za prikaz mog broja kod odlaznih poziva"</string>
+ <string name="sum_default_caller_id" msgid="1767070797135682959">"Upotrijebi zadane postavke operatera za prikaz mog broja kod odlaznih poziva"</string>
<string name="labelCW" msgid="8449327023861428622">"Poziv na čekanju"</string>
- <string name="sum_cw_enabled" msgid="3977308526187139996">"Obavijesti me tijekom poziva o dolaznim pozivima"</string>
- <string name="sum_cw_disabled" msgid="3658094589461768637">"Obavijesti me tijekom poziva o dolaznim pozivima"</string>
+ <string name="sum_cw_enabled" msgid="3977308526187139996">"Obavijesti me o dolaznim pozivima tijekom poziva"</string>
+ <string name="sum_cw_disabled" msgid="3658094589461768637">"Obavijesti me o dolaznim pozivima tijekom poziva"</string>
<string name="call_forwarding_settings" msgid="8937130467468257671">"Postavke preusmjeravanja poziva"</string>
<string name="call_forwarding_settings_with_label" msgid="2345432813399564272">"Prosljeđivanje poziva (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="labelCF" msgid="3578719437928476078">"Preusmjeravanje poziva"</string>
<string name="labelCFU" msgid="8870170873036279706">"Uvijek preusmjeri"</string>
<string name="messageCFU" msgid="1361806450979589744">"Uvijek koristi ovaj broj"</string>
<string name="sum_cfu_enabled_indicator" msgid="9030139213402432776">"Preusmjeravanje svih poziva"</string>
- <string name="sum_cfu_enabled" msgid="5806923046528144526">"Preusmjeravanje poziva na <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
+ <string name="sum_cfu_enabled" msgid="5806923046528144526">"Preusmjeravanje svih poziva na <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfu_enabled_no_number" msgid="7287752761743377930">"Broj je nedostupan"</string>
<string name="sum_cfu_disabled" msgid="5010617134210809853">"Isključeno"</string>
<string name="labelCFB" msgid="615265213360512768">"Kad je broj zauzet"</string>
@@ -878,7 +878,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SUBID zadanog SIM-a za podatkovni promet:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL propusnost (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL propusnost (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informacije o lokaciji ćelije (obustavljeno):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguracija LTE fizičkog kanala:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Stopa osvježavanja informacija u ćeliji:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Sve informacije ćelija o mjerenju:"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index a9e0de6..45405e9 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Alapértelmezett adatok SIM-alazonosítója:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Letöltési sávszélesség (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Feltöltési sávszélesség (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Mobilos helyadatok (megszűnt):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE fizikai csatorna konfigurációja:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Cellainformáció frissítési gyakorisága:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Minden cellamérési információ:"</string>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 96e87b2..af95672 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -103,7 +103,7 @@
<string name="call_forwarding_settings" msgid="8937130467468257671">"Վերահասցեավորում"</string>
<string name="call_forwarding_settings_with_label" msgid="2345432813399564272">"Զանգի փոխանցման կարգավորումներ (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="labelCF" msgid="3578719437928476078">"Զանգի վերահասցեավորում"</string>
- <string name="labelCFU" msgid="8870170873036279706">"Միշտ փոխանցել"</string>
+ <string name="labelCFU" msgid="8870170873036279706">"Միշտ վերահասցեավորել"</string>
<string name="messageCFU" msgid="1361806450979589744">"Միշտ օգտագործել այս համարը"</string>
<string name="sum_cfu_enabled_indicator" msgid="9030139213402432776">"Բոլոր զանգերը վերահասցեավորվում են"</string>
<string name="sum_cfu_enabled" msgid="5806923046528144526">"Բոլոր զանգերը վերահասցեավորվում են <xliff:g id="PHONENUMBER">{0}</xliff:g>-ին"</string>
@@ -114,12 +114,12 @@
<string name="sum_cfb_enabled" msgid="332037613072049492">"Վերահասցեավորվում է դեպի <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfb_disabled" msgid="3589913334164866035">"Անջատված է"</string>
<string name="disable_cfb_forbidden" msgid="4831494744351633961">"Ձեր օպերատորը չի աջակցում զանգի վերահասցեավորման կասեցում, երբ ձեր հեռախոսը զբաղված է:"</string>
- <string name="labelCFNRy" msgid="3403533792248457946">"Երբ պատասխան չկա"</string>
+ <string name="labelCFNRy" msgid="3403533792248457946">"Երբ չեմ պատասխանում"</string>
<string name="messageCFNRy" msgid="7644434155765359009">"Թվել, երբ անպատասխան է"</string>
<string name="sum_cfnry_enabled" msgid="3000500837493854799">"Վերահասցեավորվում է դեպի <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfnry_disabled" msgid="1990563512406017880">"Անջատված է"</string>
<string name="disable_cfnry_forbidden" msgid="3174731413216550689">"Ձեր օպերատորը չի աջակցում զանգի վերահասցեավորման կասեցում, երբ ձեր հեռախոսը չի պատասխանում:"</string>
- <string name="labelCFNRc" msgid="4163399350778066013">"Երբ անհասանելի է"</string>
+ <string name="labelCFNRc" msgid="4163399350778066013">"Երբ անհասանելի եմ"</string>
<string name="messageCFNRc" msgid="6980340731313007250">"Թվել, երբ անհասանելի է"</string>
<string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Վերահասցեավորվում է դեպի <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfnrc_disabled" msgid="739289696796917683">"Անջատված է"</string>
@@ -136,7 +136,7 @@
<string name="call_settings_with_label" msgid="8460230435361579511">"Կարգավորումներ (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="error_updating_title" msgid="2024290892676808965">"Զանգի կարգավորումների սխալ"</string>
<string name="reading_settings" msgid="1605904432450871183">"Ընթերցման կարգավորումներ..."</string>
- <string name="updating_settings" msgid="3650396734816028808">"Թարմացվում են կարգավորումները..."</string>
+ <string name="updating_settings" msgid="3650396734816028808">"Կարգավորումների թարմացում..."</string>
<string name="reverting_settings" msgid="7378668837291012205">"Կարգավորւմները հետադարձվում են..."</string>
<string name="response_error" msgid="3904481964024543330">"Անակնկալ պատասխան ցանցից:"</string>
<string name="exception_error" msgid="330994460090467">"Ցանցի կամ SIM քարտի սխալ"</string>
@@ -149,7 +149,7 @@
<string name="close_dialog" msgid="1074977476136119408">"Լավ"</string>
<string name="enable" msgid="2636552299455477603">"Միացնել"</string>
<string name="disable" msgid="1122698860799462116">"Անջատել"</string>
- <string name="change_num" msgid="6982164494063109334">"Նորացնել"</string>
+ <string name="change_num" msgid="6982164494063109334">"Թարմացնել"</string>
<string-array name="clir_display_values">
<item msgid="8477364191403806960">"Կանխադրված ցանց"</item>
<item msgid="6813323051965618926">"Թաքցնել համարը"</item>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SIM քարտի հավելյալ ID կանխադրված բջջային ինտերնետի համար՝"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL թողունակությունը (կբ/վ)՝"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL թողունակությունը (կբ/վ)՝"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Բջիջի տեղադրության տվյալներ (հնացած)՝"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ֆիզիկական ալիքի կարգավորում՝"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Բջիջի տվյալների թարմացման հաճախականությունը՝"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Բոլոր բջիջների չափման տվյալները՝"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 3251407..e06cb64 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -143,7 +143,7 @@
<string name="stk_cc_ss_to_dial_error" msgid="5147693491690618704">"Permintaan SS diubah ke panggilan reguler"</string>
<string name="stk_cc_ss_to_ussd_error" msgid="8330749347425752192">"Permintaan SS diubah ke permintaan USSD"</string>
<string name="stk_cc_ss_to_ss_error" msgid="8297155544652134278">"Diubah ke permintaan SS baru"</string>
- <string name="stk_cc_ss_to_dial_video_error" msgid="4255261231466032505">"Permintaan SS diubah ke video call"</string>
+ <string name="stk_cc_ss_to_dial_video_error" msgid="4255261231466032505">"Permintaan SS diubah ke panggilan video"</string>
<string name="fdn_check_failure" msgid="1833769746374185247">"Setelan Nomor Panggilan Tetap aplikasi Ponsel Anda diaktifkan. Akibatnya, beberapa fitur yang terkait dengan panggilan tidak bekerja."</string>
<string name="radio_off_error" msgid="8321564164914232181">"Keluar dari mode pesawat sebelum melihat setelan ini."</string>
<string name="close_dialog" msgid="1074977476136119408">"Oke"</string>
@@ -307,7 +307,7 @@
<string name="sim_change_data_title" msgid="9142726786345906606">"Ubah SIM data?"</string>
<string name="sim_change_data_message" msgid="3567358694255933280">"Gunakan <xliff:g id="NEW_SIM">%1$s</xliff:g> dan bukan <xliff:g id="OLD_SIM">%2$s</xliff:g> untuk data seluler?"</string>
<string name="wifi_calling_settings_title" msgid="5800018845662016507">"Panggilan Wi-Fi"</string>
- <string name="video_calling_settings_title" msgid="342829454913266078">"Video call operator"</string>
+ <string name="video_calling_settings_title" msgid="342829454913266078">"Panggilan video operator"</string>
<string name="gsm_umts_options" msgid="4968446771519376808">"Opsi GSM//UMTS"</string>
<string name="cdma_options" msgid="3669592472226145665">"Opsi CDMA"</string>
<string name="throttle_data_usage" msgid="1944145350660420711">"Penggunaan kuota"</string>
@@ -454,7 +454,7 @@
<string name="tty_mode_option_summary" msgid="4770510287236494371">"Setel Mode TTY"</string>
<string name="auto_retry_mode_title" msgid="2985801935424422340">"Coba lagi otomatis"</string>
<string name="auto_retry_mode_summary" msgid="2863919925349511402">"Aktifkan mode Coba lagi otomatis"</string>
- <string name="tty_mode_not_allowed_video_call" msgid="6551976083652752815">"Perubahan Mode TTY tidak diizinkan selama video call"</string>
+ <string name="tty_mode_not_allowed_video_call" msgid="6551976083652752815">"Perubahan Mode TTY tidak diizinkan selama panggilan video"</string>
<string name="menu_add" msgid="5616487894975773141">"Tambahkan kontak"</string>
<string name="menu_edit" msgid="3593856941552460706">"Edit kontak"</string>
<string name="menu_delete" msgid="6326861853830546488">"Hapus kontak"</string>
@@ -580,7 +580,7 @@
<string name="onscreenManageCallsText" msgid="1162047856081836469">"Kelola panggilan"</string>
<string name="onscreenManageConferenceText" msgid="4700574060601755137">"Kelola konferensi"</string>
<string name="onscreenAudioText" msgid="7224226735052019986">"Audio"</string>
- <string name="onscreenVideoCallText" msgid="1743992456126258698">"Video call"</string>
+ <string name="onscreenVideoCallText" msgid="1743992456126258698">"Panggilan video"</string>
<string name="importSimEntry" msgid="3892354284082689894">"Impor"</string>
<string name="importAllSimEntries" msgid="2628391505643564007">"Impor semua"</string>
<string name="importingSimContacts" msgid="4995457122107888932">"Mengimpor kontak dari SIM"</string>
@@ -591,7 +591,7 @@
<string name="hac_mode_summary" msgid="7774989500136009881">"Aktifkan kompatibilitas alat bantu dengar"</string>
<string name="rtt_mode_title" msgid="3075948111362818043">"Panggilan pesan real-time (RTT)"</string>
<string name="rtt_mode_summary" msgid="8631541375609989562">"Izinkan pengiriman pesan pada saat panggilan suara berlangsung"</string>
- <string name="rtt_mode_more_information" msgid="587500128658756318">"RTT membantu penelepon yang tunarungu, kesulitan mendengar, memiliki gangguan berbicara, atau memerlukan lebih dari sekadar suara.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>Pelajari lebih lanjut</a>\n <br><br> - Panggilan RTT disimpan sebagai transkrip pesan\n <br> - RTT tidak tersedia untuk video call"</string>
+ <string name="rtt_mode_more_information" msgid="587500128658756318">"RTT membantu penelepon yang tunarungu, kesulitan mendengar, memiliki gangguan berbicara, atau memerlukan lebih dari sekadar suara.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>Pelajari lebih lanjut</a>\n <br><br> - Panggilan RTT disimpan sebagai transkrip pesan\n <br> - RTT tidak tersedia untuk panggilan video"</string>
<string name="no_rtt_when_roaming" msgid="5268008247378355389">"Catatan: RTT tidak tersedia saat melakukan roaming"</string>
<string-array name="tty_mode_entries">
<item msgid="3238070884803849303">"TTY Nonaktif"</item>
@@ -668,8 +668,8 @@
<string name="voicemail_change_pin_dialog_title" msgid="4633077715231764435">"Ubah PIN"</string>
<string name="preference_category_ringtone" msgid="8787281191375434976">"Nada dering & Getar"</string>
<string name="pstn_connection_service_label" msgid="9200102709997537069">"Kartu SIM internal"</string>
- <string name="enable_video_calling_title" msgid="7246600931634161830">"Aktifkan video call"</string>
- <string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"Untuk mengaktifkan video call, Anda perlu mengaktifkan Mode LTE 4G yang Ditingkatkan di setelan jaringan."</string>
+ <string name="enable_video_calling_title" msgid="7246600931634161830">"Aktifkan panggilan video"</string>
+ <string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"Untuk mengaktifkan panggilan video, Anda perlu mengaktifkan Mode LTE 4G yang Ditingkatkan di setelan jaringan."</string>
<string name="enable_video_calling_dialog_settings" msgid="8697890611305307110">"Setelan jaringan"</string>
<string name="enable_video_calling_dialog_close" msgid="4298929725917045270">"Tutup"</string>
<string name="sim_label_emergency_calls" msgid="9078241989421522310">"Panggilan darurat"</string>
@@ -684,8 +684,8 @@
<string name="callFailed_cdma_call_limit" msgid="1074219746093031412">"Ada terlalu banyak panggilan aktif. Akhiri atau gabungkan panggilan yang ada sebelum melakukan panggilan baru."</string>
<string name="callFailed_imei_not_accepted" msgid="7257903653685147251">"Tidak dapat tersambung, masukkan kartu SIM yang valid."</string>
<string name="callFailed_wifi_lost" msgid="1788036730589163141">"Sambungan Wi-Fi terputus. Panggilan diakhiri."</string>
- <string name="dialFailed_low_battery" msgid="6857904237423407056">"Video call tidak bisa dilakukan karena daya baterai lemah."</string>
- <string name="callFailed_low_battery" msgid="4056828320214416182">"Video call berakhir karena daya baterai lemah."</string>
+ <string name="dialFailed_low_battery" msgid="6857904237423407056">"Panggilan video tidak bisa dilakukan karena daya baterai lemah."</string>
+ <string name="callFailed_low_battery" msgid="4056828320214416182">"Panggilan video berakhir karena daya baterai lemah."</string>
<string name="callFailed_emergency_call_over_wfc_not_available" msgid="5944309590693432042">"Panggilan darurat melalui panggilan Wi-Fi tidak tersedia di lokasi ini."</string>
<string name="callFailed_wfc_service_not_available_in_this_location" msgid="3624536608369524988">"Panggilan Wi-Fi tidak tersedia di lokasi ini."</string>
<string name="change_pin_title" msgid="3564254326626797321">"Ubah PIN Pesan Suara"</string>
@@ -831,7 +831,7 @@
<string name="radio_info_data_connection_enable" msgid="6183729739783252840">"Aktifkan Koneksi Data"</string>
<string name="radio_info_data_connection_disable" msgid="6404751291511368706">"Nonaktifkan Koneksi Data"</string>
<string name="volte_provisioned_switch_string" msgid="4812874990480336178">"VoLTE Disediakan"</string>
- <string name="vt_provisioned_switch_string" msgid="8295542122512195979">"Video Call Disediakan"</string>
+ <string name="vt_provisioned_switch_string" msgid="8295542122512195979">"Panggilan Video Disediakan"</string>
<string name="wfc_provisioned_switch_string" msgid="3835004640321078988">"Panggilan Wi-Fi Disediakan"</string>
<string name="eab_provisioned_switch_string" msgid="4449676720736033035">"EAB/Presence Disediakan"</string>
<string name="cbrs_data_switch_string" msgid="6060356430838077653">"Data Cbrs"</string>
@@ -850,7 +850,7 @@
<string name="radio_info_ims_reg_status_not_registered" msgid="8045821447288876085">"Tidak Terdaftar"</string>
<string name="radio_info_ims_feature_status_available" msgid="6493200914756969292">"Tersedia"</string>
<string name="radio_info_ims_feature_status_unavailable" msgid="8930391136839759778">"Tidak tersedia"</string>
- <string name="radio_info_ims_reg_status" msgid="25582845222446390">"Pendaftaran IMS: <xliff:g id="STATUS">%1$s</xliff:g>\nSuara melalui LTE: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nSuara melalui Wi-Fi: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nVideo Call: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nAntarmuka UT: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
+ <string name="radio_info_ims_reg_status" msgid="25582845222446390">"Pendaftaran IMS: <xliff:g id="STATUS">%1$s</xliff:g>\nSuara melalui LTE: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nSuara melalui Wi-Fi: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nPanggilan Video: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nAntarmuka UT: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
<string name="radioInfo_service_in" msgid="45753418231446400">"Dalam Layanan"</string>
<string name="radioInfo_service_out" msgid="287972405416142312">"Di Luar Area Layanan"</string>
<string name="radioInfo_service_emergency" msgid="4763879891415016848">"Panggilan Darurat Saja"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId SIM data default:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Bandwidth DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Bandwidth UL (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Info Lokasi Sel (tidak digunakan lagi):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurasi Saluran Fisik LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Rasio Pembaruan Info Sel"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Semua Info Pengukuran Sel:"</string>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index efa0690..4a467ea 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -50,8 +50,7 @@
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Aðeins aðalnotandinn má breyta talhólfsstillingum."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"Opnað var fyrir SIM-kortið. Verið er að opna símann…"</string>
<string name="label_ndp" msgid="7617392683877410341">"PIN-númer SIM-korts til að opna síma"</string>
- <!-- no translation found for label_phoneid (8775611434123577808) -->
- <skip />
+ <string name="label_phoneid" msgid="8775611434123577808">"SIM-kort læst fyrir símafyrirtæki"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Taka úr lás"</string>
<string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Hunsa"</string>
<string name="requesting_unlock" msgid="930512210309437741">"Biður um að símkerfi sé opnað…"</string>
@@ -110,7 +109,7 @@
<string name="sum_cfu_enabled" msgid="5806923046528144526">"Áframsendir öll símtöl í <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfu_enabled_no_number" msgid="7287752761743377930">"Ekki næst í númerið"</string>
<string name="sum_cfu_disabled" msgid="5010617134210809853">"Slökkt"</string>
- <string name="labelCFB" msgid="615265213360512768">"Þegar er á tali"</string>
+ <string name="labelCFB" msgid="615265213360512768">"Þegar það er á tali"</string>
<string name="messageCFB" msgid="1958017270393563388">"Númeraval þegar síminn er á tali"</string>
<string name="sum_cfb_enabled" msgid="332037613072049492">"Áframsendir í <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfb_disabled" msgid="3589913334164866035">"Slökkt"</string>
@@ -876,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Undirauðkenni sjálfgefins SIM-korts fyrir gögn:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Niðurhalsbandvídd (kb/sek.):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Upphleðslubandvídd (kb/sek.):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Staðsetningarupplýsingar loftneta (úrelt):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE-rásarstilling:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Endurnýjunartíðni loftnetaupplýsinga:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Allar mælingarupplýsingar loftneta:"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 934f56b..c05ac00 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -96,7 +96,7 @@
<string name="sum_loading_settings" msgid="434063780286688775">"Caricamento impostazioni…"</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"Numero nascosto per chiamate in uscita"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"Numero visualizzato in chiamate in uscita"</string>
- <string name="sum_default_caller_id" msgid="1767070797135682959">"Usa impostazioni dell\'operatore per mostrare il mio numero nelle chiamate in uscita"</string>
+ <string name="sum_default_caller_id" msgid="1767070797135682959">"Usa le impostazioni predefinite dell\'operatore per mostrare il mio numero nelle chiamate in uscita"</string>
<string name="labelCW" msgid="8449327023861428622">"Avviso di chiamata"</string>
<string name="sum_cw_enabled" msgid="3977308526187139996">"Notifica chiamate in entrata durante telefonata"</string>
<string name="sum_cw_disabled" msgid="3658094589461768637">"Notifica chiamate in entrata durante telefonata"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ID secondario della SIM dati predefinita:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Larghezza di banda DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Larghezza di banda UL (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informazioni sulla posizione delle celle (obsoleto):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configurazione canale fisico LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frequenza di aggiornamento delle informazioni sulle celle:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Informazioni sulla misurazione di tutte le celle:"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 93c5536..3d397d0 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -881,7 +881,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"תת-מזהה של כרטיס ה-SIM עם חבילת גלישה המוגדר כברירת מחדל:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"רוחב פס DL (ב-kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"רוחב פס UL (ב-kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"מידע על מיקום סלולרי (הוצא משימוש):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"תצורת ערוץ פיזי של LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"קצב רענון של מידע סלולרי:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"כל המידע של מדידה סלולרית:"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index e74fdb5..e571695 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"デフォルトのデータ SIM の SUBID:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL 帯域幅(kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL 帯域幅(kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"セルの位置情報(サポート終了):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE の物理チャネル設定:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"セル情報の更新間隔:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"すべてのセルの測定情報:"</string>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index 68276de..17ad78e 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -75,7 +75,7 @@
<string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"ანგარიშის პარამეტრების კონფიგურაცია"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"დარეკვის ყველა ანგარიში"</string>
<string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"აირჩიეთ რომელ ანგარიშს შეეძლება ზარების განხორციელება"</string>
- <string name="wifi_calling" msgid="3650509202851355742">"დარეკვა Wi-Fi-ს მეშვეობით"</string>
+ <string name="wifi_calling" msgid="3650509202851355742">"Wi-Fi დარეკვა"</string>
<string name="connection_service_default_label" msgid="7332739049855715584">"კავშირის ჩაშენებული სერვისი"</string>
<string name="voicemail" msgid="7697769412804195032">"ხმოვანი ფოსტა"</string>
<string name="voicemail_settings_with_label" msgid="4228431668214894138">"ხმოვანი ფოსტა (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"მონაცემების ნაგულისხმევი SIM-ის subId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL-არხის გამტარუნარიანობა (კბიტ/წმ):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL-არხის გამტარუნარიანობა (კბიტ/წმ):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"ფიჭური მდებარეობის ინფორმაცია (მოძველდა):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ფიზიკური არხის კონფიგურაცია:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ფიჭური ინფორმაციის განახლების სიხშირე:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"სრული ინფორმაცია ფიჭური ქსელის შესახებ:"</string>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index f4fcb91..cdc7f70 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -50,8 +50,7 @@
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Дауыстық пошта параметрлерін тек негізгі пайдаланушы өзгерте алады."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"SIM картаңыз ашылды. Телефоныңыздың бекітпесі ашылуда…"</string>
<string name="label_ndp" msgid="7617392683877410341">"SIM желісін ашатын PIN код"</string>
- <!-- no translation found for label_phoneid (8775611434123577808) -->
- <skip />
+ <string name="label_phoneid" msgid="8775611434123577808">"SIM картасы келесі операторға құлыпталған"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Бекітпесін ашу"</string>
<string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Бас тарту"</string>
<string name="requesting_unlock" msgid="930512210309437741">"Желінің бекітпесін ашуды өтінуде…"</string>
@@ -98,7 +97,7 @@
<string name="sum_hide_caller_id" msgid="131100328602371933">"Шығыс қоңырауларда нөмірді жасыру"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"Шығыс қоңыраулар нөмірді көрсету"</string>
<string name="sum_default_caller_id" msgid="1767070797135682959">"Шығыс қоңырауларында менің нөмірім көрсетілуі үшін бастапқы оператор параметрлерін қолдану"</string>
- <string name="labelCW" msgid="8449327023861428622">"Күтудегі қоңырау"</string>
+ <string name="labelCW" msgid="8449327023861428622">"Қоңырауды ұстап тұру"</string>
<string name="sum_cw_enabled" msgid="3977308526187139996">"Қоңырау кезінде маған келген қоңыраулар жайлы хабарлау"</string>
<string name="sum_cw_disabled" msgid="3658094589461768637">"Қоңырау кезінде маған келген қоңыраулар жайлы хабарлау"</string>
<string name="call_forwarding_settings" msgid="8937130467468257671">"Қоңырауды басқа нөмірге бағыттау параметрлері"</string>
@@ -126,12 +125,12 @@
<string name="sum_cfnrc_disabled" msgid="739289696796917683">"Өшірулі"</string>
<string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Телефоныңыз қол жетімсіз болғанда жабдықтаушы қоңырауды басқа нөмірге бағыттауды өшіруді қолдамайды."</string>
<string name="registration_cf_forbidden" msgid="4386482610771190420">"Операторыңыз қоңырауды басқа нөмірге бағыттауды қолдамайды."</string>
- <string name="cdma_call_waiting" msgid="4565070960879673216">"Басқа желідегі қоңырау мүмкіндігін қосу керек пе?"</string>
+ <string name="cdma_call_waiting" msgid="4565070960879673216">"Қоңырауды ұстап тұру мүмкіндігін қосу керек пе?"</string>
<string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"Сөйлесіп жатқанда сізге кіріс қоңыраулар туралы хабарландыру көрсетіледі."</string>
<string name="enable_cdma_cw" msgid="811047045863422232">"Қосу"</string>
<string name="disable_cdma_cw" msgid="7119290446496301734">"Бас тарту"</string>
- <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS бойынша басқа CDMA желісіндегі қоңырау мүмкіндігі қосулы."</string>
- <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS бойынша басқа CDMA желісіндегі қоңырау мүмкіндігі өшірулі."</string>
+ <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS бойынша басқа CDMA желісіндегі қоңырауды ұстап тұру мүмкіндігі қосулы."</string>
+ <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS бойынша басқа CDMA желісіндегі қоңырауды ұстап тұру мүмкіндігі өшірулі."</string>
<string name="updating_title" msgid="6130548922615719689">"Қоңырау параметрлері"</string>
<string name="call_settings_admin_user_only" msgid="7238947387649986286">"Қоңырау параметрлерін тек әкімші пайдаланушы өзгерте алады."</string>
<string name="call_settings_with_label" msgid="8460230435361579511">"Параметрлер (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -673,7 +672,7 @@
<string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"Бейне қоңырауларды қосу үшін желі параметрлерінде жақсартылған 4G LTE режимін қосу керек."</string>
<string name="enable_video_calling_dialog_settings" msgid="8697890611305307110">"Желі параметрлері"</string>
<string name="enable_video_calling_dialog_close" msgid="4298929725917045270">"Жабу"</string>
- <string name="sim_label_emergency_calls" msgid="9078241989421522310">"Жедел қоңыраулар"</string>
+ <string name="sim_label_emergency_calls" msgid="9078241989421522310">"Құтқару қызметіне қоңырау шалу"</string>
<string name="sim_description_emergency_calls" msgid="5146872803938897296">"Тек жедел қоңыраулар"</string>
<string name="sim_description_default" msgid="7474671114363724971">"SIM картасы, ұяшық: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="7883415189273700298">"Арнайы мүмкіндіктер"</string>
@@ -876,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Әдепкі деректер SIM картасының қосалқы идентификаторы:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL өткізу мүмкіндігі (кбит/сек):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL өткізу мүмкіндігі (кбит/сек):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Ұялы желінің орналасқан жері туралы ақпарат (қолданыстан шығарылды):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE физикалық арна конфигурациясы:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Ұялы желі туралы ақпаратты жаңарту жиілігі:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Барлық ұялы желі өлшемдері туралы ақпарат:"</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index cd122a9..24ce0e3 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -24,7 +24,7 @@
<string name="unknown" msgid="8279698889921830815">"មិនស្គាល់"</string>
<string name="private_num" msgid="4487990167889159992">"លេខឯកជន"</string>
<string name="payphone" msgid="7936735771836716941">"ទូរស័ព្ទសាធារណៈ"</string>
- <string name="onHold" msgid="6132725550015899006">"រង់ចាំ"</string>
+ <string name="onHold" msgid="6132725550015899006">"កំពុងរង់ចាំ"</string>
<string name="carrier_mmi_msg_title" msgid="6050165242447507034">"សារ <xliff:g id="MMICARRIER">%s</xliff:g>"</string>
<string name="default_carrier_mmi_msg_title" msgid="7754317179938537213">"សារក្រុមហ៊ុនសេវាទូរសព្ទ"</string>
<string name="mmiStarted" msgid="9212975136944568623">"បានចាប់ផ្ដើមកូដ MMI"</string>
@@ -92,7 +92,7 @@
<string name="additional_cdma_call_settings" msgid="2178016561980611304">"កំណត់ការហៅ CDMA បន្ថែម"</string>
<string name="sum_cdma_call_settings" msgid="3185825305136993636">"កំណត់ការហៅតែ CDMA បន្ថែមប៉ុណ្ណោះ"</string>
<string name="labelNwService" msgid="6015891883487125120">"ការកំណត់សេវាបណ្ដាញ"</string>
- <string name="labelCallerId" msgid="2090540744550903172">"លេខសម្គាល់អ្នកហៅ"</string>
+ <string name="labelCallerId" msgid="2090540744550903172">"អត្តសញ្ញាណអ្នកហៅទូរសព្ទ"</string>
<string name="sum_loading_settings" msgid="434063780286688775">"កំពុងផ្ទុកការកំណត់…"</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"បានលាក់លេខក្នុងការហៅចេញ"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"បានបង្ហាញលេខក្នុងការហៅចេញ"</string>
@@ -100,8 +100,8 @@
<string name="labelCW" msgid="8449327023861428622">"រង់ចាំការហៅ"</string>
<string name="sum_cw_enabled" msgid="3977308526187139996">"ក្នុងអំឡុងពេលហៅ ជូនដំណឹងដល់ខ្ញុំអំពីការហៅចូល"</string>
<string name="sum_cw_disabled" msgid="3658094589461768637">"ក្នុងអំឡុងពេលហៅ ជូនដំណឹងដល់ខ្ញុំអំពីការហៅចូល"</string>
- <string name="call_forwarding_settings" msgid="8937130467468257671">"កំណត់ការហៅបញ្ជូនបន្ត"</string>
- <string name="call_forwarding_settings_with_label" msgid="2345432813399564272">"ការកំណត់ការបញ្ជូនការហៅបន្ត (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
+ <string name="call_forwarding_settings" msgid="8937130467468257671">"ការកំណត់ការបញ្ជូនបន្តការហៅទូរសព្ទ"</string>
+ <string name="call_forwarding_settings_with_label" msgid="2345432813399564272">"ការកំណត់ការបញ្ជូនបន្តការហៅទូរសព្ទ (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="labelCF" msgid="3578719437928476078">"បញ្ជូនការហៅបន្ត"</string>
<string name="labelCFU" msgid="8870170873036279706">"បញ្ជូនបន្តជានិច្ច"</string>
<string name="messageCFU" msgid="1361806450979589744">"ប្រើលេខនេះជានិច្ច"</string>
@@ -136,7 +136,7 @@
<string name="call_settings_with_label" msgid="8460230435361579511">"ការកំណត់ (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="error_updating_title" msgid="2024290892676808965">"បញ្ហាការកំណត់ការហៅ"</string>
<string name="reading_settings" msgid="1605904432450871183">"កំពុងអានការកំណត់…"</string>
- <string name="updating_settings" msgid="3650396734816028808">"កំណត់ការធ្វើបច្ចុប្បន្នភាព…"</string>
+ <string name="updating_settings" msgid="3650396734816028808">"កំពុងធ្វើបច្ចុប្បន្នភាពការកំណត់…"</string>
<string name="reverting_settings" msgid="7378668837291012205">"ត្រឡប់ការកំណត់…"</string>
<string name="response_error" msgid="3904481964024543330">"ការឆ្លើយតបដែលមិនរំពឹងទុកពីបណ្ដាញ។"</string>
<string name="exception_error" msgid="330994460090467">"បញ្ហាស៊ីមកាត ឬបណ្ដាញ។"</string>
@@ -306,7 +306,7 @@
<string name="sim_selection_required_pref" msgid="6985901872978341314">"ជម្រើសដែលត្រូវមាន"</string>
<string name="sim_change_data_title" msgid="9142726786345906606">"ប្ដូរស៊ីមទិន្នន័យ?"</string>
<string name="sim_change_data_message" msgid="3567358694255933280">"ប្រើប្រាស់ <xliff:g id="NEW_SIM">%1$s</xliff:g> ជំនួសឲ្យ <xliff:g id="OLD_SIM">%2$s</xliff:g> សម្រាប់ទិន្នន័យទូរសព្ទចល័តដែរឬទេ?"</string>
- <string name="wifi_calling_settings_title" msgid="5800018845662016507">"ការហៅទូរសព្ទតាម Wi-Fi"</string>
+ <string name="wifi_calling_settings_title" msgid="5800018845662016507">"ការហៅតាម Wi-Fi"</string>
<string name="video_calling_settings_title" msgid="342829454913266078">"ការហៅវីដេអូតាមក្រុមផ្ដល់សេវាទូរសព្ទ"</string>
<string name="gsm_umts_options" msgid="4968446771519376808">"ជម្រើស GSM/UMTS"</string>
<string name="cdma_options" msgid="3669592472226145665">"ជម្រើស CDMA"</string>
@@ -521,7 +521,7 @@
<string name="card_title_conf_call" msgid="901197309274457427">"ការហៅជាក្រុម"</string>
<string name="card_title_incoming_call" msgid="881424648458792430">"ការហៅចូល"</string>
<string name="card_title_call_ended" msgid="650223980095026340">"បានបញ្ចប់ការហៅ"</string>
- <string name="card_title_on_hold" msgid="9028319436626975207">"រង់ចាំ"</string>
+ <string name="card_title_on_hold" msgid="9028319436626975207">"កំពុងរង់ចាំ"</string>
<string name="card_title_hanging_up" msgid="814874106866647871">"បញ្ចប់ការសន្ទនា"</string>
<string name="card_title_in_call" msgid="8231896539567594265">"ការហៅចូល"</string>
<string name="notification_voicemail_title" msgid="3932876181831601351">"សារជាសំឡេងថ្មី"</string>
@@ -572,7 +572,7 @@
<string name="dialerKeyboardHintText" msgid="1115266533703764049">"ប្រើក្ដារចុចដើម្បីចុចលេខ"</string>
<string name="onscreenHoldText" msgid="4025348842151665191">"ដាក់ឱ្យរង់ចាំ"</string>
<string name="onscreenEndCallText" msgid="6138725377654842757">"បញ្ចប់"</string>
- <string name="onscreenShowDialpadText" msgid="658465753816164079">"បន្ទះលេខ"</string>
+ <string name="onscreenShowDialpadText" msgid="658465753816164079">"ផ្ទាំងចុចលេខ"</string>
<string name="onscreenMuteText" msgid="5470306116733843621">"ស្ងាត់"</string>
<string name="onscreenAddCallText" msgid="9075675082903611677">"បន្ថែមការហៅ"</string>
<string name="onscreenMergeCallsText" msgid="3692389519611225407">"បញ្ចូលការហៅរួមគ្នា"</string>
@@ -853,7 +853,7 @@
<string name="radio_info_ims_reg_status" msgid="25582845222446390">"ការចុះឈ្មោះ IMS៖ <xliff:g id="STATUS">%1$s</xliff:g>\nការហៅជាសំឡេងតាម LTE៖ <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nការហៅជាសំឡេងតាម WiFi៖ <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nការហៅជាវីដេអូ៖ <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nផ្ទៃ UT ៖ <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
<string name="radioInfo_service_in" msgid="45753418231446400">"កំពុងដំណើរការ"</string>
<string name="radioInfo_service_out" msgid="287972405416142312">"មិនដំណើរការ"</string>
- <string name="radioInfo_service_emergency" msgid="4763879891415016848">"សម្រាប់តែការហៅទៅលេខសង្គ្រោះបន្ទាន់ប៉ុណ្ណោះ"</string>
+ <string name="radioInfo_service_emergency" msgid="4763879891415016848">"ការហៅទៅលេខសង្គ្រោះបន្ទាន់តែប៉ុណ្ណោះ"</string>
<string name="radioInfo_service_off" msgid="3456583511226783064">"វិទ្យុបានបិទ"</string>
<string name="radioInfo_roaming_in" msgid="3156335577793145965">"រ៉ូមីង"</string>
<string name="radioInfo_roaming_not" msgid="1904547918725478110">"មិនរ៉ូមីងទេ"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"លេខសម្គាល់រងរបស់ស៊ីមទិន្នន័យលំនាំដើម៖"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"កម្រិតបញ្ជូន DL (kbps) ៖"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"កម្រិតបញ្ជូន UL (kbps) ៖"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"ព័ត៌មានទីតាំងទូរសព្ទចល័ត (បានបញ្ឈប់)៖"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"ការកំណត់រចនាសម្ព័ន្ធបណ្ដាញរូបវ័ន្ត LTE ៖"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"អត្រាផ្ទុកឡើងវិញនៃព័ត៌មានទូរសព្ទចល័ត៖"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ព័ត៌មានវាស់ទូរសព្ទចល័តទាំងអស់៖"</string>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 176d812..6f92cfd 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -136,7 +136,7 @@
<string name="call_settings_with_label" msgid="8460230435361579511">"ಸೆಟ್ಟಿಂಗ್ಗಳು (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="error_updating_title" msgid="2024290892676808965">"ಕರೆ ಸೆಟ್ಟಿಂಗ್ಗಳ ದೋಷ"</string>
<string name="reading_settings" msgid="1605904432450871183">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಓದಲಾಗುತ್ತಿದೆ…"</string>
- <string name="updating_settings" msgid="3650396734816028808">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ನವೀಕರಿಸಲಾಗುತ್ತಿದೆ…"</string>
+ <string name="updating_settings" msgid="3650396734816028808">"ಸೆಟ್ಟಿಂಗ್ಗಳು ಅಪ್ಡೇಟ್ ಆಗುತ್ತಿವೆ…"</string>
<string name="reverting_settings" msgid="7378668837291012205">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಹಿಂತಿರುಗಿಸಲಾಗುತ್ತಿದೆ…"</string>
<string name="response_error" msgid="3904481964024543330">"ನೆಟ್ವರ್ಕ್ನಿಂದ ಅನಿರೀಕ್ಷಿತ ಪ್ರತಿಕ್ರಿಯೆ."</string>
<string name="exception_error" msgid="330994460090467">"ನೆಟ್ವರ್ಕ್ ಅಥವಾ ಸಿಮ್ ಕಾರ್ಡ್ ದೋಷ."</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ಡೀಫಾಲ್ಟ್ ಡೇಟಾ ಸಿಮ್ನ ವಿಷಯಐಡಿ:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL ಬ್ಯಾಂಡ್ವಿಡ್ತ್ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL ಬ್ಯಾಂಡ್ವಿಡ್ತ್ (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"ಸೆಲ್ ಸ್ಥಳ ಮಾಹಿತಿ (ತಡೆಹಿಡಿಯಲಾಗಿದೆ):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ಭೌತಿಕ ಚಾನೆಲ್ ಕಾನ್ಫಿಗರೇಶನ್:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ಸೆಲ್ ಮಾಹಿತಿ ರಿಫ್ರೆಶ್ ದರ:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ಎಲ್ಲಾ ಸೆಲ್ ಮಾಪನ ಮಾಹಿತಿ:"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 56bb019..94dfa8f 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -519,7 +519,7 @@
<string name="card_title_dialing" msgid="8742182654254431781">"전화 거는 중"</string>
<string name="card_title_redialing" msgid="18130232613559964">"재다이얼 중"</string>
<string name="card_title_conf_call" msgid="901197309274457427">"다자간 통화"</string>
- <string name="card_title_incoming_call" msgid="881424648458792430">"수신전화"</string>
+ <string name="card_title_incoming_call" msgid="881424648458792430">"수신 전화"</string>
<string name="card_title_call_ended" msgid="650223980095026340">"통화 종료됨"</string>
<string name="card_title_on_hold" msgid="9028319436626975207">"대기 중"</string>
<string name="card_title_hanging_up" msgid="814874106866647871">"전화 끊는 중"</string>
@@ -580,7 +580,7 @@
<string name="onscreenManageCallsText" msgid="1162047856081836469">"통화 관리"</string>
<string name="onscreenManageConferenceText" msgid="4700574060601755137">"다자간 통화 관리"</string>
<string name="onscreenAudioText" msgid="7224226735052019986">"오디오"</string>
- <string name="onscreenVideoCallText" msgid="1743992456126258698">"화상 통화"</string>
+ <string name="onscreenVideoCallText" msgid="1743992456126258698">"영상 통화"</string>
<string name="importSimEntry" msgid="3892354284082689894">"가져오기"</string>
<string name="importAllSimEntries" msgid="2628391505643564007">"모두 가져오기"</string>
<string name="importingSimContacts" msgid="4995457122107888932">"SIM 주소록 가져오는 중"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"기본 데이터 SIM의 subId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL 대역폭(kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL 대역폭(kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"셀 위치 정보(사용 중단됨):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE 물리적 채널 구성:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"셀 정보 새로고침 빈도:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"모든 셀 측정 정보:"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 03946a3..a9c8a83 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -48,7 +48,7 @@
<string name="no_vm_number_msg" msgid="5165161462411372504">"SIM-картада сакталган үн почтасынын номери жок."</string>
<string name="add_vm_number_str" msgid="7368168964435881637">"Номер кошуу"</string>
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Үн почта жөндөөлөрүн алгачкы колдонуучу гана өзгөртө алат."</string>
- <string name="puk_unlocked" msgid="4627340655215746511">"SIM-картаңыз бөгөттөн чыгарылган. Телефонуңуздун кулпусу ачылууда…"</string>
+ <string name="puk_unlocked" msgid="4627340655215746511">"SIM картаңыз бөгөттөн чыгарылган. Телефонуңуздун кулпусу ачылууда…"</string>
<string name="label_ndp" msgid="7617392683877410341">"SIM-карта тармагынын кулпусун ачуучу PIN код"</string>
<string name="label_phoneid" msgid="8775611434123577808">"SIM-карта оператор үчүн кулпуланган"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Кулпусун ачуу"</string>
@@ -178,7 +178,7 @@
<string name="empty_networks_list" msgid="9216418268008582342">"Эч тармак табылган жок."</string>
<string name="network_query_error" msgid="3862515805115145124">"Тармактар табылбай койду. Кайталап көрүңүз."</string>
<string name="register_on_network" msgid="4194770527833960423">"<xliff:g id="NETWORK">%s</xliff:g> тармагына катталууда…"</string>
- <string name="not_allowed" msgid="8541221928746104798">"Сиздин SIM-картаңыз бул түйүнгө кошулганга жол бербейт."</string>
+ <string name="not_allowed" msgid="8541221928746104798">"Сиздин SIM картаңыз бул түйүнгө кошулганга жол бербейт."</string>
<string name="connect_later" msgid="1950138106010005425">"Бул түйүнгө азыр кошулуу мүмкүн эмес. Бир аздан соң кайра аракеттениңиз."</string>
<string name="registration_done" msgid="5337407023566953292">"Тармакка катталды."</string>
<string name="already_auto" msgid="8607068290733079336">"Мурунтан эле автоматтык түрдө тандоодо."</string>
@@ -472,9 +472,9 @@
<string name="delete_fdn_contact" msgid="7027405651994507077">"Туруктуу терүү номерин жок кылуу"</string>
<string name="deleting_fdn_contact" msgid="6872320570844460428">"Туруктуу терүү номери жок кылынууда…"</string>
<string name="fdn_contact_deleted" msgid="1680714996763848838">"Туруктуу терүү номери өчүрүлдү."</string>
- <string name="pin2_invalid" msgid="2313954262684494442">"БНТ жаңыртылган жок, анткени туура эмес PIN-код киргизилди."</string>
- <string name="fdn_invalid_number" msgid="9067189814657840439">"Уруксат берилген номер жаңыртылган жок, себеби жазылган номердин саны <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g> ашпашы керек."</string>
- <string name="pin2_or_fdn_invalid" msgid="7542639487955868181">"БНТ жаңыртылган жок. PIN2 туура эмес, же телефон номуру жараксыз."</string>
+ <string name="pin2_invalid" msgid="2313954262684494442">"БНТ жаңырган жок, анткени туура эмес PIN-код киргизилди."</string>
+ <string name="fdn_invalid_number" msgid="9067189814657840439">"Уруксат берилген номер жаңырган жок, себеби жазылган номердин саны <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g> ашпашы керек."</string>
+ <string name="pin2_or_fdn_invalid" msgid="7542639487955868181">"БНТ жаңырган жок. PIN2 туура эмес, же телефон номуру жараксыз."</string>
<string name="fdn_failed" msgid="216592346853420250">"БНТ иши кыйрады."</string>
<string name="simContacts_emptyLoading" msgid="4989040293858675483">"SIM-картадан окулууда…"</string>
<string name="simContacts_empty" msgid="1135632055473689521">"SIM картаңызда байланыштар жок."</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Демейки оператордун SIM картасынын көз салуу идентификатору:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL өткөрүү жөндөмдүүлүгү (кб/сек.):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL өткөрүү жөндөмдүүлүгү (кб/сек.):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Уюлдук тармакта жайгашкан жери тууралуу маалымат (жоюлган):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE физикалык каналынын конфигурациясы:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Уюлдук маалыматты жаңылоо ылдамдыгы:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Уюлдук чен-өлчөм маалыматтары:"</string>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 4806481..e106463 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -50,8 +50,7 @@
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"ການຕັ້ງຄ່າຂໍ້ຄວາມສຽງສາມາດແກ້ໄຂໄດ້ໂດຍຜູ້ໃຊ້ຫຼັກເທົ່ານັ້ນ."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"ຍົກເລີກການປິດກັ້ນ SIM card ຂອງທ່ານແລ້ວ. ໂທລະສັບຂອງທ່ານກຳລັງຖືກປົດລັອກ..."</string>
<string name="label_ndp" msgid="7617392683877410341">"PIN ປົດລັອກເຄືອຂ່າຍ SIM"</string>
- <!-- no translation found for label_phoneid (8775611434123577808) -->
- <skip />
+ <string name="label_phoneid" msgid="8775611434123577808">"ລັອກ SIM ສຳລັບຜູ້ໃຫ້ບໍລິການແລ້ວ"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"ປົດລັອກ"</string>
<string name="sim_ndp_dismiss_text" msgid="89667342248929777">"ປິດໄວ້"</string>
<string name="requesting_unlock" msgid="930512210309437741">"ກຳລັງຮ້ອງຂໍການປົດລັອກເຄືອຂ່າຍ..."</string>
@@ -876,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId ຂອງຊິມອິນເຕີເນັດເລີ່ມຕົ້ນ:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"ແບນວິດ DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"ແບນວິດ UL (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"ຂໍ້ມູນສະຖານທີ່ມືຖື (ສິ້ນສຸດການສະໜັບສະໜຸນແລ້ວ):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"ການຕັ້ງຄ່າຊ່ອງ LTE ກາຍະພາບ:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ອັດຕາການໂຫຼດຄືນໃໝ່ຂອງຂໍ້ມູນມືຖື:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ຂໍ້ມູນການວັດແທກມືຖືທັງໝົດ:"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index d12bb62..7af54c0 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -135,7 +135,7 @@
<string name="call_settings_admin_user_only" msgid="7238947387649986286">"Skambučių nustatymus gali keisti tik administruojantis naudotojas."</string>
<string name="call_settings_with_label" msgid="8460230435361579511">"Nustatymai (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="error_updating_title" msgid="2024290892676808965">"Skambinimo nustatymų klaida"</string>
- <string name="reading_settings" msgid="1605904432450871183">"Skaitomi nustatymai..."</string>
+ <string name="reading_settings" msgid="1605904432450871183">"Analizuojami nustatymai..."</string>
<string name="updating_settings" msgid="3650396734816028808">"Atnaujinami nustatymai..."</string>
<string name="reverting_settings" msgid="7378668837291012205">"Grąžinami nustatymai…"</string>
<string name="response_error" msgid="3904481964024543330">"Netikėtas atsakas iš tinklo."</string>
@@ -883,7 +883,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Numatytųjų duomenų SIM kortelės papildomas ID:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL pralaidumas (Kb/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL pralaidumas (Kb/s):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Mobiliojo ryšio vietovės informacija (nebenaudojama):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE fizinio kanalo konfigūracija:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobiliojo ryšio informacijos atnaujinimo dažnis:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Visų mobiliųjų ryšių įvertinimo informacija:"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index a5b9eb8..12af068 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -50,8 +50,7 @@
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Tikai galvenais lietotājs var mainīt balss pasta iestatījumus."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"SIM karte ir atbloķēta. Notiek tālruņa atbloķēšana..."</string>
<string name="label_ndp" msgid="7617392683877410341">"SIM tīkla atbloķēšanas PIN"</string>
- <!-- no translation found for label_phoneid (8775611434123577808) -->
- <skip />
+ <string name="label_phoneid" msgid="8775611434123577808">"SIM karte ir bloķēta operatoram"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Atbloķēt"</string>
<string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Noraidīt"</string>
<string name="requesting_unlock" msgid="930512210309437741">"Notiek tīkla atbloķēšanas pieprasīšana..."</string>
@@ -879,7 +878,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Noklusējuma datu SIM kartes papildu ID:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL joslas platums (kb/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL joslas platums (kb/s):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Mobilā tālruņa atrašanās vietas informācija (novecojusi):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE fiziskā kanāla konfigurācija:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobilā tīkla informācijas atsvaidzināšanas biežums:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Visa mobilā tīkla mērījumu informācija:"</string>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index d48b078..ed3a16a 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -176,7 +176,7 @@
<string name="label_available" msgid="1316084116670821258">"Достапни мрежи"</string>
<string name="load_networks_progress" msgid="4051433047717401683">"Се пребарува..."</string>
<string name="empty_networks_list" msgid="9216418268008582342">"Не се пронајдени мрежи."</string>
- <string name="network_query_error" msgid="3862515805115145124">"Не можеше да се најдат мрежи. Обидете се повторно."</string>
+ <string name="network_query_error" msgid="3862515805115145124">"Не може да се најдат мрежи. Обидете се повторно."</string>
<string name="register_on_network" msgid="4194770527833960423">"Регистрирање на <xliff:g id="NETWORK">%s</xliff:g>..."</string>
<string name="not_allowed" msgid="8541221928746104798">"Вашата SIM картичка не дозволува поврзување со оваа мрежа."</string>
<string name="connect_later" msgid="1950138106010005425">"Не може да се поврзе со оваа мрежа во моментов. Обидете се повторно подоцна."</string>
@@ -194,7 +194,7 @@
<string name="network_disconnected" msgid="8844141106841160825">"Исклучено"</string>
<string name="network_connected" msgid="2760235679963580224">"Поврзано"</string>
<string name="network_connecting" msgid="160901383582774987">"Се поврзува…"</string>
- <string name="network_could_not_connect" msgid="6547460848093727998">"Не можеше да се поврзе"</string>
+ <string name="network_could_not_connect" msgid="6547460848093727998">"Не може да се поврзе"</string>
<string-array name="preferred_network_mode_choices">
<item msgid="4531933377509551889">"Претпочитан: GSM/WCDMA"</item>
<item msgid="5120532750027435355">"Само GSM"</item>
@@ -620,7 +620,7 @@
<string name="ota_listen" msgid="2772252405488894280">"Следете ги гласовните упатства додека не слушнете дека активацијата е завршена."</string>
<string name="ota_speaker" msgid="1086766980329820528">"Звучник"</string>
<string name="ota_progress" msgid="8837259285255700132">"Телефонот се програмира…"</string>
- <string name="ota_failure" msgid="5674217489921481576">"Телефонот не можеше да се програмира"</string>
+ <string name="ota_failure" msgid="5674217489921481576">"Телефонот не може да се програмира"</string>
<string name="ota_successful" msgid="1106825981548107774">"Вашиот телефон е сега активиран. Може да поминат и до 15 минути за услугата да започне."</string>
<string name="ota_unsuccessful" msgid="8531037653803955754">"Вашиот телефон не се активираше. \nМожеби ќе треба да најде област со подобра покриеност (во близина на прозорец или надвор). \n\nОбидете се повторно или јавете се во служба за услуги на клиенти за повеќе опции."</string>
<string name="ota_spc_failure" msgid="904092035241370080">"ВИШОК SPC ГРЕШКИ"</string>
@@ -719,54 +719,54 @@
<string name="clh_callFailed_simError_txt" msgid="5128538525762326413">"Не може да се пристапи до SIM-картичката"</string>
<string name="clh_incall_error_out_of_service_txt" msgid="2736010617446749869">"Мобилната мрежа не е достапна"</string>
<string name="clh_callFailed_unassigned_number_txt" msgid="141967660286695682">"Проблем со телефонскиот број што се обидувате да го бирате. Код за грешка: 1."</string>
- <string name="clh_callFailed_no_route_to_destination_txt" msgid="4805015149822352308">"Повикот не можеше да се заврши. Код за грешка: 3."</string>
- <string name="clh_callFailed_channel_unacceptable_txt" msgid="4062754579408613021">"Повикот не можеше да се заврши. Код за грешка: 6."</string>
- <string name="clh_callFailed_operator_determined_barring_txt" msgid="4202077821465974286">"Повикот не можеше да се заврши. Код за грешка: 8."</string>
- <string name="clh_callFailed_normal_call_clearing_txt" msgid="5677987959062976462">"Повикот не можеше да се заврши. Код за грешка: 16."</string>
+ <string name="clh_callFailed_no_route_to_destination_txt" msgid="4805015149822352308">"Повикот не може да се заврши. Код за грешка: 3."</string>
+ <string name="clh_callFailed_channel_unacceptable_txt" msgid="4062754579408613021">"Повикот не може да се заврши. Код за грешка: 6."</string>
+ <string name="clh_callFailed_operator_determined_barring_txt" msgid="4202077821465974286">"Повикот не може да се заврши. Код за грешка: 8."</string>
+ <string name="clh_callFailed_normal_call_clearing_txt" msgid="5677987959062976462">"Повикот не може да се заврши. Код за грешка: 16."</string>
<string name="clh_callFailed_user_busy_txt" msgid="8886432858568086854">"Корисникот е зафатен"</string>
<string name="clh_callFailed_no_user_responding_txt" msgid="341100226919865128">"Корисникот не одговара"</string>
- <string name="clh_callFailed_user_alerting_txt" msgid="896082976264427969">"Повикот не можеше да се заврши. Код за грешка: 19."</string>
+ <string name="clh_callFailed_user_alerting_txt" msgid="896082976264427969">"Повикот не може да се заврши. Код за грешка: 19."</string>
<string name="clh_callFailed_call_rejected_txt" msgid="3439435671153341709">"Повикот е одбиен"</string>
<string name="clh_callFailed_number_changed_txt" msgid="2868476949771441667">"Бројот е променет"</string>
- <string name="clh_callFailed_pre_emption_txt" msgid="8887998866342162724">"Повикот не можеше да се заврши. Код за грешка: 25."</string>
- <string name="clh_callFailed_non_selected_user_clearing_txt" msgid="4804529874810197550">"Повикот не можеше да се заврши. Код за грешка: 26."</string>
- <string name="clh_callFailed_destination_out_of_order_txt" msgid="1130697076352728824">"Повикот не можеше да се заврши. Код за грешка: 27."</string>
+ <string name="clh_callFailed_pre_emption_txt" msgid="8887998866342162724">"Повикот не може да се заврши. Код за грешка: 25."</string>
+ <string name="clh_callFailed_non_selected_user_clearing_txt" msgid="4804529874810197550">"Повикот не може да се заврши. Код за грешка: 26."</string>
+ <string name="clh_callFailed_destination_out_of_order_txt" msgid="1130697076352728824">"Повикот не може да се заврши. Код за грешка: 27."</string>
<string name="clh_callFailed_invalid_number_format_txt" msgid="3171016382987224989">"Неважечки формат на број (нецелосен број)"</string>
- <string name="clh_callFailed_facility_rejected_txt" msgid="1054386430010898993">"Повикот не можеше да се заврши. Код за грешка: 29."</string>
- <string name="clh_callFailed_response_to_STATUS_ENQUIRY_txt" msgid="2763172551412307536">"Повикот не можеше да се заврши. Код за грешка: 30."</string>
- <string name="clh_callFailed_normal_unspecified_txt" msgid="978119938935737419">"Повикот не можеше да се заврши. Код за грешка: 31."</string>
- <string name="clh_callFailed_no_circuit_available_txt" msgid="1519684050419134605">"Повикот не можеше да се заврши. Код за грешка: 34."</string>
- <string name="clh_callFailed_network_out_of_order_txt" msgid="8689826504394592289">"Повикот не можеше да се заврши. Код за грешка: 38."</string>
- <string name="clh_callFailed_temporary_failure_txt" msgid="5065091554509067874">"Повикот не можеше да се заврши. Код за грешка: 41."</string>
- <string name="clh_callFailed_switching_equipment_congestion_txt" msgid="8681599376741988769">"Повикот не можеше да се заврши. Код за грешка: 42."</string>
- <string name="clh_callFailed_access_information_discarded_txt" msgid="2476199425130545428">"Повикот не можеше да се заврши. Код за грешка: 43."</string>
- <string name="clh_callFailed_requested_circuit_txt" msgid="7497497808928490219">"Повикот не можеше да се заврши. Код за грешка: 44."</string>
- <string name="clh_callFailed_resources_unavailable_unspecified_txt" msgid="144010529672928445">"Повикот не можеше да се заврши. Код за грешка: 47."</string>
- <string name="clh_callFailed_quality_of_service_unavailable_txt" msgid="4650329342288289290">"Повикот не можеше да се заврши. Код за грешка: 49."</string>
- <string name="clh_callFailed_requested_facility_not_subscribed_txt" msgid="9107977008516882170">"Повикот не можеше да се заврши. Код за грешка: 50."</string>
- <string name="clh_callFailed_incoming_calls_barred_within_the_CUG_txt" msgid="501037491908315591">"Повикот не можеше да се заврши. Код за грешка: 55."</string>
- <string name="clh_callFailed_bearer_capability_not_authorized_txt" msgid="4344366517528362620">"Повикот не можеше да се заврши. Код за грешка: 57."</string>
- <string name="clh_callFailed_bearer_capability_not_presently_available_txt" msgid="1436957294571545381">"Повикот не можеше да се заврши. Код за грешка: 58."</string>
- <string name="clh_callFailed_service_or_option_not_available_unspecified_txt" msgid="2149878874722675428">"Повикот не можеше да се заврши. Код за грешка: 63."</string>
- <string name="clh_callFailed_bearer_service_not_implemented_txt" msgid="1074983013965612410">"Повикот не можеше да се заврши. Код за грешка: 65."</string>
- <string name="clh_callFailed_ACM_equal_to_or_greater_than_ACMmax_txt" msgid="7889034195264205333">"Повикот не можеше да се заврши. Код за грешка: 68."</string>
- <string name="clh_callFailed_requested_facility_not_implemented_txt" msgid="7996646684699167978">"Повикот не можеше да се заврши. Код за грешка: 69."</string>
- <string name="clh_callFailed_only_restricted_digital_information_bearer_capability_is_available_txt" msgid="2358958110447385682">"Повикот не можеше да се заврши. Код за грешка: 70."</string>
- <string name="clh_callFailed_service_or_option_not_implemented_unspecified_txt" msgid="3046428509531159481">"Повикот не можеше да се заврши. Код за грешка: 79."</string>
- <string name="clh_callFailed_invalid_transaction_identifier_value_txt" msgid="1727401871777396619">"Повикот не можеше да се заврши. Код за грешка: 81."</string>
- <string name="clh_callFailed_user_not_member_of_CUG_txt" msgid="442282135105229307">"Повикот не можеше да се заврши. Код за грешка: 87."</string>
- <string name="clh_callFailed_incompatible_destination_txt" msgid="5900394706344969020">"Повикот не можеше да се заврши. Код за грешка: 88."</string>
- <string name="clh_callFailed_invalid_transit_network_selection_txt" msgid="6274621838349037741">"Повикот не можеше да се заврши. Код за грешка: 91."</string>
- <string name="clh_callFailed_semantically_incorrect_message_txt" msgid="7000705190197981937">"Повикот не можеше да се заврши. Код за грешка: 95."</string>
- <string name="clh_callFailed_invalid_mandatory_information_txt" msgid="3609204152671052123">"Повикот не можеше да се заврши. Код за грешка: 96."</string>
- <string name="clh_callFailed_message_type_non_existent_or_not_implemented_txt" msgid="1552110431052032814">"Повикот не можеше да се заврши. Код за грешка: 97."</string>
- <string name="clh_callFailed_message_type_not_compatible_with_protocol_state_txt" msgid="7717048934226300032">"Повикот не можеше да се заврши. Код за грешка: 98."</string>
- <string name="clh_callFailed_information_element_non_existent_or_not_implemented_txt" msgid="8931396541061612169">"Повикот не можеше да се заврши. Код за грешка: 99."</string>
- <string name="clh_callFailed_conditional_IE_error_txt" msgid="4630685477888727741">"Повикот не можеше да се заврши. Код за грешка: 100."</string>
- <string name="clh_callFailed_message_not_compatible_with_protocol_state_txt" msgid="3014075977395922947">"Повикот не можеше да се заврши. Код за грешка: 101."</string>
- <string name="clh_callFailed_recovery_on_timer_expiry_txt" msgid="5637581978978731672">"Повикот не можеше да се заврши. Код за грешка: 102."</string>
- <string name="clh_callFailed_protocol_Error_unspecified_txt" msgid="9203320572562697755">"Повикот не можеше да се заврши. Код за грешка: 111."</string>
- <string name="clh_callFailed_interworking_unspecified_txt" msgid="7969686413930847182">"Повикот не можеше да се заврши. Код за грешка: 127."</string>
+ <string name="clh_callFailed_facility_rejected_txt" msgid="1054386430010898993">"Повикот не може да се заврши. Код за грешка: 29."</string>
+ <string name="clh_callFailed_response_to_STATUS_ENQUIRY_txt" msgid="2763172551412307536">"Повикот не може да се заврши. Код за грешка: 30."</string>
+ <string name="clh_callFailed_normal_unspecified_txt" msgid="978119938935737419">"Повикот не може да се заврши. Код за грешка: 31."</string>
+ <string name="clh_callFailed_no_circuit_available_txt" msgid="1519684050419134605">"Повикот не може да се заврши. Код за грешка: 34."</string>
+ <string name="clh_callFailed_network_out_of_order_txt" msgid="8689826504394592289">"Повикот не може да се заврши. Код за грешка: 38."</string>
+ <string name="clh_callFailed_temporary_failure_txt" msgid="5065091554509067874">"Повикот не може да се заврши. Код за грешка: 41."</string>
+ <string name="clh_callFailed_switching_equipment_congestion_txt" msgid="8681599376741988769">"Повикот не може да се заврши. Код за грешка: 42."</string>
+ <string name="clh_callFailed_access_information_discarded_txt" msgid="2476199425130545428">"Повикот не може да се заврши. Код за грешка: 43."</string>
+ <string name="clh_callFailed_requested_circuit_txt" msgid="7497497808928490219">"Повикот не може да се заврши. Код за грешка: 44."</string>
+ <string name="clh_callFailed_resources_unavailable_unspecified_txt" msgid="144010529672928445">"Повикот не може да се заврши. Код за грешка: 47."</string>
+ <string name="clh_callFailed_quality_of_service_unavailable_txt" msgid="4650329342288289290">"Повикот не може да се заврши. Код за грешка: 49."</string>
+ <string name="clh_callFailed_requested_facility_not_subscribed_txt" msgid="9107977008516882170">"Повикот не може да се заврши. Код за грешка: 50."</string>
+ <string name="clh_callFailed_incoming_calls_barred_within_the_CUG_txt" msgid="501037491908315591">"Повикот не може да се заврши. Код за грешка: 55."</string>
+ <string name="clh_callFailed_bearer_capability_not_authorized_txt" msgid="4344366517528362620">"Повикот не може да се заврши. Код за грешка: 57."</string>
+ <string name="clh_callFailed_bearer_capability_not_presently_available_txt" msgid="1436957294571545381">"Повикот не може да се заврши. Код за грешка: 58."</string>
+ <string name="clh_callFailed_service_or_option_not_available_unspecified_txt" msgid="2149878874722675428">"Повикот не може да се заврши. Код за грешка: 63."</string>
+ <string name="clh_callFailed_bearer_service_not_implemented_txt" msgid="1074983013965612410">"Повикот не може да се заврши. Код за грешка: 65."</string>
+ <string name="clh_callFailed_ACM_equal_to_or_greater_than_ACMmax_txt" msgid="7889034195264205333">"Повикот не може да се заврши. Код за грешка: 68."</string>
+ <string name="clh_callFailed_requested_facility_not_implemented_txt" msgid="7996646684699167978">"Повикот не може да се заврши. Код за грешка: 69."</string>
+ <string name="clh_callFailed_only_restricted_digital_information_bearer_capability_is_available_txt" msgid="2358958110447385682">"Повикот не може да се заврши. Код за грешка: 70."</string>
+ <string name="clh_callFailed_service_or_option_not_implemented_unspecified_txt" msgid="3046428509531159481">"Повикот не може да се заврши. Код за грешка: 79."</string>
+ <string name="clh_callFailed_invalid_transaction_identifier_value_txt" msgid="1727401871777396619">"Повикот не може да се заврши. Код за грешка: 81."</string>
+ <string name="clh_callFailed_user_not_member_of_CUG_txt" msgid="442282135105229307">"Повикот не може да се заврши. Код за грешка: 87."</string>
+ <string name="clh_callFailed_incompatible_destination_txt" msgid="5900394706344969020">"Повикот не може да се заврши. Код за грешка: 88."</string>
+ <string name="clh_callFailed_invalid_transit_network_selection_txt" msgid="6274621838349037741">"Повикот не може да се заврши. Код за грешка: 91."</string>
+ <string name="clh_callFailed_semantically_incorrect_message_txt" msgid="7000705190197981937">"Повикот не може да се заврши. Код за грешка: 95."</string>
+ <string name="clh_callFailed_invalid_mandatory_information_txt" msgid="3609204152671052123">"Повикот не може да се заврши. Код за грешка: 96."</string>
+ <string name="clh_callFailed_message_type_non_existent_or_not_implemented_txt" msgid="1552110431052032814">"Повикот не може да се заврши. Код за грешка: 97."</string>
+ <string name="clh_callFailed_message_type_not_compatible_with_protocol_state_txt" msgid="7717048934226300032">"Повикот не може да се заврши. Код за грешка: 98."</string>
+ <string name="clh_callFailed_information_element_non_existent_or_not_implemented_txt" msgid="8931396541061612169">"Повикот не може да се заврши. Код за грешка: 99."</string>
+ <string name="clh_callFailed_conditional_IE_error_txt" msgid="4630685477888727741">"Повикот не може да се заврши. Код за грешка: 100."</string>
+ <string name="clh_callFailed_message_not_compatible_with_protocol_state_txt" msgid="3014075977395922947">"Повикот не може да се заврши. Код за грешка: 101."</string>
+ <string name="clh_callFailed_recovery_on_timer_expiry_txt" msgid="5637581978978731672">"Повикот не може да се заврши. Код за грешка: 102."</string>
+ <string name="clh_callFailed_protocol_Error_unspecified_txt" msgid="9203320572562697755">"Повикот не може да се заврши. Код за грешка: 111."</string>
+ <string name="clh_callFailed_interworking_unspecified_txt" msgid="7969686413930847182">"Повикот не може да се заврши. Код за грешка: 127."</string>
<string name="labelCallBarring" msgid="4180377113052853173">"Забрана на повик"</string>
<string name="sum_call_barring_enabled" msgid="5184331188926370824">"Вклучено"</string>
<string name="sum_call_barring_disabled" msgid="5699448000600153096">"Исклучено"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SUBID на стандардната SIM за мобилен интернет:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Брзина на пренос при преземање (кбит/с):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Брзина на пренос при прикачување (кбит/с):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Информации за локација на мобилен (неподдржано):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Конфигурација на физички канал на LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Стапка на освежување на информациите за мобилниот:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Сите информации за мерењата на мобилниот:"</string>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 17b7077..daaa13e7 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -96,11 +96,11 @@
<string name="sum_loading_settings" msgid="434063780286688775">"ക്രമീകരണങ്ങൾ ലോഡുചെയ്യുന്നു…"</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"ഔട്ട്ഗോയിംഗ് കോളുകളിൽ നമ്പർ മറച്ചിരിക്കുന്നു"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"ഔട്ട്ഗോയിംഗ് കോളുകളിൽ നമ്പർ ദൃശ്യമാക്കിയിരിക്കുന്നു"</string>
- <string name="sum_default_caller_id" msgid="1767070797135682959">"ഔട്ട്ഗോയിംഗ് കോളുകളിൽ എന്റെ നമ്പർ ദൃശ്യമാക്കാൻ സ്ഥിര ഓപ്പറേറ്റർ ക്രമീകരണങ്ങൾ ഉപയോഗിക്കുക"</string>
+ <string name="sum_default_caller_id" msgid="1767070797135682959">"ഔട്ട്ഗോയിംഗ് കോളുകളിൽ എന്റെ നമ്പർ കാണിക്കാൻ ഡിഫോൾട്ട് ഓപ്പറേറ്റർ ക്രമീകരണങ്ങൾ ഉപയോഗിക്കുക"</string>
<string name="labelCW" msgid="8449327023861428622">"കോൾ വെയ്റ്റിംഗ്"</string>
<string name="sum_cw_enabled" msgid="3977308526187139996">"ഒരു കോളിനിടയിൽ, ഇൻകമിംഗ് കോളുകളെക്കുറിച്ച് എന്നെ അറിയിക്കുക"</string>
<string name="sum_cw_disabled" msgid="3658094589461768637">"ഒരു കോളിനിടയിൽ, ഇൻകമിംഗ് കോളുകളെക്കുറിച്ച് എന്നെ അറിയിക്കുക"</string>
- <string name="call_forwarding_settings" msgid="8937130467468257671">"കോൾഫോർവേഡിംഗ് ക്രമീകരണം"</string>
+ <string name="call_forwarding_settings" msgid="8937130467468257671">"കോൾ ഫോർവേഡിംഗ് ക്രമീകരണം"</string>
<string name="call_forwarding_settings_with_label" msgid="2345432813399564272">"കോൾഫോർവേഡിംഗ് ക്രമീകരണം (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="labelCF" msgid="3578719437928476078">"കോൾ ഫോർവേഡിംഗ്"</string>
<string name="labelCFU" msgid="8870170873036279706">"എല്ലായ്പ്പോഴും കൈമാറുക"</string>
@@ -135,8 +135,8 @@
<string name="call_settings_admin_user_only" msgid="7238947387649986286">"അഡ്മിൻ ഉപയോക്താവിന് മാത്രമേ കോൾ ക്രമീകരണം മാറ്റാൻ കഴിയൂ."</string>
<string name="call_settings_with_label" msgid="8460230435361579511">"ക്രമീകരണം (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="error_updating_title" msgid="2024290892676808965">"കോൾ ക്രമീകരണ പിശക്"</string>
- <string name="reading_settings" msgid="1605904432450871183">"ക്രമീകരണങ്ങൾ റീഡുചെയ്യുന്നു.…"</string>
- <string name="updating_settings" msgid="3650396734816028808">"ക്രമീകരണങ്ങൾ അപ്ഡേറ്റുചെയ്യുന്നു…"</string>
+ <string name="reading_settings" msgid="1605904432450871183">"ക്രമീകരണങ്ങൾ റീഡ് ചെയ്യുന്നു.…"</string>
+ <string name="updating_settings" msgid="3650396734816028808">"ക്രമീകരണങ്ങൾ അപ്ഡേറ്റ് ചെയ്യുന്നു…"</string>
<string name="reverting_settings" msgid="7378668837291012205">"ക്രമീകരണങ്ങൾ പഴയപടിയാക്കുന്നു…"</string>
<string name="response_error" msgid="3904481964024543330">"നെറ്റ്വർക്കിൽ നിന്നുള്ള അപ്രതീക്ഷിത പ്രതികരണം."</string>
<string name="exception_error" msgid="330994460090467">"നെറ്റ്വർക്ക് അല്ലെങ്കിൽ സിം കാർഡ് പിശക്."</string>
@@ -530,7 +530,7 @@
<string name="notification_voicemail_no_vm_number" msgid="3423686009815186750">"വോയ്സ്മെയിൽ നമ്പർ അജ്ഞാതമാണ്"</string>
<string name="notification_network_selection_title" msgid="255595526707809121">"സേവനമില്ല"</string>
<string name="notification_network_selection_text" msgid="553288408722427659">"തിരഞ്ഞെടുത്ത നെറ്റ്വർക്ക് (<xliff:g id="OPERATOR_NAME">%s</xliff:g>) ലഭ്യമല്ല"</string>
- <string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"ഒരു കോൾ വിളിക്കാൻ മൊബൈൽ നെറ്റ്വർക്ക് ഓണാക്കുകയോ ഫ്ലൈറ്റ് മോഡ് അല്ലെങ്കിൽ ബാറ്ററി സേവർ മോഡ് ഓഫാക്കുകയോ ചെയ്യുക."</string>
+ <string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"ഒരു കോൾ വിളിക്കാൻ മൊബൈൽ നെറ്റ്വർക്ക് ഓണാക്കുകയോ ഫ്ലൈറ്റ് മോഡ് അല്ലെങ്കിൽ ബാറ്ററി ലാഭിക്കൽ മോഡ് ഓഫാക്കുകയോ ചെയ്യുക."</string>
<string name="incall_error_power_off" product="default" msgid="8131672264311208673">"ഒരു കോൾ വിളിക്കാൻ വിമാന മോഡ് ഓഫാക്കുക."</string>
<string name="incall_error_power_off_wfc" msgid="9125661184694727052">"ഒരു കോൾ വിളിക്കാൻ വിമാന മോഡ് ഓഫാക്കുക അല്ലെങ്കിൽ വയർലെസ്സ് നെറ്റ്വർക്കിലേക്ക് കണക്റ്റുചെയ്യുക."</string>
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"അടിയന്തിരമല്ലാത്ത കോൾ ചെയ്യാൻ അടിയന്തിര കോൾബാക്ക് മോഡിൽ നിന്ന് പുറത്തുകടക്കുക."</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ഡിഫോൾട്ട് ഡാറ്റാ സിമ്മിന്റെ ഉപഐഡി:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL ബാൻഡ്വിത്ത് (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL ബാൻഡ്വിത്ത് (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"സെൽ ലൊക്കേഷൻ വിവരങ്ങൾ (അവസാനിപ്പിച്ചു):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ഫിസിക്കൽ ചാനൽ കോൺഫിഗറേഷൻ:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"സെൽ വിവരങ്ങൾ പുതുക്കിയെടുക്കൽ നിരക്ക്:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"എല്ലാ സെൽ അളവ് വിവരങ്ങളും:"</string>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index 03b799e..c7ecf19 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -31,7 +31,7 @@
<string name="ussdRunning" msgid="1163586813106772717">"USSD код ажиллаж байна…"</string>
<string name="mmiCancelled" msgid="5339191899200678272">"MMI код цуцлагдсан"</string>
<string name="cancel" msgid="8984206397635155197">"Цуцлах"</string>
- <string name="enter_input" msgid="6193628663039958990">"USSD зурвасын үсгийн тоо <xliff:g id="MIN_LEN">%1$d</xliff:g> болон <xliff:g id="MAX_LEN">%2$d</xliff:g> хооронд байх шаардлагатай. Дахин оролдоно уу."</string>
+ <string name="enter_input" msgid="6193628663039958990">"USSD мессежийн үсгийн тоо <xliff:g id="MIN_LEN">%1$d</xliff:g> болон <xliff:g id="MAX_LEN">%2$d</xliff:g> хооронд байх шаардлагатай. Дахин оролдоно уу."</string>
<string name="manageConferenceLabel" msgid="8415044818156353233">"Хурлын дуудлага удирдах"</string>
<string name="ok" msgid="7818974223666140165">"OK"</string>
<string name="audio_mode_speaker" msgid="243689733219312360">"Чанга яригч"</string>
@@ -63,7 +63,7 @@
<string name="labelCdmaMore_with_label" msgid="7759692829160238152">"CDMA дуудлагын тохиргоо (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="apn_settings" msgid="1978652203074756623">"Хандалтын Цэгийн Нэрс"</string>
<string name="settings_label" msgid="9101778088412567956">"Сүлжээний тохиргоо"</string>
- <string name="phone_accounts" msgid="1216879437523774604">"Дуудах бүртгэл"</string>
+ <string name="phone_accounts" msgid="1216879437523774604">"Дуудлагын бүртгэлүүд"</string>
<string name="phone_accounts_make_calls_with" msgid="16747814788918145">"Дараахаар дуудлага хийх"</string>
<string name="phone_accounts_make_sip_calls_with" msgid="4691221006731847255">"Дараахаар SIP дуудлага хийх"</string>
<string name="phone_accounts_ask_every_time" msgid="6192347582666047168">"Эхлэж хандах"</string>
@@ -103,10 +103,10 @@
<string name="call_forwarding_settings" msgid="8937130467468257671">"Дуудлага шилжүүлэх тохиргоо"</string>
<string name="call_forwarding_settings_with_label" msgid="2345432813399564272">"Дуудлага шилжүүлэх тохиргоонууд (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="labelCF" msgid="3578719437928476078">"Дуудлага дамжуулах"</string>
- <string name="labelCFU" msgid="8870170873036279706">"Байнга дамжуулах"</string>
+ <string name="labelCFU" msgid="8870170873036279706">"Байнга шилжүүлэх"</string>
<string name="messageCFU" msgid="1361806450979589744">"Байнга энэ дугаарыг ашиглах"</string>
<string name="sum_cfu_enabled_indicator" msgid="9030139213402432776">"Бүх дуудлагыг дамжуулж байна"</string>
- <string name="sum_cfu_enabled" msgid="5806923046528144526">"Бүх дуудлагыг <xliff:g id="PHONENUMBER">{0}</xliff:g> руу дамжуулж байна"</string>
+ <string name="sum_cfu_enabled" msgid="5806923046528144526">"Бүх дуудлагыг <xliff:g id="PHONENUMBER">{0}</xliff:g> руу шилжүүлж байна"</string>
<string name="sum_cfu_enabled_no_number" msgid="7287752761743377930">"Дугаар холбогдох боломжгүй"</string>
<string name="sum_cfu_disabled" msgid="5010617134210809853">"Идэвхгүй"</string>
<string name="labelCFB" msgid="615265213360512768">"Завгүй бол"</string>
@@ -171,7 +171,7 @@
<string name="vm_change_pin_error_mismatch" msgid="5364847280026257331">"Хуучин PIN таарахгүй байна."</string>
<string name="vm_change_pin_error_invalid" msgid="5230002671175580674">"Шинэ PIN-д буруу тэмдэгт агуулагдаж байна."</string>
<string name="vm_change_pin_error_system_error" msgid="9116483527909681791">"PIN-г өөрчлөх боломжгүй"</string>
- <string name="vvm_unsupported_message_format" msgid="4206402558577739713">"Дэмжигдээгүй зурвасын төрөл, сонсохын тулд <xliff:g id="NUMBER">%s</xliff:g> руу залгана уу."</string>
+ <string name="vvm_unsupported_message_format" msgid="4206402558577739713">"Дэмжигдээгүй мессежийн төрөл, сонсохын тулд <xliff:g id="NUMBER">%s</xliff:g> руу залгана уу."</string>
<string name="network_settings_title" msgid="7560807107123171541">"Мобайл сүлжээ"</string>
<string name="label_available" msgid="1316084116670821258">"Боломжтой сүлжээнүүд"</string>
<string name="load_networks_progress" msgid="4051433047717401683">"Хайж байна..."</string>
@@ -433,7 +433,7 @@
<string name="cdma_activate_device" msgid="5914720276140097632">"Төхөөрөмжийг идэвхжүүлэх"</string>
<string name="cdma_lte_data_service" msgid="359786441782404562">"Дата үйлчилгээний тохиргоо"</string>
<string name="carrier_settings_title" msgid="6292869148169850220">"Операторын тохиргоо"</string>
- <string name="fdn" msgid="2545904344666098749">"Тогтсон Залгах Дугаарууд"</string>
+ <string name="fdn" msgid="2545904344666098749">"Тогтсон залгах дугаарууд"</string>
<string name="fdn_with_label" msgid="6412087553365709494">"Тогтсон Дуудлагын Дугаарууд(<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="manage_fdn_list" msgid="3341716430375195441">"FDN жагсаалт"</string>
<string name="fdn_list_with_label" msgid="1409655283510382556">"FDN жагсаалт (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -539,7 +539,7 @@
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Мобайл сүлжээнд холбогдох боломжгүй байна. Дуудлага хийхийн тулд утасгүй интернетэд холбогдоно уу."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Дуудлага хийхийн тулд хүчин төгөлдөр дугаар оруулна уу."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Дуудлага амжилтгүй болсон."</string>
- <string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Дуудлагыг энэ удаад нэмэх боломжгүй. Та зурвас илгээн холбоо тогтоохыг оролдох боломжтой."</string>
+ <string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Дуудлагыг энэ удаад нэмэх боломжгүй. Та мессеж илгээн холбоо тогтоохыг оролдох боломжтой."</string>
<string name="incall_error_supp_service_unknown" msgid="8751177117194592623">"Үйлчилгээг дэмждэггүй байна"</string>
<string name="incall_error_supp_service_switch" msgid="5272822448189448479">"Дуудлагыг солих боломжгүй байна."</string>
<string name="incall_error_supp_service_resume" msgid="1276861499306817035">"Дуудлагыг үргэлжлүүлэх боломжгүй."</string>
@@ -570,7 +570,7 @@
<string name="fire_type_description" msgid="6565200468934914930">"Гал"</string>
<string name="description_concat_format" msgid="2014471565101724088">"%1$s, %2$s"</string>
<string name="dialerKeyboardHintText" msgid="1115266533703764049">"Залгахдаа гар ашиглах"</string>
- <string name="onscreenHoldText" msgid="4025348842151665191">"Саатуулах"</string>
+ <string name="onscreenHoldText" msgid="4025348842151665191">"Хүлээлгэх"</string>
<string name="onscreenEndCallText" msgid="6138725377654842757">"Дуусгах"</string>
<string name="onscreenShowDialpadText" msgid="658465753816164079">"Диалпад"</string>
<string name="onscreenMuteText" msgid="5470306116733843621">"Дууг хаах"</string>
@@ -590,8 +590,8 @@
<string name="hac_mode_title" msgid="4127986689621125468">"Сонсголын төхөөрөмж"</string>
<string name="hac_mode_summary" msgid="7774989500136009881">"Сонсголын төхөөрөмж тааруулагчийг асаана уу"</string>
<string name="rtt_mode_title" msgid="3075948111362818043">"Шууд мессежлэх (RTT) дуудлага"</string>
- <string name="rtt_mode_summary" msgid="8631541375609989562">"Дуудлагын дотор зурвас бичихийг зөвшөөрөх"</string>
- <string name="rtt_mode_more_information" msgid="587500128658756318">"RTT нь дүлий, хатуу чихтэй, хэл ярианы хөгжлийн бэрхшээлтэй, эсвэл хэн нэгний тусламжтай ярьдаг дуудлага хийгчдэд тусладаг.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>Дэлгэрэнгүй үзэх</a>\n <br><br> - RTT дуудлага нь зурвасын сийрүүлэг хэлбэрээр хадгалагдана\n <br> - RTT нь видео дуудлага хийхэд боломжгүй"</string>
+ <string name="rtt_mode_summary" msgid="8631541375609989562">"Дуудлагын дотор мессеж бичихийг зөвшөөрөх"</string>
+ <string name="rtt_mode_more_information" msgid="587500128658756318">"RTT нь дүлий, хатуу чихтэй, хэл ярианы хөгжлийн бэрхшээлтэй, эсвэл хэн нэгний тусламжтай ярьдаг дуудлага хийгчдэд тусладаг.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>Дэлгэрэнгүй үзэх</a>\n <br><br> - RTT дуудлага нь мессежийн сийрүүлэг хэлбэрээр хадгалагдана\n <br> - RTT нь видео дуудлага хийхэд боломжгүй"</string>
<string name="no_rtt_when_roaming" msgid="5268008247378355389">"Санамж: RTT (Тухайн агшины текст) роуминг үйлчилгээний үед боломжгүй байна"</string>
<string-array name="tty_mode_entries">
<item msgid="3238070884803849303">"TTY Унтраасан"</item>
@@ -605,14 +605,14 @@
<item msgid="2271798469250155310">"Энгийн"</item>
<item msgid="6044210222666533564">"Урт"</item>
</string-array>
- <string name="network_info_message" msgid="7599413947016532355">"Сүлжээний зурвас"</string>
- <string name="network_error_message" msgid="4271579424089326618">"Алдаатай зурвас"</string>
+ <string name="network_info_message" msgid="7599413947016532355">"Сүлжээний мессеж"</string>
+ <string name="network_error_message" msgid="4271579424089326618">"Алдаатай мессеж"</string>
<string name="ota_title_activate" msgid="4049645324841263423">"Утсаа идэвхжүүлнэ үү"</string>
<string name="ota_touch_activate" msgid="838764494319694754">"Таны утасны үйлчилгээ идэвхжүүлэхийн тулд тусгай дуудлага хийх шаардлагатай. \n\n“Идэвхжүүлэх” гэснийг дарсны дараа өгч байгаа зааврыг сонсон утсаа идэвхжүүлнэ үү."</string>
<string name="ota_hfa_activation_title" msgid="3300556778212729671">"Идэвхжүүлж байна..."</string>
<string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"Утас таны мобайл дата үйлчилгээг идэвхжүүлж байна.\n\nҮүнд 5 хүртэл минут орж болно."</string>
<string name="ota_skip_activation_dialog_title" msgid="7666611236789203797">"Идэвхжүүлэхийг алгасах уу?"</string>
- <string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"Хэрэв та идэвхжүүлэхийг алгасвал дуудлага хийх буюу мобайль дата сүлжээнд холбогдох (хэдийгээр Wi-Fi сүлжээнд холбогдож болох ч) боломжгүй болно. Таныг утсаа идэвхжүүлэх хүртэл утсаа асаах бүрт идэвхжүүлэхийг хүсэх болно."</string>
+ <string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"Хэрэв та идэвхжүүлэхийг алгасвал дуудлага хийх буюу мобайль дата сүлжээнд холбогдох (хэдийгээр Wi-Fi сүлжээнд холбогдож болох ч) боломжгүй болно. Таныг утсаа идэвхжүүлэх хүртэл утсаа асаах бүрд идэвхжүүлэхийг хүсэх болно."</string>
<string name="ota_skip_activation_dialog_skip_label" msgid="5908029466817825633">"Алгасах"</string>
<string name="ota_activate" msgid="7939695753665438357">"Идэвхжүүлэх"</string>
<string name="ota_title_activate_success" msgid="1272135024761004889">"Утсыг идэвхжүүллээ."</string>
@@ -633,8 +633,8 @@
<string name="phone_in_ecm_call_notification_text" msgid="653972232922670335">"Дата холболтыг идэвхгүйжүүлсэн"</string>
<string name="phone_in_ecm_notification_complete_time" msgid="7341624337163082759">"<xliff:g id="COMPLETETIME">%s</xliff:g> болтол дата холболт байхгүй"</string>
<plurals name="alert_dialog_exit_ecm" formatted="false" msgid="5425906903766466743">
- <item quantity="other">Таны гар утас яаралтай түргэн тусламжийн дуудлагын хэлбэрт<xliff:g id="COUNT_1">%s</xliff:g> минут байна. Энэ горимд байгаа тохиолдолд интернет холболт ашигладаг ямар ч програмыг ашиглаж үл болно. Та гарахыг хүсэж байна уу?</item>
- <item quantity="one">Таны гар утас яаралтай түргэн тусламжийн дуудлагын хэлбэрт <xliff:g id="COUNT_0">%s</xliff:g> минут байна. Энэ горимд байгаа тохиолдолд интернет холболт ашигладаг ямар ч програмыг ашиглаж үл болно. Та гарахыг хүсэж байна уу?</item>
+ <item quantity="other">Таны гар утас яаралтай түргэн тусламжийн дуудлагын хэлбэрт<xliff:g id="COUNT_1">%s</xliff:g> минут байна. Энэ горимд байгаа тохиолдолд интернет холболт ашигладаг ямар ч программыг ашиглаж үл болно. Та гарахыг хүсэж байна уу?</item>
+ <item quantity="one">Таны гар утас яаралтай түргэн тусламжийн дуудлагын хэлбэрт <xliff:g id="COUNT_0">%s</xliff:g> минут байна. Энэ горимд байгаа тохиолдолд интернет холболт ашигладаг ямар ч программыг ашиглаж үл болно. Та гарахыг хүсэж байна уу?</item>
</plurals>
<plurals name="alert_dialog_not_avaialble_in_ecm" formatted="false" msgid="1152682528741457004">
<item quantity="other">Сонгосон үйлдлийг яаралтай түргэн тусламжийн горимд байгаа үед ашиглах боломжгүй. Таны гар утас энэ горимд <xliff:g id="COUNT_1">%s</xliff:g> минут байх болно. Та гарахыг хүсэж байна уу?</item>
@@ -663,7 +663,7 @@
<string name="description_dial_button" msgid="8614631902795087259">"залгах"</string>
<string name="description_dialpad_button" msgid="7395114120463883623">"дугаар цуглуулах самбарыг харуулах"</string>
<string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"Яаралтай тусламжийн дугаар цуглуулах самбар"</string>
- <string name="voicemail_visual_voicemail_switch_title" msgid="6610414098912832120">"Уншиж болохуйц дуут шуудан"</string>
+ <string name="voicemail_visual_voicemail_switch_title" msgid="6610414098912832120">"Визуал дуут шуудан"</string>
<string name="voicemail_set_pin_dialog_title" msgid="7005128605986960003">"PIN тохируулах"</string>
<string name="voicemail_change_pin_dialog_title" msgid="4633077715231764435">"PIN өөрчлөх"</string>
<string name="preference_category_ringtone" msgid="8787281191375434976">"Хонхны ая & Чичиргээ"</string>
@@ -679,7 +679,7 @@
<string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"Wi-Fi дуудлага"</string>
<string name="status_hint_label_wifi_call" msgid="942993035689809853">"Wi-Fi дуудлага"</string>
<string name="emergency_action_launch_hint" msgid="2762016865340891314">"Нээхийн тулд дахин дарна уу"</string>
- <string name="message_decode_error" msgid="1061856591500290887">"Зурвасын кодыг тайлах явцад алдаа гарсан."</string>
+ <string name="message_decode_error" msgid="1061856591500290887">"Мессежийн кодыг тайлах явцад алдаа гарсан."</string>
<string name="callFailed_cdma_activation" msgid="5392057031552253550">"SIM карт таны үйлчилгээг идэвхжүүлж, утасны роаминг багтаамжийг шинэчиллээ."</string>
<string name="callFailed_cdma_call_limit" msgid="1074219746093031412">"Хэт олон идэвхтэй дуудлага байна. Шинэ дуудлага хийхийн өмнө одоогийн дуудлагуудыг таслах буюу нэгтгэнэ үү."</string>
<string name="callFailed_imei_not_accepted" msgid="7257903653685147251">"Холбох боломжгүй, хүчинтэй SIM карт оруулна уу."</string>
@@ -874,8 +874,7 @@
<string name="radio_info_subid" msgid="6839966868621703203">"Одоогийн subId:"</string>
<string name="radio_info_dds" msgid="1122593144425697126">"Өгөгдмөл дата SIM-н SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DLзурвасын өргөн (kbps):"</string>
- <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL Зурвасын өргөн (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Үүрэн байршлын мэдээлэл (цуцалсан):"</string>
+ <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL Мессежийн өргөн (kbps):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE Сувгийн бодит тохиргоо:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Үүрэн мэдээлэл сэргээх тариф:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Бүх үүрэн хэмжилтийн мэдээлэл:"</string>
@@ -890,9 +889,9 @@
<string name="radio_info_signal_strength_label" msgid="5545444702102543260">"Дохионы хүч:"</string>
<string name="radio_info_call_status_label" msgid="7693575431923095487">"Дуут дуудлагын төлөв:"</string>
<string name="radio_info_ppp_sent_label" msgid="6542208429356199695">"Дата илгээсэн:"</string>
- <string name="radio_info_message_waiting_label" msgid="1886549432566952078">"Зурвасыг хүлээж байна:"</string>
+ <string name="radio_info_message_waiting_label" msgid="1886549432566952078">"Мессежийг хүлээж байна:"</string>
<string name="radio_info_phone_number_label" msgid="2533852539562512203">"Утасны дугаар:"</string>
- <string name="radio_info_band_mode_label" msgid="23480556225515290">"Радио зурвасыг сонгох"</string>
+ <string name="radio_info_band_mode_label" msgid="23480556225515290">"Радио мессежийг сонгох"</string>
<string name="radio_info_voice_network_type_label" msgid="2395347336419593265">"Дуут сүлжээний төрөл:"</string>
<string name="radio_info_data_network_type_label" msgid="8886597029237501929">"Дата сүлжээний төрөл:"</string>
<string name="phone_index_label" msgid="6222406512768964268">"Утасны индекс сонгох"</string>
@@ -911,8 +910,8 @@
<string name="radio_info_nr_available" msgid="1321318331361249997">"NR боломжтой:"</string>
<string name="radio_info_nr_state" msgid="1337571996788535356">"NR төлөв:"</string>
<string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR давтамж:"</string>
- <string name="band_mode_title" msgid="7988822920724576842">"Радио зурвасын горимыг тохируулах"</string>
- <string name="band_mode_loading" msgid="795923726636735967">"Зурвасын жагсаалтыг ачаалж байна…"</string>
+ <string name="band_mode_title" msgid="7988822920724576842">"Радио мессежийн горимыг тохируулах"</string>
+ <string name="band_mode_loading" msgid="795923726636735967">"Мессежийн жагсаалтыг ачаалж байна…"</string>
<string name="band_mode_set" msgid="6657819412803771421">"Тохируулах"</string>
<string name="band_mode_failed" msgid="1707488541847192924">"Амжилтгүй"</string>
<string name="band_mode_succeeded" msgid="2230018000534761063">"Амжилттай"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 174ca05..8e5b47b 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/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="phoneAppLabel" product="tablet" msgid="1916019789885839910">"मोबाईल डेटा"</string>
+ <string name="phoneAppLabel" product="tablet" msgid="1916019789885839910">"मोबाइल डेटा"</string>
<string name="phoneAppLabel" product="default" msgid="130465039375347763">"फोन सेवा"</string>
<string name="emergencyDialerIconLabel" msgid="8668005772339436680">"आणीबाणी डायलर"</string>
<string name="phoneIconLabel" msgid="3015941229249651419">"फोन"</string>
@@ -28,11 +28,11 @@
<string name="carrier_mmi_msg_title" msgid="6050165242447507034">"<xliff:g id="MMICARRIER">%s</xliff:g> मेसेज"</string>
<string name="default_carrier_mmi_msg_title" msgid="7754317179938537213">"वाहक मेसेज"</string>
<string name="mmiStarted" msgid="9212975136944568623">"MMI कोड प्रारंभ केला"</string>
- <string name="ussdRunning" msgid="1163586813106772717">"USSD कोड चालू…"</string>
+ <string name="ussdRunning" msgid="1163586813106772717">"USSD कोड सुरू…"</string>
<string name="mmiCancelled" msgid="5339191899200678272">"MMI कोड रद्द केला"</string>
<string name="cancel" msgid="8984206397635155197">"रद्द करा"</string>
<string name="enter_input" msgid="6193628663039958990">"USSD मेसेज <xliff:g id="MIN_LEN">%1$d</xliff:g> आणि <xliff:g id="MAX_LEN">%2$d</xliff:g> वर्णांमधील असणे आवश्यक आहे. कृपया पुन्हा प्रयत्न करा."</string>
- <string name="manageConferenceLabel" msgid="8415044818156353233">"कॉन्फरन्स कॉल व्यवस्थापित करा"</string>
+ <string name="manageConferenceLabel" msgid="8415044818156353233">"कॉंफरन्स कॉल व्यवस्थापित करा"</string>
<string name="ok" msgid="7818974223666140165">"ठीक"</string>
<string name="audio_mode_speaker" msgid="243689733219312360">"स्पीकर"</string>
<string name="audio_mode_earpiece" msgid="2823700267171134282">"हँडसेट इअरपीस"</string>
@@ -50,14 +50,13 @@
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"केवळ प्राथमिक वापरकर्ता व्हॉइसमेल सेटिंग्ज बदलू शकतो."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"तुमचे सिम कार्ड अवरोधित करणे रद्द केले गेले आहे. तुमचा फोन अनलॉक होत आहे…"</string>
<string name="label_ndp" msgid="7617392683877410341">"सिम नेटवर्क अनलॉक पिन"</string>
- <!-- no translation found for label_phoneid (8775611434123577808) -->
- <skip />
+ <string name="label_phoneid" msgid="8775611434123577808">"ऑपरेटरसाठी सिम लॉक केले आहे"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"अनलॉक करा"</string>
<string name="sim_ndp_dismiss_text" msgid="89667342248929777">"डिसमिस करा"</string>
<string name="requesting_unlock" msgid="930512210309437741">"नेटवर्क अनलॉकची विनंती करत आहे..."</string>
<string name="unlock_failed" msgid="7103543844840661366">"नेटवर्क अनलॉक विनंती अयशस्वी."</string>
<string name="unlock_success" msgid="32681089371067565">"नेटवर्क अनलॉक यशस्वी."</string>
- <string name="mobile_network_settings_not_available" msgid="8678168497517090039">"या वापरकर्त्यासाठी मोबाईल नेटवर्क सेटिंग्ज उपलब्ध नाहीत"</string>
+ <string name="mobile_network_settings_not_available" msgid="8678168497517090039">"या वापरकर्त्यासाठी मोबाइल नेटवर्क सेटिंग्ज उपलब्ध नाहीत"</string>
<string name="labelGSMMore" msgid="7354182269461281543">"GSM कॉल सेटिंग्ज"</string>
<string name="labelGsmMore_with_label" msgid="3206015314393246224">"GSM कॉल सेटिंग्ज (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="labelCDMAMore" msgid="7937441382611224632">"CDMA कॉल सेटिंग्ज"</string>
@@ -107,7 +106,7 @@
<string name="labelCFU" msgid="8870170873036279706">"नेहमी फॉरवर्ड करा"</string>
<string name="messageCFU" msgid="1361806450979589744">"नेहमी हा नंबर वापरा"</string>
<string name="sum_cfu_enabled_indicator" msgid="9030139213402432776">"सर्व कॉल अग्रेषित करत आहे"</string>
- <string name="sum_cfu_enabled" msgid="5806923046528144526">"सर्व कॉल <xliff:g id="PHONENUMBER">{0}</xliff:g> वर अग्रेषित करत आहे"</string>
+ <string name="sum_cfu_enabled" msgid="5806923046528144526">"सर्व कॉल <xliff:g id="PHONENUMBER">{0}</xliff:g> वर फॉरवर्ड करत आहे"</string>
<string name="sum_cfu_enabled_no_number" msgid="7287752761743377930">"नंबर अनुपलब्ध आहे"</string>
<string name="sum_cfu_disabled" msgid="5010617134210809853">"बंद"</string>
<string name="labelCFB" msgid="615265213360512768">"व्यस्त असताना"</string>
@@ -145,10 +144,10 @@
<string name="stk_cc_ss_to_ussd_error" msgid="8330749347425752192">"SS विनंती USSD विनंतीवर बदलली"</string>
<string name="stk_cc_ss_to_ss_error" msgid="8297155544652134278">"नवीन SS विनंतीवर बदलली"</string>
<string name="stk_cc_ss_to_dial_video_error" msgid="4255261231466032505">"SS विनंती व्हिडिओ कॉलवर बदलली"</string>
- <string name="fdn_check_failure" msgid="1833769746374185247">"आपल्या फोन अॅप्सचे निश्चित डायलिंग नंबर सेटिंग चालू केले. परिणामी, काही कॉल संबंधित वैशिष्ट्ये कार्य करीत नाहीत."</string>
- <string name="radio_off_error" msgid="8321564164914232181">"या सेटिंग्ज पाहण्यापूर्वी रेडिओ चालू करा."</string>
+ <string name="fdn_check_failure" msgid="1833769746374185247">"आपल्या फोन अॅप्सचे निश्चित डायलिंग नंबर सेटिंग सुरू केले. परिणामी, काही कॉल संबंधित वैशिष्ट्ये कार्य करीत नाहीत."</string>
+ <string name="radio_off_error" msgid="8321564164914232181">"या सेटिंग्ज पाहण्यापूर्वी रेडिओ सुरू करा."</string>
<string name="close_dialog" msgid="1074977476136119408">"ठीक"</string>
- <string name="enable" msgid="2636552299455477603">"चालू करा"</string>
+ <string name="enable" msgid="2636552299455477603">"सुरू करा"</string>
<string name="disable" msgid="1122698860799462116">"बंद करा"</string>
<string name="change_num" msgid="6982164494063109334">"अपडेट करा"</string>
<string-array name="clir_display_values">
@@ -519,7 +518,7 @@
<string name="voicemail_settings_number_label" msgid="1265118640154688162">"व्हॉइसमेल नंबर"</string>
<string name="card_title_dialing" msgid="8742182654254431781">"डायल करत आहे"</string>
<string name="card_title_redialing" msgid="18130232613559964">"रीडायल करत आहे"</string>
- <string name="card_title_conf_call" msgid="901197309274457427">"कॉन्फरन्स कॉल"</string>
+ <string name="card_title_conf_call" msgid="901197309274457427">"कॉंफरन्स कॉल"</string>
<string name="card_title_incoming_call" msgid="881424648458792430">"येणारे कॉल"</string>
<string name="card_title_call_ended" msgid="650223980095026340">"कॉल संपला"</string>
<string name="card_title_on_hold" msgid="9028319436626975207">"होल्ड वर"</string>
@@ -531,7 +530,7 @@
<string name="notification_voicemail_no_vm_number" msgid="3423686009815186750">"व्हॉइसमेल नंबर अज्ञात"</string>
<string name="notification_network_selection_title" msgid="255595526707809121">"सेवा नाही"</string>
<string name="notification_network_selection_text" msgid="553288408722427659">"निवडलेले नेटवर्क<xliff:g id="OPERATOR_NAME">%s</xliff:g> उपलब्ध नाही"</string>
- <string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"कॉल करण्यासाठी मोबाइल नेटवर्क चालू करा, विमान मोड बंद करा किंवा बॅटरी बचकर्ता मोड बंद करा."</string>
+ <string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"कॉल करण्यासाठी मोबाइल नेटवर्क सुरू करा, विमान मोड बंद करा किंवा बॅटरी बचकर्ता मोड बंद करा."</string>
<string name="incall_error_power_off" product="default" msgid="8131672264311208673">"कॉल करण्यासाठी विमान मोड बंद करा."</string>
<string name="incall_error_power_off_wfc" msgid="9125661184694727052">"कॉल करण्यासाठी विमान मोड बंद करा किंवा वायरलेस नेटवर्कशी कनेक्ट करा."</string>
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"आणीबाणी नसलेला कॉल करण्यासाठी आणीबाणी कॉलबॅक मोडमधून बाहेर पडा."</string>
@@ -549,7 +548,7 @@
<string name="incall_error_supp_service_conference" msgid="27578082433544702">"कॉल विलीन करता आले नाहीत."</string>
<string name="incall_error_supp_service_reject" msgid="3044363092441655912">"कॉल नाकारू शकत नाही."</string>
<string name="incall_error_supp_service_hangup" msgid="836524952243836735">"कॉल रिलीज करू शकत नाही."</string>
- <string name="incall_error_supp_service_hold" msgid="8535056414643540997">"कॉल सुरु ठेवू शकत नाही."</string>
+ <string name="incall_error_supp_service_hold" msgid="8535056414643540997">"कॉल सुरू ठेवू शकत नाही."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"कॉल करण्यासाठी वायरलेस नेटवर्कशी कनेक्ट करा."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"कॉल करण्यासाठी वाय-फाय कॉलिंग सक्षम करा."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"अतिमहत्त्वाची माहिती"</string>
@@ -559,7 +558,7 @@
<string name="single_emergency_number_title" msgid="8413371079579067196">"आणीबाणी नंबर"</string>
<string name="numerous_emergency_numbers_title" msgid="8972398932506755510">"आणीबाणी नंबर"</string>
<string name="emergency_call_shortcut_hint" msgid="1290485125107779500">"<xliff:g id="EMERGENCY_NUMBER">%s</xliff:g> ला कॉल करण्यासाठी पुन्हा टॅप करा"</string>
- <string name="emergency_enable_radio_dialog_message" msgid="1695305158151408629">"रेडिओ चालू करत आहे..."</string>
+ <string name="emergency_enable_radio_dialog_message" msgid="1695305158151408629">"रेडिओ सुरू करत आहे..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="4329131876852608587">"सेवा नाही. पुन्हा प्रयत्न करत आहे…"</string>
<string name="radio_off_during_emergency_call" msgid="8011154134040481609">"आणीबाणी कॉलदरम्यान विमान मोडमध्ये प्रवेश करू शकत नाही."</string>
<string name="dial_emergency_error" msgid="825822413209026039">"कॉल करू शकत नाही. <xliff:g id="NON_EMERGENCY_NUMBER">%s</xliff:g> हा आणीबाणी नंबर नाहीये."</string>
@@ -574,7 +573,7 @@
<string name="onscreenHoldText" msgid="4025348842151665191">"होल्ड करा"</string>
<string name="onscreenEndCallText" msgid="6138725377654842757">"शेवट"</string>
<string name="onscreenShowDialpadText" msgid="658465753816164079">"डायलपॅड"</string>
- <string name="onscreenMuteText" msgid="5470306116733843621">"नि:शब्द करा"</string>
+ <string name="onscreenMuteText" msgid="5470306116733843621">"म्यूट करा"</string>
<string name="onscreenAddCallText" msgid="9075675082903611677">"कॉल जोडा"</string>
<string name="onscreenMergeCallsText" msgid="3692389519611225407">"कॉल विलीन करा"</string>
<string name="onscreenSwapCallsText" msgid="2682542150803377991">"अदलाबदल करा"</string>
@@ -589,7 +588,7 @@
<string name="singleContactImportedMsg" msgid="3619804066300998934">"इंपोर्ट केलेला संपर्क"</string>
<string name="failedToImportSingleContactMsg" msgid="228095510489830266">"संपर्क इंपोर्ट करण्यात अयशस्वी"</string>
<string name="hac_mode_title" msgid="4127986689621125468">"श्रवणयंत्रे"</string>
- <string name="hac_mode_summary" msgid="7774989500136009881">"श्रवणयंत्र कंपॅटिबिलिटी चालू करा"</string>
+ <string name="hac_mode_summary" msgid="7774989500136009881">"श्रवणयंत्र कंपॅटिबिलिटी सुरू करा"</string>
<string name="rtt_mode_title" msgid="3075948111362818043">"रीअल-टाइम टेक्स्ट (RTT) कॉल"</string>
<string name="rtt_mode_summary" msgid="8631541375609989562">"व्हॉइस कॉल करताना मेसेजिंग करू शकतो"</string>
<string name="rtt_mode_more_information" msgid="587500128658756318">"RTT अशा कॉल करणार्यांना साहाय्य करते, ज्यांना बहिरेपणा आहे, ज्यांना कमी ऐकू येते किंवा बोलताना अडखळतात किंवा ज्यांना फक्त आवाज पुरेसा नसतो.<br>a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>अधिक जाणून घ्या<a>\n <br/> - RTT cकॉल मेसेज प्रतिलेख म्हणून सेव्ह केले आहेत\n <br/> - RTT व्हिडिओ कॉलसाठी उपलब्ध नाही"</string>
@@ -613,7 +612,7 @@
<string name="ota_hfa_activation_title" msgid="3300556778212729671">"सक्रिय करत आहे..."</string>
<string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"फोन तुमची मोबाइल डेटा सेवा सक्रिय करत आहे.\n\nयास सुमारे 5 मिनिटे लागतील."</string>
<string name="ota_skip_activation_dialog_title" msgid="7666611236789203797">"सक्रिय करणे वगळायचे?"</string>
- <string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"तुम्ही सक्रिय करणे वगळल्यास, तुम्ही कॉल करू शकत नाही किंवा मोबाइल डेटा नेटवर्कशी कनेक्ट करू शकत नाही (तुम्ही वाय-फाय नेटवर्कशी कनेक्ट करू शकत असला तरीही). तुम्ही तुमचा फोन सक्रिय करेपर्यंत, तुम्ही तो प्रत्येक वेळी चालू करताना आपल्याला तो सक्रिय करण्यास सांगितले जाईल."</string>
+ <string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"तुम्ही सक्रिय करणे वगळल्यास, तुम्ही कॉल करू शकत नाही किंवा मोबाइल डेटा नेटवर्कशी कनेक्ट करू शकत नाही (तुम्ही वाय-फाय नेटवर्कशी कनेक्ट करू शकत असला तरीही). तुम्ही तुमचा फोन सक्रिय करेपर्यंत, तुम्ही तो प्रत्येक वेळी सुरू करताना आपल्याला तो सक्रिय करण्यास सांगितले जाईल."</string>
<string name="ota_skip_activation_dialog_skip_label" msgid="5908029466817825633">"वगळा"</string>
<string name="ota_activate" msgid="7939695753665438357">"सक्रिय करा"</string>
<string name="ota_title_activate_success" msgid="1272135024761004889">"फोन सक्रिय केला आहे."</string>
@@ -669,8 +668,8 @@
<string name="voicemail_change_pin_dialog_title" msgid="4633077715231764435">"पिन बदला"</string>
<string name="preference_category_ringtone" msgid="8787281191375434976">"रिंगटोन आणि कंपन"</string>
<string name="pstn_connection_service_label" msgid="9200102709997537069">"अंगभूत सिम कार्डे"</string>
- <string name="enable_video_calling_title" msgid="7246600931634161830">"व्हिडिओ कॉलिंग चालू करा"</string>
- <string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"व्हिडिओ कॉल करणे चालू करण्यासाठी, आपल्याला नेटवर्क सेटिंग्ज मधील वर्धित 4G LTE मोड सक्षम करणे आवश्यक आहे."</string>
+ <string name="enable_video_calling_title" msgid="7246600931634161830">"व्हिडिओ कॉलिंग सुरू करा"</string>
+ <string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"व्हिडिओ कॉल करणे सुरू करण्यासाठी, आपल्याला नेटवर्क सेटिंग्ज मधील वर्धित 4G LTE मोड सक्षम करणे आवश्यक आहे."</string>
<string name="enable_video_calling_dialog_settings" msgid="8697890611305307110">"नेटवर्क सेटिंग्ज"</string>
<string name="enable_video_calling_dialog_close" msgid="4298929725917045270">"बंद करा"</string>
<string name="sim_label_emergency_calls" msgid="9078241989421522310">"आणीबाणी कॉल"</string>
@@ -694,7 +693,7 @@
<string name="change_pin_cancel_label" msgid="2301711566758827936">"रद्द करा"</string>
<string name="change_pin_ok_label" msgid="6861082678817785330">"ठीक आहे"</string>
<string name="change_pin_enter_old_pin_header" msgid="853151335217594829">"आपल्या जुन्या पिनची पुष्टी करा"</string>
- <string name="change_pin_enter_old_pin_hint" msgid="8801292976275169367">"सुरु ठेवण्यासाठी तुमचा व्हॉइसमेल पिन प्रविष्ट करा."</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8801292976275169367">"सुरू ठेवण्यासाठी तुमचा व्हॉइसमेल पिन प्रविष्ट करा."</string>
<string name="change_pin_enter_new_pin_header" msgid="4739465616733486118">"नवीन पिन सेट करा"</string>
<string name="change_pin_enter_new_pin_hint" msgid="2326038476516364210">"पिन <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> अंकी असणे आवश्यक आहे."</string>
<string name="change_pin_confirm_pin_header" msgid="2606303906320705726">"आपल्या पिनची पुष्टी करा"</string>
@@ -702,7 +701,7 @@
<string name="change_pin_succeeded" msgid="2504705600693014403">"व्हॉइसमेल पिन अपडेट केला"</string>
<string name="change_pin_system_error" msgid="7772788809875146873">"पिन सेट करण्यात अक्षम"</string>
<string name="mobile_data_status_roaming_turned_off_subtext" msgid="6840673347416227054">"डेटा रोमिंग बंद केलेले आहे"</string>
- <string name="mobile_data_status_roaming_turned_on_subtext" msgid="5615757897768777865">"डेटा रोमिंग चालू केलेले आहे"</string>
+ <string name="mobile_data_status_roaming_turned_on_subtext" msgid="5615757897768777865">"डेटा रोमिंग सुरू केलेले आहे"</string>
<string name="mobile_data_status_roaming_without_plan_subtext" msgid="6536671968072284677">"सध्या रोमिंग, डेटा योजना आवश्यक आहे"</string>
<string name="mobile_data_status_roaming_with_plan_subtext" msgid="2576177169108123095">"सध्या रोमिंग, डेटा योजना सक्रिय आहे"</string>
<string name="mobile_data_status_no_plan_subtext" msgid="170331026419263657">"मोबाइल डेटा शिल्लक नाही"</string>
@@ -769,7 +768,7 @@
<string name="clh_callFailed_protocol_Error_unspecified_txt" msgid="9203320572562697755">"कॉल पूर्ण करता आला नाही. एरर कोड १११."</string>
<string name="clh_callFailed_interworking_unspecified_txt" msgid="7969686413930847182">"कॉल पूर्ण करता आला नाही. एरर कोड १२७."</string>
<string name="labelCallBarring" msgid="4180377113052853173">"कॉल बारिंग"</string>
- <string name="sum_call_barring_enabled" msgid="5184331188926370824">"चालू"</string>
+ <string name="sum_call_barring_enabled" msgid="5184331188926370824">"सुरू"</string>
<string name="sum_call_barring_disabled" msgid="5699448000600153096">"बंद"</string>
<string name="call_barring_baoc" msgid="7400892586336429326">"सर्व जाणारे"</string>
<string name="call_barring_baoc_enabled" msgid="3131509193386668182">"सर्व जाणारे कॉल ब्लॉक करणे बंद करायचे का?"</string>
@@ -876,8 +875,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"डीफॉल्ट डेटा सिम SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL बँडविड्थ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL बँडविड्थ (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"सेल स्थान माहिती (कालबाह्य झाली):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE फिजिकल चॅनेल कॉंफिगरेशन:"</string>
+ <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE फिजिकल चॅनल कॉंफिगरेशन:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"सेल माहिती रिफ्रेश रेट:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"सर्व सेल परिमाण माहिती:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"डेटा सर्व्हिस:"</string>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index e370447..f9829bd 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -122,7 +122,7 @@
<string name="labelCFNRc" msgid="4163399350778066013">"Jika tidak dapat dihubungi"</string>
<string name="messageCFNRc" msgid="6980340731313007250">"Nombor apabila tidak dapat dihubungi"</string>
<string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Memajukan ke <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
- <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Mati"</string>
+ <string name="sum_cfnrc_disabled" msgid="739289696796917683">"Dimatikan"</string>
<string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Pembawa anda tidak menyokong pelumpuhan pemajuan panggilan semasa telefon anda tidak boleh dihubungi."</string>
<string name="registration_cf_forbidden" msgid="4386482610771190420">"Pembawa anda tidak menyokong pemajuan panggilan."</string>
<string name="cdma_call_waiting" msgid="4565070960879673216">"Hidupkan panggilan menunggu?"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId SIM data lalai:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Lebar Jalur DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Lebar Jalur UL (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Maklumat Lokasi Selular (ditamatkan):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurasi Saluran Fizikal LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Kadar Muat Semula Maklumat Selular:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Semua Maklumat Ukuran Selular:"</string>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index e314a6b..43930e9 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -24,7 +24,7 @@
<string name="unknown" msgid="8279698889921830815">"မသိပါ"</string>
<string name="private_num" msgid="4487990167889159992">"လျို့ဝှက် နံပါတ်"</string>
<string name="payphone" msgid="7936735771836716941">"ငွေပေးရသည့်ဖုန်း"</string>
- <string name="onHold" msgid="6132725550015899006">"ခဏ ကိုင်ထားစဉ်"</string>
+ <string name="onHold" msgid="6132725550015899006">"ဖုန်းကိုင်ထားသည်"</string>
<string name="carrier_mmi_msg_title" msgid="6050165242447507034">"<xliff:g id="MMICARRIER">%s</xliff:g> မက်ဆေ့ဂျ်"</string>
<string name="default_carrier_mmi_msg_title" msgid="7754317179938537213">"ဖုန်းလိုင်းဝန်ဆောင်မှု မက်ဆေ့ဂျ်"</string>
<string name="mmiStarted" msgid="9212975136944568623">"MMIကုတ်နံပါတ်ကို စတင်ပြီးပါပြီ"</string>
@@ -75,7 +75,7 @@
<string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"အကောင့် ချိန်ညှိချက်များ ပြုပြင်မည်"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"ခေါ်ဆိုနေသော အကောင့်များ အားလုံး"</string>
<string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"ဖုန်းခေါ်ဆိုနိုင်သည့် အကောင့်များအား ရွေးရန်"</string>
- <string name="wifi_calling" msgid="3650509202851355742">"Wi-Fi ခေါ်ဆိုမှု"</string>
+ <string name="wifi_calling" msgid="3650509202851355742">"Wi-Fi ခေါ်ဆိုခြင်း"</string>
<string name="connection_service_default_label" msgid="7332739049855715584">"တပ်ဆင်ပြီး ချိတ်ဆက်ရေး ဝန်ဆောင်မှု"</string>
<string name="voicemail" msgid="7697769412804195032">"အသံမေးလ်"</string>
<string name="voicemail_settings_with_label" msgid="4228431668214894138">"အသံမေးလ် ( <xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g> )"</string>
@@ -92,7 +92,7 @@
<string name="additional_cdma_call_settings" msgid="2178016561980611304">"ပိုမိုသော CDMA ခေါ်ဆိုမှု အပြင်အဆင်"</string>
<string name="sum_cdma_call_settings" msgid="3185825305136993636">"CDMA ခေါ်ဆိုမှုအတွက်သာ ဖြည့်စွက်အပြင်အဆင်"</string>
<string name="labelNwService" msgid="6015891883487125120">"ကွန်ရက် ဝန်ဆောင်မှု ဆက်တင်"</string>
- <string name="labelCallerId" msgid="2090540744550903172">"ခေါ်ဆိုသူအိုင်ဒီ"</string>
+ <string name="labelCallerId" msgid="2090540744550903172">"ခေါ်ဆိုသူ ID"</string>
<string name="sum_loading_settings" msgid="434063780286688775">"ဆက်တင်များကို ကြည့်ရှုရန် လုပ်နေပါသည်…"</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"အထွက်ဖုန်းများတွင် နံပါတ်ဖျောက်ထားပါ"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"အထွက်ဖုန်းများတွင် နံပါတ်မြင်ရသည်"</string>
@@ -106,7 +106,7 @@
<string name="labelCFU" msgid="8870170873036279706">"အမြဲတမ်း ထပ်ဆင့်ပို့ပါ"</string>
<string name="messageCFU" msgid="1361806450979589744">"ဤနံပါတ်ကို အမြဲသုံးပါ"</string>
<string name="sum_cfu_enabled_indicator" msgid="9030139213402432776">"ခေါ်ဆိုမှုအားလုံးအား တဆင့်ထပ်ပို့နေသည်"</string>
- <string name="sum_cfu_enabled" msgid="5806923046528144526">"<xliff:g id="PHONENUMBER">{0}</xliff:g> သို့ခေါ်ဆိုမှုအားလုံးအား တဆင့်ထပ်ပို့နေသည်"</string>
+ <string name="sum_cfu_enabled" msgid="5806923046528144526">"ခေါ်ဆိုမှုအားလုံးကို <xliff:g id="PHONENUMBER">{0}</xliff:g> သို့ ထပ်ဆင့်ပို့နေသည်"</string>
<string name="sum_cfu_enabled_no_number" msgid="7287752761743377930">"ဖုန်းနံပါတ်မှာ မရှိပါ"</string>
<string name="sum_cfu_disabled" msgid="5010617134210809853">"ပိတ်ထားသည်"</string>
<string name="labelCFB" msgid="615265213360512768">"မအားလပ်ချိန်"</string>
@@ -135,7 +135,7 @@
<string name="call_settings_admin_user_only" msgid="7238947387649986286">"ခေါ်ဆိုမှုကြိုတင်ပြင်ဆင်ချက်များကို ကြီးကြပ်သူသာလျှင် ပြောင်းလဲနိုင်သည်။"</string>
<string name="call_settings_with_label" msgid="8460230435361579511">"ဆက်တင်များ ( <xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g> )"</string>
<string name="error_updating_title" msgid="2024290892676808965">"ခေါ်ဆိုမှုဆက်တင်အမှား"</string>
- <string name="reading_settings" msgid="1605904432450871183">"အပြင်အဆင်များကို ဖတ်နေပါသည်…"</string>
+ <string name="reading_settings" msgid="1605904432450871183">"ဆက်တင်များကို ဖတ်နေပါသည်…"</string>
<string name="updating_settings" msgid="3650396734816028808">"ဆက်တင်များအား ပြင်နေသည်…"</string>
<string name="reverting_settings" msgid="7378668837291012205">"ဆက်တင်များကို ပြန်ပြောင်းနေစဉ်…"</string>
<string name="response_error" msgid="3904481964024543330">"ကွန်ယက်မှ မထင်မှတ်သောတုံ့ပြန်ချက်"</string>
@@ -148,7 +148,7 @@
<string name="radio_off_error" msgid="8321564164914232181">"ဤအပြင်အဆင်များကို မကြည့်ခင် ရေဒီယိုကို ဖွင့်ပါ"</string>
<string name="close_dialog" msgid="1074977476136119408">"OK"</string>
<string name="enable" msgid="2636552299455477603">"ဖွင့်ထားရန်"</string>
- <string name="disable" msgid="1122698860799462116">"ပိတ်မည်"</string>
+ <string name="disable" msgid="1122698860799462116">"ပိတ်ရန်"</string>
<string name="change_num" msgid="6982164494063109334">"အဆင်မြှင့်ခြင်း"</string>
<string-array name="clir_display_values">
<item msgid="8477364191403806960">"မူရင်း ကွန်ရက်"</item>
@@ -521,7 +521,7 @@
<string name="card_title_conf_call" msgid="901197309274457427">"ကွန်းဖရင့်ခေါ်ဆိုမှု"</string>
<string name="card_title_incoming_call" msgid="881424648458792430">"အဝင်ခေါ်ဆိုမှု"</string>
<string name="card_title_call_ended" msgid="650223980095026340">"ဖုန်းခေါ်ဆိုမှု ပြီးဆုံးပါပြီ"</string>
- <string name="card_title_on_hold" msgid="9028319436626975207">"ခဏ ကိုင်ထားစဉ်"</string>
+ <string name="card_title_on_hold" msgid="9028319436626975207">"ဖုန်းကိုင်ထားသည်"</string>
<string name="card_title_hanging_up" msgid="814874106866647871">"ဖုန်းချနေပါသည်"</string>
<string name="card_title_in_call" msgid="8231896539567594265">"ဖုန်းပြောနေစဉ်"</string>
<string name="notification_voicemail_title" msgid="3932876181831601351">"အသံမေးလ်အသစ်"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"မူရင်း ဒေတာဆင်းမ်ကဒ်အတွက် Id အခွဲ −"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL မြန်နှုန်း (kbps)−"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL မြန်နှုန်း (kbps)−"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"ဆဲလ်လူလာတည်နေရာ အချက်အလက် (ကန့်ကွက်ထားသည်) −"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ရုပ်ပိုင်းဆိုင်ရာ ချန်နယ်စီစဉ်သတ်မှတ်မှု−"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ဆဲလ်လူလာ အချက်အလက် ရယူမှုနှုန်း −"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ဆဲလ်လူလာတိုင်းတာမှု အချက်အလက် အားလုံး −"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 938a056..dc6d224 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -50,8 +50,7 @@
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Talepost-innstillinger kan bare endres av hovedbrukeren."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"SIM-kortet er blitt avblokkert. Telefonen låses opp…"</string>
<string name="label_ndp" msgid="7617392683877410341">"PIN-kode for å fjerne operatørlås"</string>
- <!-- no translation found for label_phoneid (8775611434123577808) -->
- <skip />
+ <string name="label_phoneid" msgid="8775611434123577808">"SIM-kortet er operatørlåst"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Lås opp"</string>
<string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Skjul"</string>
<string name="requesting_unlock" msgid="930512210309437741">"Spør om fjerning av operatørlås…"</string>
@@ -876,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Under-ID for standard-SIM-kort for data:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Båndbredde for nedlasting (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Båndbredde for opplasting (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informasjon om celleposisjonen (avviklet):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurering av fysisk LTE-kanal:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Oppdateringsfrekvens for celleinformasjon:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All informasjon for cellemåling:"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 9a08855..acb6056 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -18,7 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="phoneAppLabel" product="tablet" msgid="1916019789885839910">"मोबाइल डेटा"</string>
<string name="phoneAppLabel" product="default" msgid="130465039375347763">"फोन सेवाहरू"</string>
- <string name="emergencyDialerIconLabel" msgid="8668005772339436680">"आपतकालीन डायल गर्ने"</string>
+ <string name="emergencyDialerIconLabel" msgid="8668005772339436680">"आपत्कालीन डायल गर्ने"</string>
<string name="phoneIconLabel" msgid="3015941229249651419">"फोन"</string>
<string name="fdnListLabel" msgid="4119121875004244097">"FDN सूची"</string>
<string name="unknown" msgid="8279698889921830815">"अज्ञात"</string>
@@ -84,7 +84,7 @@
<string name="smart_forwarding_settings_menu" msgid="8850429887958938540">"स्मार्ट तरिकाले फर्वार्ड गर्ने सुविधा"</string>
<string name="smart_forwarding_settings_menu_summary" msgid="5096947726032885325">"एउटा नम्बर सम्पर्क क्षेत्रबाहिर भएका बेला कल सधैँ आफ्नो अर्को नम्बरमा फर्वार्ड गर्नुहोस्"</string>
<string name="voicemail_notifications_preference_title" msgid="7829238858063382977">"सूचनाहरू"</string>
- <string name="cell_broadcast_settings" msgid="8135324242541809924">"आपतकालीन प्रसारणहरू"</string>
+ <string name="cell_broadcast_settings" msgid="8135324242541809924">"आपत्कालीन प्रसारणहरू"</string>
<string name="call_settings" msgid="3677282690157603818">"कल सेटिङहरू"</string>
<string name="additional_gsm_call_settings" msgid="1561980168685658846">"अतिरिक्त सेटिङहरू"</string>
<string name="additional_gsm_call_settings_with_label" msgid="7973920539979524908">"अतिरिक्त सेटिङ ( <xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g> )"</string>
@@ -149,7 +149,7 @@
<string name="close_dialog" msgid="1074977476136119408">"ठिक छ"</string>
<string name="enable" msgid="2636552299455477603">"सकृय पार्नुहोस्"</string>
<string name="disable" msgid="1122698860799462116">"निस्कृय पार्नुहोस्"</string>
- <string name="change_num" msgid="6982164494063109334">"अद्यावधिक गर्नुहोस्"</string>
+ <string name="change_num" msgid="6982164494063109334">"अपडेट गर्नुहोस्"</string>
<string-array name="clir_display_values">
<item msgid="8477364191403806960">"नेटवर्क पूर्वनिर्धारित"</item>
<item msgid="6813323051965618926">"सङ्ख्या लुकाउनुहोस्"</item>
@@ -306,7 +306,7 @@
<string name="sim_selection_required_pref" msgid="6985901872978341314">"चयन गर्न आवश्यक छ"</string>
<string name="sim_change_data_title" msgid="9142726786345906606">"डेटा सिम परिवर्तन गर्ने हो?"</string>
<string name="sim_change_data_message" msgid="3567358694255933280">"मोबाइल डेटाका लागि <xliff:g id="OLD_SIM">%2$s</xliff:g> को सट्टा <xliff:g id="NEW_SIM">%1$s</xliff:g> को प्रयोग गर्ने हो?"</string>
- <string name="wifi_calling_settings_title" msgid="5800018845662016507">"Wi-Fi कल"</string>
+ <string name="wifi_calling_settings_title" msgid="5800018845662016507">"Wi-Fi कलिङ"</string>
<string name="video_calling_settings_title" msgid="342829454913266078">"सेवा प्रदायकको भिडियो कल"</string>
<string name="gsm_umts_options" msgid="4968446771519376808">"GSM/UMTS विकल्पहरू"</string>
<string name="cdma_options" msgid="3669592472226145665">"CDMA विकल्पहरू"</string>
@@ -326,9 +326,9 @@
<string name="cell_bc_sms_enable" msgid="2019708772024632073">"सेल प्रसारण SMS सक्षम"</string>
<string name="cell_bc_sms_disable" msgid="1214238639910875347">"सेल प्रसारण SMS अक्षम"</string>
<string name="cb_sms_settings" msgid="6858093721831312036">"सेल प्रसारण SMS सेटिङहरू"</string>
- <string name="enable_disable_emergency_broadcast" msgid="6325655044472196496">"आपतकालीन प्रसारण"</string>
- <string name="emergency_broadcast_enable" msgid="5759610647771102442">"आपतकालीन प्रसारण सक्षम भयो"</string>
- <string name="emergency_broadcast_disable" msgid="2844904734469323266">"आपतकालीन प्रसारण अक्षम भयो"</string>
+ <string name="enable_disable_emergency_broadcast" msgid="6325655044472196496">"आपत्कालीन प्रसारण"</string>
+ <string name="emergency_broadcast_enable" msgid="5759610647771102442">"आपत्कालीन प्रसारण सक्षम भयो"</string>
+ <string name="emergency_broadcast_disable" msgid="2844904734469323266">"आपत्कालीन प्रसारण अक्षम भयो"</string>
<string name="enable_disable_administrative" msgid="7825925366822117961">"प्रशासकीय"</string>
<string name="administrative_enable" msgid="5717963431079532028">"प्रशासनिक सक्षम"</string>
<string name="administrative_disable" msgid="156796633660118691">"प्रशासनिक असक्षम"</string>
@@ -533,7 +533,7 @@
<string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"मोबाइल नेटवर्क सक्रिय पार्नुहोस्, कल गर्न हवाइजहाज मोड वा ब्याट्री सेवर मोड निष्क्रिय पार्नुहोस्।"</string>
<string name="incall_error_power_off" product="default" msgid="8131672264311208673">"एक कल गर्न हवाइजहाज मोड बन्द गर्नुहोस्।"</string>
<string name="incall_error_power_off_wfc" msgid="9125661184694727052">"एक कल गर्न हवाइजहाज मोड बन्द गर्नुहोस् वा एक ताररहितको सञ्जालमा जडान गर्नुहोस्।"</string>
- <string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"गैर-आपतकालीन कल गर्न आपतकालीन कलब्याक मोडबाट निस्कनुहोस्।"</string>
+ <string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"गैर-आपत्कालीन कल गर्न आपत्कालीन कलब्याक मोडबाट निस्कनुहोस्।"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"नेटवर्कमा दर्ता भएको छैन।"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"मोबाइल नेटवर्क उपलब्ध छैन।"</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"मोबाइल नेटवर्क उपलब्ध छैन। कल गर्न तारविनाको नेटवर्कमा जडान गर्नुहोस्।"</string>
@@ -551,19 +551,19 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"कल सञ्चालन गर्न सकिँदैन।"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"एक कल गर्न एक ताररहितको सञ्जालमा जडान गर्नुहोस्।"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"कल गर्नका लागि Wi-Fi कलिङ सक्षम गर्नुहोस्।"</string>
- <string name="emergency_information_hint" msgid="9208897544917793012">"आपतकालीन जानकारी"</string>
+ <string name="emergency_information_hint" msgid="9208897544917793012">"आपत्कालीन जानकारी"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"मालिक"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"जानकारी हेर्न पुनः ट्याप गर्नुहोस्"</string>
- <string name="emergency_enable_radio_dialog_title" msgid="2667568200755388829">"आपतकालीन कल"</string>
- <string name="single_emergency_number_title" msgid="8413371079579067196">"आपतकालीन नम्बर"</string>
- <string name="numerous_emergency_numbers_title" msgid="8972398932506755510">"आपतकालीन नम्बरहरू"</string>
+ <string name="emergency_enable_radio_dialog_title" msgid="2667568200755388829">"आपत्कालीन कल"</string>
+ <string name="single_emergency_number_title" msgid="8413371079579067196">"आपत्कालीन नम्बर"</string>
+ <string name="numerous_emergency_numbers_title" msgid="8972398932506755510">"आपत्कालीन नम्बरहरू"</string>
<string name="emergency_call_shortcut_hint" msgid="1290485125107779500">"<xliff:g id="EMERGENCY_NUMBER">%s</xliff:g> मा कल गर्न फेरि ट्याप गर्नुहोस्"</string>
<string name="emergency_enable_radio_dialog_message" msgid="1695305158151408629">"रेडियो खोल्दै..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="4329131876852608587">"कुनै सेवा छैन। फेरि प्रयास गर्दै ..."</string>
- <string name="radio_off_during_emergency_call" msgid="8011154134040481609">"आपतकालीन कलको समयमा हवाइजहाज मोडमा प्रविष्ट गर्न सक्दैन।"</string>
- <string name="dial_emergency_error" msgid="825822413209026039">"कल गर्न सकिँदैन। <xliff:g id="NON_EMERGENCY_NUMBER">%s</xliff:g> आपतकालीन नम्बर होइन।"</string>
- <string name="dial_emergency_empty_error" msgid="2785803395047793634">"कल गर्न सकिँदैन। आपतकालीन नम्बर डायल गर्नुहोस्।"</string>
- <string name="dial_emergency_calling_not_available" msgid="6485846193794727823">"आपतकालीन कल सेवा उपलब्ध छैन"</string>
+ <string name="radio_off_during_emergency_call" msgid="8011154134040481609">"आपत्कालीन कलको समयमा हवाइजहाज मोडमा प्रविष्ट गर्न सक्दैन।"</string>
+ <string name="dial_emergency_error" msgid="825822413209026039">"कल गर्न सकिँदैन। <xliff:g id="NON_EMERGENCY_NUMBER">%s</xliff:g> आपत्कालीन नम्बर होइन।"</string>
+ <string name="dial_emergency_empty_error" msgid="2785803395047793634">"कल गर्न सकिँदैन। आपत्कालीन नम्बर डायल गर्नुहोस्।"</string>
+ <string name="dial_emergency_calling_not_available" msgid="6485846193794727823">"आपत्कालीन कल सेवा उपलब्ध छैन"</string>
<string name="pin_puk_system_user_only" msgid="1045147220686867922">"यन्त्रका मालिक मात्र PIN/PUK कोडहरू प्रविष्टि गर्न सक्नुहुन्छ।"</string>
<string name="police_type_description" msgid="2819533883972081757">"प्रहरी"</string>
<string name="ambulance_type_description" msgid="6798237503553180461">"एम्बुलेन्स सेवा"</string>
@@ -628,20 +628,20 @@
<string name="ota_try_again" msgid="6914781945599998550">"फेरि प्रयास गर्नुहोस्"</string>
<string name="ota_next" msgid="2041016619313475914">"अर्को"</string>
<string name="ecm_exit_dialog" msgid="4200691880721429078">"EcmExitDialog"</string>
- <string name="phone_entered_ecm_text" msgid="8431238297843035842">"आपतकालीन कलब्याक मोड प्रविष्टि गरियो"</string>
- <string name="phone_in_ecm_notification_title" msgid="6825016389926367946">"आपतकालीन कलब्याक मोड"</string>
+ <string name="phone_entered_ecm_text" msgid="8431238297843035842">"आपत्कालीन कलब्याक मोड प्रविष्टि गरियो"</string>
+ <string name="phone_in_ecm_notification_title" msgid="6825016389926367946">"आपत्कालीन कलब्याक मोड"</string>
<string name="phone_in_ecm_call_notification_text" msgid="653972232922670335">"डेटा जडान अक्षम भयो"</string>
- <string name="phone_in_ecm_notification_complete_time" msgid="7341624337163082759">"<xliff:g id="COMPLETETIME">%s</xliff:g> सम्म डेटा जडान भएको छैन"</string>
+ <string name="phone_in_ecm_notification_complete_time" msgid="7341624337163082759">"<xliff:g id="COMPLETETIME">%s</xliff:g> सम्म डेटा कनेक्ट भएको छैन"</string>
<plurals name="alert_dialog_exit_ecm" formatted="false" msgid="5425906903766466743">
- <item quantity="other"> फोन आपतकालीन कलब्याक मोडमा <xliff:g id="COUNT_1">%s</xliff:g> मिनेटको लागि हुनेछ। यस मोडको अवस्थामा एक डेटा जडान प्रयोग गरेर कुनै पनि एपहरू प्रयोग गर्न सकिँदैन। के तपाईं अहिले निस्कन चाहनुहुन्छ?</item>
- <item quantity="one"> फोन आपतकालीन कलब्याक मोडमा <xliff:g id="COUNT_0">%s</xliff:g> मिनेटको लागि हुनेछ। यस मोडको समयमा एक डेटा जडान प्रयोग गरेर कुनै पनि एपहरू प्रयोग गर्न सकिँदैन। के तपाईं अहिले निस्कन चाहनुहुन्छ?</item>
+ <item quantity="other"> फोन आपत्कालीन कलब्याक मोडमा <xliff:g id="COUNT_1">%s</xliff:g> मिनेटको लागि हुनेछ। यस मोडको अवस्थामा एक डेटा जडान प्रयोग गरेर कुनै पनि एपहरू प्रयोग गर्न सकिँदैन। के तपाईं अहिले निस्कन चाहनुहुन्छ?</item>
+ <item quantity="one"> फोन आपत्कालीन कलब्याक मोडमा <xliff:g id="COUNT_0">%s</xliff:g> मिनेटको लागि हुनेछ। यस मोडको समयमा एक डेटा जडान प्रयोग गरेर कुनै पनि एपहरू प्रयोग गर्न सकिँदैन। के तपाईं अहिले निस्कन चाहनुहुन्छ?</item>
</plurals>
<plurals name="alert_dialog_not_avaialble_in_ecm" formatted="false" msgid="1152682528741457004">
- <item quantity="other"> आपतकालीन कलब्याक मोडको समयमा चयनित कार्य उपलब्ध छैन। फोन यस मोडमा <xliff:g id="COUNT_1">%s</xliff:g> मिनेटको लागि हुनेछ। के तपाईं अहिले निस्कन चाहनुहुन्छ?</item>
- <item quantity="one"> आपतकालीन कलब्याक मोडको समयमा चयनित कार्य उपलब्ध छैन। फोन यस मोडमा <xliff:g id="COUNT_0">%s</xliff:g> मिनेटको लागि हुनेछ। के तपाईं अहिले निस्कन चाहनुहुन्छ?</item>
+ <item quantity="other"> आपत्कालीन कलब्याक मोडको समयमा चयनित कार्य उपलब्ध छैन। फोन यस मोडमा <xliff:g id="COUNT_1">%s</xliff:g> मिनेटको लागि हुनेछ। के तपाईं अहिले निस्कन चाहनुहुन्छ?</item>
+ <item quantity="one"> आपत्कालीन कलब्याक मोडको समयमा चयनित कार्य उपलब्ध छैन। फोन यस मोडमा <xliff:g id="COUNT_0">%s</xliff:g> मिनेटको लागि हुनेछ। के तपाईं अहिले निस्कन चाहनुहुन्छ?</item>
</plurals>
- <string name="alert_dialog_in_ecm_call" msgid="1207545603149771978">"आपतकालीन कल हुँदा चयन भएको कार्य उपलब्ध हुँदैन।"</string>
- <string name="progress_dialog_exiting_ecm" msgid="9159080081676927217">"आपतकालीन कलब्याक मोडबाट निस्कदै"</string>
+ <string name="alert_dialog_in_ecm_call" msgid="1207545603149771978">"आपत्कालीन कल हुँदा चयन भएको कार्य उपलब्ध हुँदैन।"</string>
+ <string name="progress_dialog_exiting_ecm" msgid="9159080081676927217">"आपत्कालीन कलब्याक मोडबाट निस्कदै"</string>
<string name="alert_dialog_yes" msgid="3532525979632841417">"हो"</string>
<string name="alert_dialog_no" msgid="1075632654085988420">"होइन"</string>
<string name="alert_dialog_dismiss" msgid="1336356286354517054">"खारेज गर्नुहोस्"</string>
@@ -662,7 +662,7 @@
<string name="not_voice_capable" msgid="2819996734252084253">"भ्वाइस कल गर्ने समर्थित छैन"</string>
<string name="description_dial_button" msgid="8614631902795087259">"डायल"</string>
<string name="description_dialpad_button" msgid="7395114120463883623">"डायलप्याड देखाउनुहोस्"</string>
- <string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"आपतकालीन डायलप्याड"</string>
+ <string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"आपत्कालीन डायलप्याड"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="6610414098912832120">"भिजुअल भ्वाइस मेल"</string>
<string name="voicemail_set_pin_dialog_title" msgid="7005128605986960003">"PIN सेट गर्नुहोस्"</string>
<string name="voicemail_change_pin_dialog_title" msgid="4633077715231764435">"PIN परिवर्तन गर्नुहोस्"</string>
@@ -686,7 +686,7 @@
<string name="callFailed_wifi_lost" msgid="1788036730589163141">"Wi-Fi जडान विच्छेद भयो। कल समाप्त भयो।"</string>
<string name="dialFailed_low_battery" msgid="6857904237423407056">"ब्याट्रीको चार्ज स्तर कम हुनाले तपाईं भिडियो कल गर्न सक्नुहुन्न।"</string>
<string name="callFailed_low_battery" msgid="4056828320214416182">"ब्याट्रीको चार्ज स्तर कम हुनाले भिडियो कल बन्द भयो।"</string>
- <string name="callFailed_emergency_call_over_wfc_not_available" msgid="5944309590693432042">"यो स्थानमा Wi-Fi कलिङमार्फत आपतकालीन कलहरू गर्ने सुविधा उपलब्ध छैन।"</string>
+ <string name="callFailed_emergency_call_over_wfc_not_available" msgid="5944309590693432042">"यो स्थानमा Wi-Fi कलिङमार्फत आपत्कालीन कलहरू गर्ने सुविधा उपलब्ध छैन।"</string>
<string name="callFailed_wfc_service_not_available_in_this_location" msgid="3624536608369524988">"यो स्थानमा Wi-Fi कलिङ उपलब्ध छैन।"</string>
<string name="change_pin_title" msgid="3564254326626797321">"भ्वाइस मेलको PIN परिवर्तन गर्नुहोस्"</string>
<string name="change_pin_continue_label" msgid="5177011752453506371">"जारी राख्नुहोस्"</string>
@@ -853,7 +853,7 @@
<string name="radio_info_ims_reg_status" msgid="25582845222446390">"IMS को दर्ता: <xliff:g id="STATUS">%1$s</xliff:g>\nभ्वाइस ओभर LTE: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nभ्वाइस ओभर WiFi: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nभिडियो कलिङ: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nUT को इन्टरफेस: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
<string name="radioInfo_service_in" msgid="45753418231446400">"सेवामा"</string>
<string name="radioInfo_service_out" msgid="287972405416142312">"सेवा उपलब्ध छैन"</string>
- <string name="radioInfo_service_emergency" msgid="4763879891415016848">"आपतकालीन कल मात्र"</string>
+ <string name="radioInfo_service_emergency" msgid="4763879891415016848">"आपत्कालीन कल मात्र"</string>
<string name="radioInfo_service_off" msgid="3456583511226783064">"रेडियो निष्क्रिय छ"</string>
<string name="radioInfo_roaming_in" msgid="3156335577793145965">"रोमिङ"</string>
<string name="radioInfo_roaming_not" msgid="1904547918725478110">"रोमिङमा छैन"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"पूर्वनिर्धारित डेटा SIM को SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL ब्यान्डविथ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL व्यान्डविथ (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"सेलको स्थानबारे जानकारी (चल्तीबाट हटाइएको):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE को भौतिक च्यानलको कन्फिगरेसन:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"सेलसम्बन्धी जानकारीलाई पुनः ताजा गरिने दर:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"सेलको मापनसम्बन्धी सबै जानकारी:"</string>
@@ -902,7 +901,7 @@
<string name="radio_info_http_client_test" msgid="1329583721088428238">"HTTP क्लाइन्टको परीक्षण:"</string>
<string name="ping_test_label" msgid="448617502935719694">"पिङसम्बन्धी परीक्षण सञ्चालन गर्नुहोस्"</string>
<string name="radio_info_smsc_label" msgid="3749927072726033763">"SMSC:"</string>
- <string name="radio_info_smsc_update_label" msgid="5141996256097115753">"अद्यावधिक गर्नुहोस्"</string>
+ <string name="radio_info_smsc_update_label" msgid="5141996256097115753">"अपडेट गर्नुहोस्"</string>
<string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"पुनः ताजा गर्नुहोस्"</string>
<string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS को जाँचलाई टगल गर्नुहोस्"</string>
<string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-विशिष्ट जानकारी/सेटिङ"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index e3be4af..1013da8 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -32,7 +32,7 @@
<string name="mmiCancelled" msgid="5339191899200678272">"MMI-code geannuleerd"</string>
<string name="cancel" msgid="8984206397635155197">"Annuleren"</string>
<string name="enter_input" msgid="6193628663039958990">"USSD-bericht moet tussen <xliff:g id="MIN_LEN">%1$d</xliff:g> en <xliff:g id="MAX_LEN">%2$d</xliff:g> tekens lang zijn. Probeer het opnieuw."</string>
- <string name="manageConferenceLabel" msgid="8415044818156353233">"Telefonische vergadering beheren"</string>
+ <string name="manageConferenceLabel" msgid="8415044818156353233">"Conferencecall beheren"</string>
<string name="ok" msgid="7818974223666140165">"OK"</string>
<string name="audio_mode_speaker" msgid="243689733219312360">"Luidspreker"</string>
<string name="audio_mode_earpiece" msgid="2823700267171134282">"Oortelefoon van handset"</string>
@@ -514,11 +514,11 @@
<string name="pin2_attempts" msgid="5625178102026453023">\n"Je hebt nog <xliff:g id="NUMBER">%d</xliff:g> pogingen."</string>
<string name="pin2_unblocked" msgid="4481107908727789303">"PIN2 niet langer geblokkeerd"</string>
<string name="pin2_error_exception" msgid="8116103864600823641">"Netwerk- of simkaartfout"</string>
- <string name="doneButton" msgid="7371209609238460207">"Gereed"</string>
+ <string name="doneButton" msgid="7371209609238460207">"Klaar"</string>
<string name="voicemail_settings_number_label" msgid="1265118640154688162">"Voicemailnummer"</string>
<string name="card_title_dialing" msgid="8742182654254431781">"Kiezen"</string>
<string name="card_title_redialing" msgid="18130232613559964">"Opnieuw bellen"</string>
- <string name="card_title_conf_call" msgid="901197309274457427">"Telefonische vergadering"</string>
+ <string name="card_title_conf_call" msgid="901197309274457427">"Conferencecall"</string>
<string name="card_title_incoming_call" msgid="881424648458792430">"Inkomend gesprek"</string>
<string name="card_title_call_ended" msgid="650223980095026340">"Gesprek beëindigd"</string>
<string name="card_title_on_hold" msgid="9028319436626975207">"In de wacht"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId van standaard simkaart voor data:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL-bandbreedte (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL-bandbreedte (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Mobiele locatiegegevens (beëindigd):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Fysieke LTE-kanaalconfiguratie:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Vernieuwingsfrequentie van mobiele data:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Alle mobiele meetgegevens:"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index e88c745..e0523e4 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ଡିଫଲ୍ଟ ଡାଟା SIMର SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL ବ୍ୟାଣ୍ଡୱିଡଥ୍ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL ବ୍ୟାଣ୍ଡୱିଡଥ୍ (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"ସେଲ୍ ଲୋକେସନ୍ ସୂଚନା (ଅନୁରୋଧ କରାଯାଇଛି):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ଫିଜିକାଲ୍ ଚ୍ୟାନେଲ୍ କନ୍ଫିଗରେସନ୍:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ସେଲ୍ ସୂଚନା ରିଫ୍ରେସ୍ ଦର:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ସମସ୍ତ ସେଲ୍ ପରିମାପ ସୂଚନା:"</string>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 1a05015..69da642 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ਪੂਰਵ-ਨਿਰਧਾਰਤ ਡਾਟਾ ਸਿਮ ਦਾ SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL ਬੈਂਡਵਿਡਥ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL ਬੈਂਡਵਿਡਥ (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"ਸੈੱਲ ਦੀ ਟਿਕਾਣਾ ਜਾਣਕਾਰੀ (ਨਾਪਸੰਦ ਕੀਤੀ):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ਭੌਤਿਕ ਚੈਨਲ ਸੰਰੂਪਣ:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ਸੈੱਲ ਦੀ ਜਾਣਕਾਰੀ ਦੀ ਰਿਫ੍ਰੈਸ਼ ਦਰ:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ਸਾਰੀ ਸੈੱਲ ਮਾਪ ਜਾਣਕਾਰੀ:"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 498ff71..4abf1d4 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -50,8 +50,7 @@
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Ustawienia poczty głosowej może zmienić tylko użytkownik główny."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"Karta SIM została odblokowana. Odblokowywanie telefonu..."</string>
<string name="label_ndp" msgid="7617392683877410341">"Kod PIN do karty SIM odblokowujący sieć"</string>
- <!-- no translation found for label_phoneid (8775611434123577808) -->
- <skip />
+ <string name="label_phoneid" msgid="8775611434123577808">"Urządzenie obsługuje tylko karty SIM operatora"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Odblokuj"</string>
<string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Zamknij"</string>
<string name="requesting_unlock" msgid="930512210309437741">"Żądanie odblokowania sieci..."</string>
@@ -882,7 +881,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Identyfikator domyślnej karty SIM do transmisji danych:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Przepustowość kanału DL (kb/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Przepustowość kanału UL (kb/s):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informacje o lokalizacji z sieci komórkowej (wycofane):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguracja kanału fizycznego LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Częstotliwość odświeżania informacji o sieci komórkowej:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Wszystkie informacje pomiarowe z sieci komórkowej:"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 8cd9be2..a3242ba 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -96,10 +96,10 @@
<string name="sum_loading_settings" msgid="434063780286688775">"A carregar as definições..."</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"Ocultar o número em chamadas efectuadas"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"Número apresentado em chamadas efectuadas"</string>
- <string name="sum_default_caller_id" msgid="1767070797135682959">"Utilizar as predefinições do operador para apresentar o meu número nas chamadas efectuadas"</string>
+ <string name="sum_default_caller_id" msgid="1767070797135682959">"Utilizar as predefinições do operador para apresentar o meu número nas chamadas efetuadas"</string>
<string name="labelCW" msgid="8449327023861428622">"Chamada em espera"</string>
- <string name="sum_cw_enabled" msgid="3977308526187139996">"Notificar-me de chamadas a receber durante uma chamada"</string>
- <string name="sum_cw_disabled" msgid="3658094589461768637">"Notificar-me de chamadas a receber durante uma chamada"</string>
+ <string name="sum_cw_enabled" msgid="3977308526187139996">"Notificar-me de chamadas em espera durante uma chamada"</string>
+ <string name="sum_cw_disabled" msgid="3658094589461768637">"Notificar-me de chamadas em espera durante uma chamada"</string>
<string name="call_forwarding_settings" msgid="8937130467468257671">"Definições do encaminhamento de chamadas"</string>
<string name="call_forwarding_settings_with_label" msgid="2345432813399564272">"Definições de encaminhamento de chamadas (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="labelCF" msgid="3578719437928476078">"Encaminhamento de chamadas"</string>
@@ -144,7 +144,7 @@
<string name="stk_cc_ss_to_ussd_error" msgid="8330749347425752192">"Pedido SS alterado para um novo pedido USSD"</string>
<string name="stk_cc_ss_to_ss_error" msgid="8297155544652134278">"Foi alterado para um novo pedido SS"</string>
<string name="stk_cc_ss_to_dial_video_error" msgid="4255261231466032505">"O pedido SS foi alterado para uma videochamada"</string>
- <string name="fdn_check_failure" msgid="1833769746374185247">"A definição Números Autorizados da aplicação do seu Telemóvel está ativada. Por conseguinte, algumas funcionalidades relacionadas com chamadas não estão a funcionar."</string>
+ <string name="fdn_check_failure" msgid="1833769746374185247">"A definição Números Autorizados da app do seu Telemóvel está ativada. Por conseguinte, algumas funcionalidades relacionadas com chamadas não estão a funcionar."</string>
<string name="radio_off_error" msgid="8321564164914232181">"Ative o rádio antes de visualizar estas definições."</string>
<string name="close_dialog" msgid="1074977476136119408">"OK"</string>
<string name="enable" msgid="2636552299455477603">"Ativar"</string>
@@ -294,7 +294,7 @@
<string name="limited_sim_function_notification_title" msgid="612715399099846281">"Funcionalidade de SIM limitada"</string>
<string name="limited_sim_function_with_phone_num_notification_message" msgid="5928988883403677610">"As chamadas e os serviços de dados da <xliff:g id="CARRIER_NAME">%1$s</xliff:g> podem ficar bloqueados ao utilizar o número <xliff:g id="PHONE_NUMBER">%2$s</xliff:g>."</string>
<string name="limited_sim_function_notification_message" msgid="5338638075496721160">"As chamadas e serviços de dados da <xliff:g id="CARRIER_NAME">%1$s</xliff:g> podem ser bloqueados se utilizar outro SIM."</string>
- <string name="data_usage_title" msgid="8438592133893837464">"Utilização de dados da aplicação"</string>
+ <string name="data_usage_title" msgid="8438592133893837464">"Utilização de dados da app"</string>
<string name="data_usage_template" msgid="6287906680674061783">"<xliff:g id="ID_1">%1$s</xliff:g> de dados móveis utilizados entre <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="advanced_options_title" msgid="9208195294513520934">"Avançadas"</string>
<string name="carrier_settings_euicc" msgid="1190237227261337749">"Operador"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubID do SIM de dados predefinido:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Largura de banda de transferência (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Largura de banda de carregamento (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informações da localização da célula (descontinuadas):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuração do canal físico LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Taxa de atualização das informações da célula:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Todas as informações de medição de células:"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 29add63..4b71e5b 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -92,14 +92,14 @@
<string name="additional_cdma_call_settings" msgid="2178016561980611304">"Configurações de chamada CDMA adicionais"</string>
<string name="sum_cdma_call_settings" msgid="3185825305136993636">"Configurações adicionais somente de chamada CDMA"</string>
<string name="labelNwService" msgid="6015891883487125120">"Configurações do serviço de rede"</string>
- <string name="labelCallerId" msgid="2090540744550903172">"ID da chamada"</string>
+ <string name="labelCallerId" msgid="2090540744550903172">"Identificador de chamadas"</string>
<string name="sum_loading_settings" msgid="434063780286688775">"Carregando configurações…"</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"Número oculto nas chamadas enviadas"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"Número exibido nas chamadas enviadas"</string>
- <string name="sum_default_caller_id" msgid="1767070797135682959">"Usar configurações padrão da operadora para exibir meu número em chamadas efetuadas"</string>
+ <string name="sum_default_caller_id" msgid="1767070797135682959">"Usar configurações padrão da operadora para exibir meu número em chamadas realizadas"</string>
<string name="labelCW" msgid="8449327023861428622">"Chamada em espera"</string>
- <string name="sum_cw_enabled" msgid="3977308526187139996">"Notificar sobre a entrada de outras chamadas durante uma ligação"</string>
- <string name="sum_cw_disabled" msgid="3658094589461768637">"Notificar sobre a entrada de outras chamadas durante uma ligação"</string>
+ <string name="sum_cw_enabled" msgid="3977308526187139996">"Notificar sobre outras chamadas recebidas durante uma ligação"</string>
+ <string name="sum_cw_disabled" msgid="3658094589461768637">"Notificar sobre outras chamadas recebidas durante uma ligação"</string>
<string name="call_forwarding_settings" msgid="8937130467468257671">"Configurações de encaminhamento de chamada"</string>
<string name="call_forwarding_settings_with_label" msgid="2345432813399564272">"Configurações de encaminhamento de chamada (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="labelCF" msgid="3578719437928476078">"Encaminhamento de chamada"</string>
@@ -144,7 +144,7 @@
<string name="stk_cc_ss_to_ussd_error" msgid="8330749347425752192">"Solicitação SS alterada para solicitação USSD"</string>
<string name="stk_cc_ss_to_ss_error" msgid="8297155544652134278">"Alterada para uma nova solicitação SS"</string>
<string name="stk_cc_ss_to_dial_video_error" msgid="4255261231466032505">"Solicitação SS alterada para videochamada"</string>
- <string name="fdn_check_failure" msgid="1833769746374185247">"A configuração \"Números de discagem fixa\" do seu app Telefone está ativada. Por isso, alguns recursos relacionados a chamadas não funcionam."</string>
+ <string name="fdn_check_failure" msgid="1833769746374185247">"A configuração \"N fixa\" do seu app Telefone está ativada. Por isso, alguns recursos relacionados a chamadas não funcionam."</string>
<string name="radio_off_error" msgid="8321564164914232181">"Ligue o rádio antes de ver essas configurações."</string>
<string name="close_dialog" msgid="1074977476136119408">"OK"</string>
<string name="enable" msgid="2636552299455477603">"Ativar"</string>
@@ -433,8 +433,8 @@
<string name="cdma_activate_device" msgid="5914720276140097632">"Ativar aparelho"</string>
<string name="cdma_lte_data_service" msgid="359786441782404562">"Configurar serviço de dados"</string>
<string name="carrier_settings_title" msgid="6292869148169850220">"Config. da operadora"</string>
- <string name="fdn" msgid="2545904344666098749">"Números de discagem fixa"</string>
- <string name="fdn_with_label" msgid="6412087553365709494">"Números de discagem fixa (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
+ <string name="fdn" msgid="2545904344666098749">"N fixa"</string>
+ <string name="fdn_with_label" msgid="6412087553365709494">"N fixa (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="manage_fdn_list" msgid="3341716430375195441">"Lista FDN"</string>
<string name="fdn_list_with_label" msgid="1409655283510382556">"Lista de FDNs (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="fdn_activation" msgid="2178637004710435895">"Ativação do FDN"</string>
@@ -516,9 +516,9 @@
<string name="pin2_error_exception" msgid="8116103864600823641">"Erro de rede ou do chip"</string>
<string name="doneButton" msgid="7371209609238460207">"Concluído"</string>
<string name="voicemail_settings_number_label" msgid="1265118640154688162">"Número correio de voz"</string>
- <string name="card_title_dialing" msgid="8742182654254431781">"Discando"</string>
+ <string name="card_title_dialing" msgid="8742182654254431781">"Chamando..."</string>
<string name="card_title_redialing" msgid="18130232613559964">"Rediscando"</string>
- <string name="card_title_conf_call" msgid="901197309274457427">"teleconferência"</string>
+ <string name="card_title_conf_call" msgid="901197309274457427">"Teleconferência"</string>
<string name="card_title_incoming_call" msgid="881424648458792430">"Recebendo chamada"</string>
<string name="card_title_call_ended" msgid="650223980095026340">"Chamada encerrada"</string>
<string name="card_title_on_hold" msgid="9028319436626975207">"Em espera"</string>
@@ -562,7 +562,7 @@
<string name="emergency_enable_radio_dialog_retry" msgid="4329131876852608587">"Sem serviço. Tentando novamente..."</string>
<string name="radio_off_during_emergency_call" msgid="8011154134040481609">"Não é possível usar o modo avião durante uma chamada de emergência."</string>
<string name="dial_emergency_error" msgid="825822413209026039">"Não é possível realizar chamadas. <xliff:g id="NON_EMERGENCY_NUMBER">%s</xliff:g> não é um telefone de emergência."</string>
- <string name="dial_emergency_empty_error" msgid="2785803395047793634">"Não é possível realizar chamadas. Disque o número de telefone de emergência."</string>
+ <string name="dial_emergency_empty_error" msgid="2785803395047793634">"Não é possível realizar chamadas. Ligue para o número de telefone de emergência."</string>
<string name="dial_emergency_calling_not_available" msgid="6485846193794727823">"Chamada de emergência indisponível"</string>
<string name="pin_puk_system_user_only" msgid="1045147220686867922">"Somente o proprietário do dispositivo pode digitar os códigos PIN/PUK."</string>
<string name="police_type_description" msgid="2819533883972081757">"Polícia"</string>
@@ -580,7 +580,7 @@
<string name="onscreenManageCallsText" msgid="1162047856081836469">"Gerenciar chamadas"</string>
<string name="onscreenManageConferenceText" msgid="4700574060601755137">"Gerenciar conferência"</string>
<string name="onscreenAudioText" msgid="7224226735052019986">"Áudio"</string>
- <string name="onscreenVideoCallText" msgid="1743992456126258698">"Videocham."</string>
+ <string name="onscreenVideoCallText" msgid="1743992456126258698">"Vídeo"</string>
<string name="importSimEntry" msgid="3892354284082689894">"Importar"</string>
<string name="importAllSimEntries" msgid="2628391505643564007">"Importar tudo"</string>
<string name="importingSimContacts" msgid="4995457122107888932">"Importando contatos do chip"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Subcódigo do chip de dados padrão:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Largura de banda DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Largura de banda UL (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informações de local do celular (uso suspenso):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuração do canal físico de LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Taxa de atualização das informações do celular:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Todas as informações de medição do celular:"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index b0aba84..559ee07 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -878,7 +878,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId pentru SIM-ul de date prestabilit:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Lățime de bandă de descărcare (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Lățime de bandă de încărcare (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informații despre localizarea celulei (învechite):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configurarea canalului fizic LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Rata de actualizare a informațiilor despre celulă:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Toate informațiile de măsurare despre celulă:"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index c97d7f1..8e59241 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -97,7 +97,7 @@
<string name="sum_hide_caller_id" msgid="131100328602371933">"Скрывать номер при исходящих вызовах"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"Номер, отображающийся при исходящих вызовах"</string>
<string name="sum_default_caller_id" msgid="1767070797135682959">"Использовать стандартные настройки оператора для показа моего номера при исходящих вызовах"</string>
- <string name="labelCW" msgid="8449327023861428622">"Параллельный вызов"</string>
+ <string name="labelCW" msgid="8449327023861428622">"Ожидание вызова"</string>
<string name="sum_cw_enabled" msgid="3977308526187139996">"Извещать меня о входящих вызовах во время разговора"</string>
<string name="sum_cw_disabled" msgid="3658094589461768637">"Извещать меня о входящих вызовах во время разговора"</string>
<string name="call_forwarding_settings" msgid="8937130467468257671">"Переадресация"</string>
@@ -881,7 +881,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Доп. идентификатор SIM-карты для мобильного Интернета по умолчанию:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Пропускная способность DL-канала (кбит/c):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Пропускная способность UL-канала (кбит/с):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Информация о местоположении сети (устаревшее):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Конфигурация физического канала LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Частота обновления данных о сетях:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Статистика сети:"</string>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index 8d2b9b8..afab89a 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"පෙරනිමි දත්ත SIM පතේ උප හැඳුනුම:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL කලාප පළල (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL කලාප පළල (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"සෙල් ස්ථාන තොරතුරු (අත් හරින ලදී):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE භෞතික නාලිකා වින්යාසය:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"සෙල් තොරතුරු නැවුම් කිරීමේ අනුපාතය:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"සියලු සෙල් මිනුම් තොරතුරු:"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 5fdf1b2..f667513 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -135,7 +135,7 @@
<string name="call_settings_admin_user_only" msgid="7238947387649986286">"Nastavenia hovorov môže zmeniť iba používateľ s povoleniami správcu."</string>
<string name="call_settings_with_label" msgid="8460230435361579511">"Nastavenia (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="error_updating_title" msgid="2024290892676808965">"Chyba nastavení hovorov"</string>
- <string name="reading_settings" msgid="1605904432450871183">"Nastavenia sa načítajú…"</string>
+ <string name="reading_settings" msgid="1605904432450871183">"Nastavenia sa načítavajú…"</string>
<string name="updating_settings" msgid="3650396734816028808">"Prebieha aktualizácia nastavení..."</string>
<string name="reverting_settings" msgid="7378668837291012205">"Prebieha vrátenie predchádzajúcich nastavení…"</string>
<string name="response_error" msgid="3904481964024543330">"Neočakávaná odpoveď siete."</string>
@@ -881,7 +881,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Podradený identifikátor predvolenej dátovej SIM karty:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Rýchlosť pripojenia DL (kB/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Rýchlosť pripojenia UL (kB/s):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informácie o polohe mobilnej siete (podpora bola ukončená):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurácia fyzického kanála LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frekvencia obnovenia informácií o mobilnej sieti:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Všetky informácie o meraní mobilnej siete:"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index fa00faf..db13d74 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -881,7 +881,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ID naročnine privzete kartice SIM za prenos podatkov:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Pasovna širina za prenos (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Pasovna širina za nalaganje (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Podatki o lokaciji celice (zastarelo):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguracija fizičnega kanala LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frekvenca osveževanja podatkov o celici:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Vsi podatki o meritvah celice:"</string>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index ba5a5df..412fac0 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -50,8 +50,7 @@
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Cilësimet e postës zanore mund të modifikohen vetëm nga \"Përdoruesi kryesor\""</string>
<string name="puk_unlocked" msgid="4627340655215746511">"Karta jote SIM u zhbllokua. Telefoni yt po shkyçet..."</string>
<string name="label_ndp" msgid="7617392683877410341">"PIN-i i shkyçjes së rrjetit të kartës SIM"</string>
- <!-- no translation found for label_phoneid (8775611434123577808) -->
- <skip />
+ <string name="label_phoneid" msgid="8775611434123577808">"Karta SIM e kyçur për operatorin"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Shkyçe"</string>
<string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Injoro"</string>
<string name="requesting_unlock" msgid="930512210309437741">"Po kërkon shkyçjen e rrjetit…"</string>
@@ -76,7 +75,7 @@
<string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"Konfiguro cilësimet e llogarisë"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"Të gjitha llogaritë e telefonatave"</string>
<string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"Zgjidh se cilat llogari mund të kryejnë telefonata"</string>
- <string name="wifi_calling" msgid="3650509202851355742">"Telefonatë me Wi-Fi"</string>
+ <string name="wifi_calling" msgid="3650509202851355742">"Telefonata me Wi-Fi"</string>
<string name="connection_service_default_label" msgid="7332739049855715584">"Shërbim i integruar lidhjeje"</string>
<string name="voicemail" msgid="7697769412804195032">"Posta zanore"</string>
<string name="voicemail_settings_with_label" msgid="4228431668214894138">"Posta zanore (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -876,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ID-ja dytësore e kartës SIM të parazgjedhur të të dhënave:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Gjerësia e bandës DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Gjerësia e bandës UL (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Informacionet e vendndodhjes të rrjetit celular (e vjetruar):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurimi i kanalit fizik LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Shpejtësia e rifreskimit të informacioneve të rrjetit celular"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Të gjitha informacionet e matjes së rrjetit celular:"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 450a6a1..70df76d 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -75,7 +75,7 @@
<string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"Конфигурисање подешавања налога"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"Сви налози за позивање"</string>
<string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"Изаберите који налози могу да обављају позиве"</string>
- <string name="wifi_calling" msgid="3650509202851355742">"Позивање преко Wi-Fi-ја"</string>
+ <string name="wifi_calling" msgid="3650509202851355742">"Позивање преко WiFi-а"</string>
<string name="connection_service_default_label" msgid="7332739049855715584">"Уграђена услуга повезивања"</string>
<string name="voicemail" msgid="7697769412804195032">"Говорна пошта"</string>
<string name="voicemail_settings_with_label" msgid="4228431668214894138">"Гласовна пошта (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -119,7 +119,7 @@
<string name="sum_cfnry_enabled" msgid="3000500837493854799">"Прослеђује се на <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfnry_disabled" msgid="1990563512406017880">"Искључено"</string>
<string name="disable_cfnry_forbidden" msgid="3174731413216550689">"Оператер не подржава онемогућавање преусмеравања позива када се на позив не одговори."</string>
- <string name="labelCFNRc" msgid="4163399350778066013">"Кад сам недоступан/а"</string>
+ <string name="labelCFNRc" msgid="4163399350778066013">"Кад сам недоступан/на"</string>
<string name="messageCFNRc" msgid="6980340731313007250">"Број кад је недоступно"</string>
<string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Прослеђује се на <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfnrc_disabled" msgid="739289696796917683">"Искључено"</string>
@@ -306,7 +306,7 @@
<string name="sim_selection_required_pref" msgid="6985901872978341314">"Потребно је да изаберете нешто"</string>
<string name="sim_change_data_title" msgid="9142726786345906606">"Да променимо SIM за податке?"</string>
<string name="sim_change_data_message" msgid="3567358694255933280">"Желите ли да за мобилне податке користите <xliff:g id="NEW_SIM">%1$s</xliff:g> уместо <xliff:g id="OLD_SIM">%2$s</xliff:g>?"</string>
- <string name="wifi_calling_settings_title" msgid="5800018845662016507">"Позивање преко Wi-Fi-ја"</string>
+ <string name="wifi_calling_settings_title" msgid="5800018845662016507">"Позивање преко WiFi-а"</string>
<string name="video_calling_settings_title" msgid="342829454913266078">"Видео позивање преко оператера"</string>
<string name="gsm_umts_options" msgid="4968446771519376808">"Опције за GSM/UMTS"</string>
<string name="cdma_options" msgid="3669592472226145665">"CDMA опције"</string>
@@ -550,7 +550,7 @@
<string name="incall_error_supp_service_hangup" msgid="836524952243836735">"Успостављање позива није успело."</string>
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Није могуће стављати позиве на чекање."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Повежите се на бежичну мрежу да бисте упутили позив."</string>
- <string name="incall_error_promote_wfc" msgid="9164896813931363415">"Омогућите позивање преко Wi-Fi-ја да бисте упутили позив."</string>
+ <string name="incall_error_promote_wfc" msgid="9164896813931363415">"Омогућите позивање преко WiFi-а да бисте упутили позив."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Информације за хитне случајеве"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Власник"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Додирните поново да бисте видели информације"</string>
@@ -572,7 +572,7 @@
<string name="dialerKeyboardHintText" msgid="1115266533703764049">"Користите тастатуру за позивање"</string>
<string name="onscreenHoldText" msgid="4025348842151665191">"Чекање"</string>
<string name="onscreenEndCallText" msgid="6138725377654842757">"Заврши"</string>
- <string name="onscreenShowDialpadText" msgid="658465753816164079">"Нумеричка тастатура"</string>
+ <string name="onscreenShowDialpadText" msgid="658465753816164079">"Бројчаник"</string>
<string name="onscreenMuteText" msgid="5470306116733843621">"Искључи звук"</string>
<string name="onscreenAddCallText" msgid="9075675082903611677">"Додај позив"</string>
<string name="onscreenMergeCallsText" msgid="3692389519611225407">"Обједини позиве"</string>
@@ -612,7 +612,7 @@
<string name="ota_hfa_activation_title" msgid="3300556778212729671">"Активирање..."</string>
<string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"Телефон активира услугу мобилног преноса података.\n\nТо може да потраје и до 5 минута."</string>
<string name="ota_skip_activation_dialog_title" msgid="7666611236789203797">"Желите ли да прескочите активацију?"</string>
- <string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"Ако прескочите активацију, не можете да упућујете позиве или да се повезујете са мрежама за мобилни пренос података (иако можете да се повежете са Wi-Fi мрежама). Све док не активирате свој телефон, бићете упитани да то учините сваки пут када га укључите."</string>
+ <string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"Ако прескочите активацију, не можете да упућујете позиве или да се повезујете са мрежама за мобилни пренос података (иако можете да се повежете са WiFi мрежама). Све док не активирате свој телефон, бићете упитани да то учините сваки пут када га укључите."</string>
<string name="ota_skip_activation_dialog_skip_label" msgid="5908029466817825633">"Прескочи"</string>
<string name="ota_activate" msgid="7939695753665438357">"Активирај"</string>
<string name="ota_title_activate_success" msgid="1272135024761004889">"Телефон је активиран."</string>
@@ -665,7 +665,7 @@
<string name="not_voice_capable" msgid="2819996734252084253">"Аудио позиви нису подржани"</string>
<string name="description_dial_button" msgid="8614631902795087259">"бирање"</string>
<string name="description_dialpad_button" msgid="7395114120463883623">"прикажите нумеричку тастатуру"</string>
- <string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"Нумеричка тастатура за хитне позиве"</string>
+ <string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"Бројчаник за хитне позиве"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="6610414098912832120">"Визуелна говорна пошта"</string>
<string name="voicemail_set_pin_dialog_title" msgid="7005128605986960003">"Подесите PIN"</string>
<string name="voicemail_change_pin_dialog_title" msgid="4633077715231764435">"Промените PIN"</string>
@@ -679,18 +679,18 @@
<string name="sim_description_emergency_calls" msgid="5146872803938897296">"Само за хитне позиве"</string>
<string name="sim_description_default" msgid="7474671114363724971">"SIM картица, отвор: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="7883415189273700298">"Приступачност"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"Wi-Fi позив од"</string>
- <string name="status_hint_label_wifi_call" msgid="942993035689809853">"Wi-Fi позив"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"WiFi позив од"</string>
+ <string name="status_hint_label_wifi_call" msgid="942993035689809853">"WiFi позив"</string>
<string name="emergency_action_launch_hint" msgid="2762016865340891314">"Додирните поново да бисте отворили"</string>
<string name="message_decode_error" msgid="1061856591500290887">"Дошло је до грешке при декодирању поруке."</string>
<string name="callFailed_cdma_activation" msgid="5392057031552253550">"SIM картица је активирала услугу и ажурирала функције роминга на телефону."</string>
<string name="callFailed_cdma_call_limit" msgid="1074219746093031412">"Има превише активних позива. Завршите или обједините постојеће позиве пре него што упутите нови."</string>
<string name="callFailed_imei_not_accepted" msgid="7257903653685147251">"Повезивање није успело, убаците важећу SIM картицу."</string>
- <string name="callFailed_wifi_lost" msgid="1788036730589163141">"Wi-Fi веза је прекинута. Позив је завршен."</string>
+ <string name="callFailed_wifi_lost" msgid="1788036730589163141">"WiFi веза је прекинута. Позив је завршен."</string>
<string name="dialFailed_low_battery" msgid="6857904237423407056">"Не можете да упутите позив јер је батерија скоро празна."</string>
<string name="callFailed_low_battery" msgid="4056828320214416182">"Видео позив је прекинут јер је батерија скоро празна."</string>
- <string name="callFailed_emergency_call_over_wfc_not_available" msgid="5944309590693432042">"Хитни позиви помоћу функције Позивање преко Wi-Fi-ја нису доступни на овој локацији."</string>
- <string name="callFailed_wfc_service_not_available_in_this_location" msgid="3624536608369524988">"Позивање преко Wi-Fi-ја није доступно на овој локацији."</string>
+ <string name="callFailed_emergency_call_over_wfc_not_available" msgid="5944309590693432042">"Хитни позиви помоћу функције Позивање преко WiFi-а нису доступни на овој локацији."</string>
+ <string name="callFailed_wfc_service_not_available_in_this_location" msgid="3624536608369524988">"Позивање преко WiFi-а није доступно на овој локацији."</string>
<string name="change_pin_title" msgid="3564254326626797321">"Промените PIN кôд говорне поште"</string>
<string name="change_pin_continue_label" msgid="5177011752453506371">"Настави"</string>
<string name="change_pin_cancel_label" msgid="2301711566758827936">"Откажи"</string>
@@ -835,7 +835,7 @@
<string name="radio_info_data_connection_disable" msgid="6404751291511368706">"Онемогући везу за пренос података"</string>
<string name="volte_provisioned_switch_string" msgid="4812874990480336178">"Додељено за VoLTE"</string>
<string name="vt_provisioned_switch_string" msgid="8295542122512195979">"Видео позиви су додељени"</string>
- <string name="wfc_provisioned_switch_string" msgid="3835004640321078988">"Позивање преко Wi-Fi-ја је додељено"</string>
+ <string name="wfc_provisioned_switch_string" msgid="3835004640321078988">"Позивање преко WiFi-а је додељено"</string>
<string name="eab_provisioned_switch_string" msgid="4449676720736033035">"Додељен је EAB/присуство"</string>
<string name="cbrs_data_switch_string" msgid="6060356430838077653">"Подаци CBRS-а"</string>
<string name="dsds_switch_string" msgid="7564769822086764796">"Омогући DSDS"</string>
@@ -853,7 +853,7 @@
<string name="radio_info_ims_reg_status_not_registered" msgid="8045821447288876085">"Није регистровано"</string>
<string name="radio_info_ims_feature_status_available" msgid="6493200914756969292">"Доступно"</string>
<string name="radio_info_ims_feature_status_unavailable" msgid="8930391136839759778">"Није доступно"</string>
- <string name="radio_info_ims_reg_status" msgid="25582845222446390">"Регистрација IMS-а: <xliff:g id="STATUS">%1$s</xliff:g>\nГлас преко LTE-а: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nГлас преко Wi-Fi-ја: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nВидео позив: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nUT интерфејс: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
+ <string name="radio_info_ims_reg_status" msgid="25582845222446390">"Регистрација IMS-а: <xliff:g id="STATUS">%1$s</xliff:g>\nГлас преко LTE-а: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nГлас преко WiFi-а: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nВидео позив: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nUT интерфејс: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
<string name="radioInfo_service_in" msgid="45753418231446400">"Ради"</string>
<string name="radioInfo_service_out" msgid="287972405416142312">"Не ради"</string>
<string name="radioInfo_service_emergency" msgid="4763879891415016848">"Само хитни позиви"</string>
@@ -878,7 +878,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubID подразумеваног SIM-а за податке:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL пропусни опсег (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL пропусни опсег (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Информације о локацији предајника (застарело):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Конфигурација LTE физичког канала:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Учесталост освежавања информација о предајнику:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Све информације о мерењу за предајник:"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 8493a20..76d37f8 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -696,7 +696,7 @@
<string name="change_pin_enter_old_pin_hint" msgid="8801292976275169367">"Ange pinkoden till röstbrevlådan för att fortsätta."</string>
<string name="change_pin_enter_new_pin_header" msgid="4739465616733486118">"Ange en ny pinkod"</string>
<string name="change_pin_enter_new_pin_hint" msgid="2326038476516364210">"Pinkoden måste ha <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> siffror."</string>
- <string name="change_pin_confirm_pin_header" msgid="2606303906320705726">"Bekräfta pinkod"</string>
+ <string name="change_pin_confirm_pin_header" msgid="2606303906320705726">"Bekräfta PIN-kod"</string>
<string name="change_pin_confirm_pins_dont_match" msgid="305164501222587215">"Pinkoderna matchar inte"</string>
<string name="change_pin_succeeded" msgid="2504705600693014403">"Röstbrevlådans pinkod bekräftad"</string>
<string name="change_pin_system_error" msgid="7772788809875146873">"Det går inte att ställa in pinkod"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId för standarddata på SIM-kortet:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Bandbredd för nedladdning (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Bandbredd för uppladdning (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Platsinformation för mast (utfasad):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Fysisk kanalkonfiguration för LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frekvens för uppdatering av mastinformation:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Alla information om mastmätning:"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index b57f699..28f2503 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -24,7 +24,7 @@
<string name="unknown" msgid="8279698889921830815">"Haijulikani"</string>
<string name="private_num" msgid="4487990167889159992">" Number isiyojulikana"</string>
<string name="payphone" msgid="7936735771836716941">"Simu ya kulipia"</string>
- <string name="onHold" msgid="6132725550015899006">"Inangoja"</string>
+ <string name="onHold" msgid="6132725550015899006">"Imesitishwa"</string>
<string name="carrier_mmi_msg_title" msgid="6050165242447507034">"Ujumbe wa <xliff:g id="MMICARRIER">%s</xliff:g>"</string>
<string name="default_carrier_mmi_msg_title" msgid="7754317179938537213">"Ujumbe wa Mtoa Huduma"</string>
<string name="mmiStarted" msgid="9212975136944568623">"Msimbo wa MMI umeanza"</string>
@@ -50,8 +50,7 @@
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Mipangilio ya ujumbe wa sauti inaweza kubadilishwa na Mtumiaji wa Msingi Pekee."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"Kadi yako ya simu imefunguliwa. Simu yangu inafungua…."</string>
<string name="label_ndp" msgid="7617392683877410341">"PIN ya kufungua mtandao wa SIM"</string>
- <!-- no translation found for label_phoneid (8775611434123577808) -->
- <skip />
+ <string name="label_phoneid" msgid="8775611434123577808">"SIM imefungwa kwa mtoa huduma"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Fungua"</string>
<string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Ondoa"</string>
<string name="requesting_unlock" msgid="930512210309437741">"Inaomba mtandao ufunguliwe…."</string>
@@ -93,11 +92,11 @@
<string name="additional_cdma_call_settings" msgid="2178016561980611304">"Mipangilio ya ziada ya simu ya CDMA"</string>
<string name="sum_cdma_call_settings" msgid="3185825305136993636">"Mipangilio ya ziada ya simu ya CDMA tu"</string>
<string name="labelNwService" msgid="6015891883487125120">"Mipangilio ya huduma ya mtandao"</string>
- <string name="labelCallerId" msgid="2090540744550903172">"Kitambulisho cha mpigaji SIM"</string>
+ <string name="labelCallerId" msgid="2090540744550903172">"Kitambulisho cha anayepiga"</string>
<string name="sum_loading_settings" msgid="434063780286688775">"Mipangilio inapakia..."</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"Nambari imefichwa kwa simu unayopiga"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"Namba inaonekana kwa simu zinazopigwa"</string>
- <string name="sum_default_caller_id" msgid="1767070797135682959">"Tumia mipangilio ya kiendesha chaguomsingi kuonyesha namba kwa simu zinazopigwa"</string>
+ <string name="sum_default_caller_id" msgid="1767070797135682959">"Tumia mipangilio ya mtoa huduma chaguomsingi kuonyesha nambari kwa simu unazopiga"</string>
<string name="labelCW" msgid="8449327023861428622">"Simu inayosubiri kupokewa"</string>
<string name="sum_cw_enabled" msgid="3977308526187139996">"Wakati ninapokea simu, niarifu kuhusu simu zingine zinazoingia"</string>
<string name="sum_cw_disabled" msgid="3658094589461768637">"Wakati ninapokea simu, niarifu kuhusu simu zingine zinazoingia"</string>
@@ -137,7 +136,7 @@
<string name="call_settings_with_label" msgid="8460230435361579511">"Mipangilio (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="error_updating_title" msgid="2024290892676808965">"Hitilafu ya mipangilio ya kupiga simu"</string>
<string name="reading_settings" msgid="1605904432450871183">"Inasoma mipangilio…."</string>
- <string name="updating_settings" msgid="3650396734816028808">"Inaboresha mipangilio…"</string>
+ <string name="updating_settings" msgid="3650396734816028808">"Inasasisha mipangilio…"</string>
<string name="reverting_settings" msgid="7378668837291012205">"Inageuza mipangilio..."</string>
<string name="response_error" msgid="3904481964024543330">"Jibu lisilotarajiwa kutoka kwa mtandao."</string>
<string name="exception_error" msgid="330994460090467">"Hitilafu ya mtandao au SIM kadi."</string>
@@ -522,7 +521,7 @@
<string name="card_title_conf_call" msgid="901197309274457427">"Simu ya kongamano"</string>
<string name="card_title_incoming_call" msgid="881424648458792430">"Simu inayoingia"</string>
<string name="card_title_call_ended" msgid="650223980095026340">"Simu imekamilika"</string>
- <string name="card_title_on_hold" msgid="9028319436626975207">"Inangoja"</string>
+ <string name="card_title_on_hold" msgid="9028319436626975207">"Imesitishwa"</string>
<string name="card_title_hanging_up" msgid="814874106866647871">"Kukata simu"</string>
<string name="card_title_in_call" msgid="8231896539567594265">"Katika simu"</string>
<string name="notification_voicemail_title" msgid="3932876181831601351">"Ujumbe mpya wa sauti"</string>
@@ -876,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId ya SIM chaguomsingi ya data:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Kipimo Data cha DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Kipimo Data cha UL (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Maelezo ya Mahali Simu ya Mkononi Ilipo (huduma haipo tena):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Mipangilio ya Kituo Halisi cha LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Kasi ya Kuonyesha Upya Maelezo ya Simu:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Maelezo Yote ya Vipimo vya Simu:"</string>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index f83457d..29f191d 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"இயல்பான டேட்டா சிம்மின் துணை ஐடி:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL இணைய வேகம் (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL இணைய வேகம் (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"மொபைலின் இருப்பிடத் தகவல் (நிறுத்தப்பட்டது):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ஃபிசிக்கல் சேனல் உள்ளமைவு:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"மொபைல் தகவலின் புதுப்பிப்பு விகிதம்:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"அனைத்து மொபைல் அளவீட்டுத் தகவல்:"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index aa833b1..b6996f7 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -136,7 +136,7 @@
<string name="call_settings_with_label" msgid="8460230435361579511">"సెట్టింగ్లు (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="error_updating_title" msgid="2024290892676808965">"కాల్ సెట్టింగ్ల లోపం"</string>
<string name="reading_settings" msgid="1605904432450871183">"సెట్టింగ్లను చదువుతోంది…"</string>
- <string name="updating_settings" msgid="3650396734816028808">"సెట్టింగ్లను నవీకరిస్తోంది…"</string>
+ <string name="updating_settings" msgid="3650396734816028808">"సెట్టింగ్లను అప్డేట్ చేస్తోంది…"</string>
<string name="reverting_settings" msgid="7378668837291012205">"సెట్టింగ్లను తిరిగి మారుస్తోంది…"</string>
<string name="response_error" msgid="3904481964024543330">"నెట్వర్క్ నుండి ఊహించని ప్రతిస్పందన."</string>
<string name="exception_error" msgid="330994460090467">"నెట్వర్క్ లేదా SIM కార్డు లోపం."</string>
@@ -149,7 +149,7 @@
<string name="close_dialog" msgid="1074977476136119408">"సరే"</string>
<string name="enable" msgid="2636552299455477603">"ఆన్ చేయి"</string>
<string name="disable" msgid="1122698860799462116">"ఆఫ్ చేయి"</string>
- <string name="change_num" msgid="6982164494063109334">"నవీకరించు"</string>
+ <string name="change_num" msgid="6982164494063109334">"అప్డేట్ చేయి"</string>
<string-array name="clir_display_values">
<item msgid="8477364191403806960">"నెట్వర్క్ డిఫాల్ట్"</item>
<item msgid="6813323051965618926">"నంబర్ను దాచు"</item>
@@ -296,7 +296,7 @@
<string name="limited_sim_function_notification_message" msgid="5338638075496721160">"వేరొక SIMను ఉపయోగిస్తున్నప్పుడు <xliff:g id="CARRIER_NAME">%1$s</xliff:g> కాల్లు మరియు డేటా సేవలు బ్లాక్ చేయబడవచ్చు."</string>
<string name="data_usage_title" msgid="8438592133893837464">"యాప్ డేటా వినియోగం"</string>
<string name="data_usage_template" msgid="6287906680674061783">"<xliff:g id="ID_2">%2$s</xliff:g> మధ్య కాలంలో <xliff:g id="ID_1">%1$s</xliff:g> మొబైల్ డేటా ఉపయోగించబడింది"</string>
- <string name="advanced_options_title" msgid="9208195294513520934">"అధునాతనం"</string>
+ <string name="advanced_options_title" msgid="9208195294513520934">"అధునాతన సెట్టింగ్లు"</string>
<string name="carrier_settings_euicc" msgid="1190237227261337749">"క్యారియర్"</string>
<string name="keywords_carrier_settings_euicc" msgid="8540160967922063745">"క్యారియర్, ఇసిమ్, సిమ్, ఇయుక్, క్యారియర్లను మార్చు, క్యారియర్ను జోడించు"</string>
<string name="carrier_settings_euicc_summary" msgid="2027941166597330117">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g> — <xliff:g id="PHONE_NUMBER">%2$s</xliff:g>"</string>
@@ -589,7 +589,7 @@
<string name="failedToImportSingleContactMsg" msgid="228095510489830266">"పరిచయాన్ని దిగుమతి చేయడంలో విఫలమైంది"</string>
<string name="hac_mode_title" msgid="4127986689621125468">"వినికిడి సహాయక సాధనాలు"</string>
<string name="hac_mode_summary" msgid="7774989500136009881">"వినికిడి సహాయక సాధనం అనుకూలతను ప్రారంభించండి"</string>
- <string name="rtt_mode_title" msgid="3075948111362818043">"నిజ సమయ వచనం (RTT) కాల్"</string>
+ <string name="rtt_mode_title" msgid="3075948111362818043">"రియల్-టైమ్ టెక్స్ట్ (RTT) కాల్"</string>
<string name="rtt_mode_summary" msgid="8631541375609989562">"వాయిస్ కాల్లో సందేశాలు పంపడానికి అనుమతించండి"</string>
<string name="rtt_mode_more_information" msgid="587500128658756318">"బధిరులు, వినికిడి సమస్యలు ఉన్న వారు, మాట్లాడటంలో సమస్యలు ఉన్న వారు లేదా కేవలం వాయిస్తో అర్థం చేసుకోలేని కాలర్లకు RTT సహాయపడుతుంది.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>మరింత తెలుసుకోండి</a>\n <br><br> - RTT కాల్లు సందేశ లిపి మార్పు వలె సేవ్ చేయబడతాయి\n <br> - వీడియో కాల్ల కోసం RTT అందుబాటులో లేదు"</string>
<string name="no_rtt_when_roaming" msgid="5268008247378355389">"గమనిక: రోమింగ్లో ఉండగా RTTఅందుబాటులో ఉండదు"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"డిఫాల్ట్ డేటా SIM యొక్క SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL బ్యాండ్విడ్త్ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL బ్యాండ్విడ్త్ (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"సెల్ స్థాన సమాచారం (నిలిపివేయబడింది):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE భౌతిక ఛానెల్ కాన్ఫిగరేషన్:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"సెల్ సమాచార రిఫ్రెష్ సగటు:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"మొత్తం సెల్ పరిమాణ సమాచారం:"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 3825792..81d954f 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -433,8 +433,8 @@
<string name="cdma_activate_device" msgid="5914720276140097632">"เปิดใช้งานอุปกรณ์"</string>
<string name="cdma_lte_data_service" msgid="359786441782404562">"ตั้งค่าบริการข้อมูล"</string>
<string name="carrier_settings_title" msgid="6292869148169850220">"การตั้งค่าของผู้ให้บริการ"</string>
- <string name="fdn" msgid="2545904344666098749">"การจำกัดหมายเลขโทรออก"</string>
- <string name="fdn_with_label" msgid="6412087553365709494">"โหมดจำกัดการโทร (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
+ <string name="fdn" msgid="2545904344666098749">"หมายเลขโทรออกที่กำหนดตายตัว"</string>
+ <string name="fdn_with_label" msgid="6412087553365709494">"หมายเลขโทรออกที่กำหนดตายตัว (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="manage_fdn_list" msgid="3341716430375195441">"รายการ FDN"</string>
<string name="fdn_list_with_label" msgid="1409655283510382556">"รายการ FDN (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="fdn_activation" msgid="2178637004710435895">"การเปิดใช้งาน FDN"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId ของซิมอินเทอร์เน็ตเริ่มต้น:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"แบนด์วิดท์ดาวน์โหลด (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"แบนด์วิดท์อัปโหลด (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"ข้อมูลตำแหน่งของเครือข่ายมือถือ (เลิกใช้งานแล้ว):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"การกำหนดค่าแชเนลทางกายภาพของ LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"อัตราการรีเฟรชข้อมูลมือถือ:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ข้อมูลการวัดเครือข่ายมือถือทั้งหมด:"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index d2f5b7b..805edce 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -50,8 +50,7 @@
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Maaari lang baguhin ng Pangunahing User ang Mga Setting ng Voicemail."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"Na-unblock ang iyong SIM card. Nag-a-unlock ang telepono mo…"</string>
<string name="label_ndp" msgid="7617392683877410341">"PIN na pang-unlock ng SIM network"</string>
- <!-- no translation found for label_phoneid (8775611434123577808) -->
- <skip />
+ <string name="label_phoneid" msgid="8775611434123577808">"Na-lock para sa operator ang SIM"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"I-unlock"</string>
<string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Balewalain"</string>
<string name="requesting_unlock" msgid="930512210309437741">"Humihiling ng pag-unlock sa network…"</string>
@@ -76,7 +75,7 @@
<string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"I-configure ang mga setting ng account"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"Lahat ng account sa pagtawag"</string>
<string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"Piliin kung aling mga account ang maaaring tumawag"</string>
- <string name="wifi_calling" msgid="3650509202851355742">"Pagtawag sa pamamagitan ng Wi-Fi"</string>
+ <string name="wifi_calling" msgid="3650509202851355742">"Pagtawag gamit ang Wi-Fi"</string>
<string name="connection_service_default_label" msgid="7332739049855715584">"Built-in na serbisyo ng koneksyon"</string>
<string name="voicemail" msgid="7697769412804195032">"Voicemail"</string>
<string name="voicemail_settings_with_label" msgid="4228431668214894138">"Voicemail (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -876,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId ng default na data SIM:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL Bandwidth (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL Bandwidth (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Impormasyon ng Lokasyon ng Cell (hindi na ginagamit):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuration ng LTE Physical Channel:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Rate ng Pag-refresh ng Impormasyon ng Cell:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Impormasyon ng Pagsukat sa Lahat ng Cell:"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index e879134..1e2868c 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Varsayılan veri SIM\'inin alt kimliği:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"İndirme Bant Genişliği (kb/sn.):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Yükleme Bant Genişliği (kb/sn.):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Hücre Konumu Bilgisi (kullanımdan kaldırıldı):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE Fiziksel Kanal Yapılandırması:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Hücre Bilgilerini Yenileme Hızı:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Tüm Hücre Ölçümü Bilgileri:"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index e2864f7..54a2bc4 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -881,7 +881,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Субідентифікатор SIM-карти для даних за умовчанням:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Пропускна спроможність DL (кбіт/с):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Пропускна спроможність UL (кбіт/с):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Геодані телефона (більше не підтримуються):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Конфігурація фізичного каналу LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Частота оновлення даних про мобільний зв\'язок:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Усі дані про показники мобільного зв\'язку:"</string>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index f031b90..1aa482d 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -96,17 +96,17 @@
<string name="sum_loading_settings" msgid="434063780286688775">"ترتیبات لوڈ ہو رہی ہیں…"</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"باہر جانے والی کالوں میں نمبر پوشیدہ ہے"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"باہر جانے والی کالوں میں ڈسپلے نمبر ہوتا ہے"</string>
- <string name="sum_default_caller_id" msgid="1767070797135682959">"باہر جانے والی کالوں میں میرا نمبر ڈسپلے کرنے کیلئے ڈیفالٹ آپریٹر کی ترتیبات کا استعمال کریں"</string>
+ <string name="sum_default_caller_id" msgid="1767070797135682959">"آؤٹ گوئنگ کالوں میں میرا نمبر ڈسپلے کرنے کیلئے ڈیفالٹ آپریٹر کی ترتیبات کا استعمال کریں"</string>
<string name="labelCW" msgid="8449327023861428622">"کال کا انتظار"</string>
- <string name="sum_cw_enabled" msgid="3977308526187139996">"کال کے دوران، مجھے آنے والی کالوں سے مطلع کریں"</string>
- <string name="sum_cw_disabled" msgid="3658094589461768637">"کال کے دوران، مجھے آنے والی کالوں سے مطلع کریں"</string>
- <string name="call_forwarding_settings" msgid="8937130467468257671">"کال آگے منتقل کرنے کی ترتیبات"</string>
+ <string name="sum_cw_enabled" msgid="3977308526187139996">"کال کے دوران، مجھے اِن کمنگ کالوں سے مطلع کریں"</string>
+ <string name="sum_cw_disabled" msgid="3658094589461768637">"کال کے دوران، مجھے اِن کمنگ کالوں سے مطلع کریں"</string>
+ <string name="call_forwarding_settings" msgid="8937130467468257671">"کال فارورڈنگ کی ترتیبات"</string>
<string name="call_forwarding_settings_with_label" msgid="2345432813399564272">"کال فارورڈنگ ترتیبات (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="labelCF" msgid="3578719437928476078">"کال فارورڈنگ"</string>
- <string name="labelCFU" msgid="8870170873036279706">"ہمیشہ آگے منتقل کریں"</string>
+ <string name="labelCFU" msgid="8870170873036279706">"ہمیشہ فارورڈ کریں"</string>
<string name="messageCFU" msgid="1361806450979589744">"ہمیشہ یہ نمبر استعمال کریں"</string>
<string name="sum_cfu_enabled_indicator" msgid="9030139213402432776">"سبھی کالیں آگے منتقل کر رہا ہے"</string>
- <string name="sum_cfu_enabled" msgid="5806923046528144526">"سبھی کالیں <xliff:g id="PHONENUMBER">{0}</xliff:g> کو آگے منتقل کر رہا ہے"</string>
+ <string name="sum_cfu_enabled" msgid="5806923046528144526">"سبھی کالیں <xliff:g id="PHONENUMBER">{0}</xliff:g> کو فارورڈ ہو رہی ہیں"</string>
<string name="sum_cfu_enabled_no_number" msgid="7287752761743377930">"نمبر دستیاب نہیں ہے"</string>
<string name="sum_cfu_disabled" msgid="5010617134210809853">"آف"</string>
<string name="labelCFB" msgid="615265213360512768">"مصروف ہونے پر"</string>
@@ -519,7 +519,7 @@
<string name="card_title_dialing" msgid="8742182654254431781">"ڈائل ہو رہا ہے"</string>
<string name="card_title_redialing" msgid="18130232613559964">"دوبارہ ڈائل ہو رہا ہے"</string>
<string name="card_title_conf_call" msgid="901197309274457427">"کانفرنس کال"</string>
- <string name="card_title_incoming_call" msgid="881424648458792430">"آنے والی کال"</string>
+ <string name="card_title_incoming_call" msgid="881424648458792430">"اِن کمنگ کال"</string>
<string name="card_title_call_ended" msgid="650223980095026340">"کال ختم ہوگئی"</string>
<string name="card_title_on_hold" msgid="9028319436626975207">"ہولڈ پر"</string>
<string name="card_title_hanging_up" msgid="814874106866647871">"کال منقطع ہو رہی ہے"</string>
@@ -820,7 +820,7 @@
<string name="supp_service_held_call_released" msgid="2847835124639112410">"ہولڈ پر رکھی کال جاری ہو گئی۔"</string>
<string name="callFailed_otasp_provisioning_in_process" msgid="3345666183602879326">"کال نہیں کی جا سکتی کیوںکہ فی الحال آلہ فراہم کیا جا رہا ہے۔"</string>
<string name="callFailed_already_dialing" msgid="7250591188960691086">"کال نہیں کی جا سکتی کیونکہ باہر جانے والی دوسری کال پہلے سے ڈائل کی جا رہی ہے۔"</string>
- <string name="callFailed_already_ringing" msgid="2376603543544289303">"ایک جواب نہ ملنے والی موصول ہونے والی کال کی وجہ سے کال نہیں کی جا سکتی۔ نئی کال کرنے کے لیے پہلے موصول ہونے والی کال کا جواب دیں یا مسترد کریں۔"</string>
+ <string name="callFailed_already_ringing" msgid="2376603543544289303">"ایک جواب نہ ملنے والی اِن کمنگ کال کی وجہ سے کال نہیں کی جا سکتی۔ نئی کال کرنے کے لیے پہلے اِن کمنگ کال کا جواب دیں یا مسترد کریں۔"</string>
<string name="callFailed_calling_disabled" msgid="5010992739401206283">"ro.telephony.disable-call سسٹم کی خصوصیت کے ذریعے کال کرنے کو غیر فعال کر دیے جانے کی وجہ سے کال نہیں کی جا سکتی۔"</string>
<string name="callFailed_too_many_calls" msgid="5379426826618582180">"پہلے سے دو کالز کے پیش رفت میں ہونے کی وجہ سے کال نہیں کی جا سکتی۔ نئی کال کرنے کے لیے پہلے ان میں سے ایک کو غیر منسلک کریں یا انہیں کانفرنس میں ضم کریں۔"</string>
<string name="supp_service_over_ut_precautions" msgid="2145018231396701311">"<xliff:g id="SUPP_SERVICE">%s</xliff:g> استعمال کرنے کے لیے، یقینی بنائيں کہ موبائل ڈیٹا آن ہے۔ آپ موبائل یٹ ورک کی ترتیبات میں اسے تبدیل کر سکتے ہیں۔"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ڈیفالٹ ڈیٹا SIM کی SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL بینڈ وڈتھ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL بینڈ وڈتھ (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"سیل کے مقام کی معلومات (فرسودہ):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE فزيکل چینل کنفیگریشن:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"سیل کی معلومات ریفریش کرنے کی شرح:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"سیل پیمائش کی تمام معلومات:"</string>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index a604ce9..e18784a 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -24,7 +24,7 @@
<string name="unknown" msgid="8279698889921830815">"Noma’lum"</string>
<string name="private_num" msgid="4487990167889159992">"Yashirin raqam"</string>
<string name="payphone" msgid="7936735771836716941">"Taksofon"</string>
- <string name="onHold" msgid="6132725550015899006">"Kutmoqda"</string>
+ <string name="onHold" msgid="6132725550015899006">"Pauzada"</string>
<string name="carrier_mmi_msg_title" msgid="6050165242447507034">"<xliff:g id="MMICARRIER">%s</xliff:g> orqali xabar"</string>
<string name="default_carrier_mmi_msg_title" msgid="7754317179938537213">"Operatordan xabar"</string>
<string name="mmiStarted" msgid="9212975136944568623">"MMI kodi ishga tushirildi"</string>
@@ -50,8 +50,7 @@
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Ovozli pochta sozlamalarini faqat bosh foydalanuvchi o‘zgartira oladi."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"To‘sib qo‘yilgan SIM kartangiz ochildi. Telefoningiz qulfdan chiqarilmoqda…"</string>
<string name="label_ndp" msgid="7617392683877410341">"SIM kartani tarmoqdagi qulfidan chiqarish PIN kodi"</string>
- <!-- no translation found for label_phoneid (8775611434123577808) -->
- <skip />
+ <string name="label_phoneid" msgid="8775611434123577808">"SIM karta operator uchun bloklangan"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Qulfdan chiqarish"</string>
<string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Rad etish"</string>
<string name="requesting_unlock" msgid="930512210309437741">"Tarmoqni qulfdan chiqarish so‘ralmoqda…"</string>
@@ -136,7 +135,7 @@
<string name="call_settings_admin_user_only" msgid="7238947387649986286">"Faqat administrator qo‘ng‘iroq sozlamalarini o‘zgartirishi mumkin."</string>
<string name="call_settings_with_label" msgid="8460230435361579511">"Sozlamalar (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="error_updating_title" msgid="2024290892676808965">"Chaqiruv sozlamalarida xato"</string>
- <string name="reading_settings" msgid="1605904432450871183">"Sozlamalar o‘qilmoqda…"</string>
+ <string name="reading_settings" msgid="1605904432450871183">"Sozlamalar olinmoqda…"</string>
<string name="updating_settings" msgid="3650396734816028808">"Sozlamalar yangilanmoqda…"</string>
<string name="reverting_settings" msgid="7378668837291012205">"Sozlamalar tiklanmoqda…"</string>
<string name="response_error" msgid="3904481964024543330">"Tarmoqdan kutilmagan javob."</string>
@@ -149,7 +148,7 @@
<string name="radio_off_error" msgid="8321564164914232181">"Ushbu sozlamalarni ko‘rishdan oldin radioni yoqing."</string>
<string name="close_dialog" msgid="1074977476136119408">"OK"</string>
<string name="enable" msgid="2636552299455477603">"Yoqish"</string>
- <string name="disable" msgid="1122698860799462116">"O‘chirib qo‘yish"</string>
+ <string name="disable" msgid="1122698860799462116">"Faolsizlantirish"</string>
<string name="change_num" msgid="6982164494063109334">"Yangilash"</string>
<string-array name="clir_display_values">
<item msgid="8477364191403806960">"Standart tarmoq sozlamalari"</item>
@@ -876,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Mobil internet uchun birlamchi SIM kartaning qoʻshimcha identifikatori:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Axborot uzatish tezligi (kbit/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL kanalining axborot uzatish tezligi (kbit/s):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Tarmoq joylashuvi haqidagi axborot (eskirgan):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE jismoniy kanal konfiguratsiyasi:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Tarmoq haqidagi axborotning yangilanish darajasi:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Tarmoq statistikasi:"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index e12a4b4..a8a57ca 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -24,7 +24,7 @@
<string name="unknown" msgid="8279698889921830815">"Không xác định"</string>
<string name="private_num" msgid="4487990167889159992">"Số cá nhân"</string>
<string name="payphone" msgid="7936735771836716941">"Điện thoại công cộng"</string>
- <string name="onHold" msgid="6132725550015899006">"Đang chờ"</string>
+ <string name="onHold" msgid="6132725550015899006">"Đang giữ máy"</string>
<string name="carrier_mmi_msg_title" msgid="6050165242447507034">"Tin nhắn <xliff:g id="MMICARRIER">%s</xliff:g>"</string>
<string name="default_carrier_mmi_msg_title" msgid="7754317179938537213">"Tin nhắn nhà mạng"</string>
<string name="mmiStarted" msgid="9212975136944568623">"Đã bắt đầu mã MMI"</string>
@@ -86,13 +86,13 @@
<string name="voicemail_notifications_preference_title" msgid="7829238858063382977">"Thông báo"</string>
<string name="cell_broadcast_settings" msgid="8135324242541809924">"Phát sóng trong tình huống khẩn cấp"</string>
<string name="call_settings" msgid="3677282690157603818">"Cài đặt cuộc gọi"</string>
- <string name="additional_gsm_call_settings" msgid="1561980168685658846">"Cài đặt bổ sung"</string>
- <string name="additional_gsm_call_settings_with_label" msgid="7973920539979524908">"Cài đặt bổ sung (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
+ <string name="additional_gsm_call_settings" msgid="1561980168685658846">"Tùy chọn cài đặt bổ sung"</string>
+ <string name="additional_gsm_call_settings_with_label" msgid="7973920539979524908">"Tùy chọn cài đặt bổ sung (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="sum_gsm_call_settings" msgid="7964692601608878138">"Cài đặt cuộc gọi chỉ GSM bổ sung"</string>
<string name="additional_cdma_call_settings" msgid="2178016561980611304">"Cài đặt cuộc gọi CDMA bổ sung"</string>
<string name="sum_cdma_call_settings" msgid="3185825305136993636">"Cài đặt cuộc gọi chỉ CDMA bổ sung"</string>
<string name="labelNwService" msgid="6015891883487125120">"Cài đặt dịch vụ mạng"</string>
- <string name="labelCallerId" msgid="2090540744550903172">"ID người gọi"</string>
+ <string name="labelCallerId" msgid="2090540744550903172">"Số nhận dạng người gọi"</string>
<string name="sum_loading_settings" msgid="434063780286688775">"Đang tải cài đặt…"</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"Số bị ẩn trong cuộc gọi đi"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"Số được hiển thị trong cuộc gọi đi"</string>
@@ -135,8 +135,8 @@
<string name="call_settings_admin_user_only" msgid="7238947387649986286">"Chỉ người dùng quản trị mới có thể thay đổi cài đặt cuộc gọi."</string>
<string name="call_settings_with_label" msgid="8460230435361579511">"Cài đặt (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="error_updating_title" msgid="2024290892676808965">"Lỗi cài đặt cuộc gọi"</string>
- <string name="reading_settings" msgid="1605904432450871183">"Đang đọc cài đặt…"</string>
- <string name="updating_settings" msgid="3650396734816028808">"Đang cập nhật cài đặt..."</string>
+ <string name="reading_settings" msgid="1605904432450871183">"Đang đọc các tùy chọn cài đặt…"</string>
+ <string name="updating_settings" msgid="3650396734816028808">"Đang cập nhật các tùy chọn cài đặt..."</string>
<string name="reverting_settings" msgid="7378668837291012205">"Đang hoàn nguyên cài đặt…"</string>
<string name="response_error" msgid="3904481964024543330">"Phản hồi không mong muốn từ mạng."</string>
<string name="exception_error" msgid="330994460090467">"Lỗi mạng hoặc thẻ SIM."</string>
@@ -307,7 +307,7 @@
<string name="sim_change_data_title" msgid="9142726786345906606">"Thay đổi SIM cho dữ liệu di động?"</string>
<string name="sim_change_data_message" msgid="3567358694255933280">"Sử dụng <xliff:g id="NEW_SIM">%1$s</xliff:g> thay vì <xliff:g id="OLD_SIM">%2$s</xliff:g> cho dữ liệu di động?"</string>
<string name="wifi_calling_settings_title" msgid="5800018845662016507">"Gọi qua Wi-Fi"</string>
- <string name="video_calling_settings_title" msgid="342829454913266078">"Tính năng gọi điện video của nhà cung cấp dịch vụ"</string>
+ <string name="video_calling_settings_title" msgid="342829454913266078">"Tính năng gọi video của nhà cung cấp dịch vụ"</string>
<string name="gsm_umts_options" msgid="4968446771519376808">"Tùy chọn GSM/UMTS"</string>
<string name="cdma_options" msgid="3669592472226145665">"Tùy chọn CDMA"</string>
<string name="throttle_data_usage" msgid="1944145350660420711">"Sử dụng dữ liệu"</string>
@@ -455,7 +455,7 @@
<string name="auto_retry_mode_title" msgid="2985801935424422340">"Tự động thử lại"</string>
<string name="auto_retry_mode_summary" msgid="2863919925349511402">"Bật chế độ Tự động thử lại"</string>
<string name="tty_mode_not_allowed_video_call" msgid="6551976083652752815">"Không được phép thay đổi Chế độ Máy điện báo đánh chữ (TTY) trong cuộc gọi video"</string>
- <string name="menu_add" msgid="5616487894975773141">"Thêm liên hệ"</string>
+ <string name="menu_add" msgid="5616487894975773141">"Thêm người liên hệ"</string>
<string name="menu_edit" msgid="3593856941552460706">"Chỉnh sửa liên hệ"</string>
<string name="menu_delete" msgid="6326861853830546488">"Xóa liên hệ"</string>
<string name="menu_dial" msgid="4178537318419450012">"Quay số liên hệ"</string>
@@ -521,7 +521,7 @@
<string name="card_title_conf_call" msgid="901197309274457427">"Cuộc gọi hội nghị"</string>
<string name="card_title_incoming_call" msgid="881424648458792430">"Cuộc gọi đến"</string>
<string name="card_title_call_ended" msgid="650223980095026340">"Cuộc gọi đã kết thúc"</string>
- <string name="card_title_on_hold" msgid="9028319436626975207">"Đang chờ"</string>
+ <string name="card_title_on_hold" msgid="9028319436626975207">"Đang giữ máy"</string>
<string name="card_title_hanging_up" msgid="814874106866647871">"Kết thúc cuộc gọi"</string>
<string name="card_title_in_call" msgid="8231896539567594265">"Đang trong cuộc gọi"</string>
<string name="notification_voicemail_title" msgid="3932876181831601351">"Thư thoại mới"</string>
@@ -668,8 +668,8 @@
<string name="voicemail_change_pin_dialog_title" msgid="4633077715231764435">"Thay đổi mã PIN"</string>
<string name="preference_category_ringtone" msgid="8787281191375434976">"Nhạc chuông và rung"</string>
<string name="pstn_connection_service_label" msgid="9200102709997537069">"Thẻ SIM tích hợp sẵn"</string>
- <string name="enable_video_calling_title" msgid="7246600931634161830">"Bật gọi điện video"</string>
- <string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"Để bật tính năng gọi điện video, bạn cần bật chế độ 4G LTE tăng cường trong cài đặt mạng."</string>
+ <string name="enable_video_calling_title" msgid="7246600931634161830">"Bật gọi video"</string>
+ <string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"Để bật tính năng gọi video, bạn cần bật chế độ 4G LTE tăng cường trong cài đặt mạng."</string>
<string name="enable_video_calling_dialog_settings" msgid="8697890611305307110">"Cài đặt mạng"</string>
<string name="enable_video_calling_dialog_close" msgid="4298929725917045270">"Đóng"</string>
<string name="sim_label_emergency_calls" msgid="9078241989421522310">"Cuộc gọi khẩn cấp"</string>
@@ -812,7 +812,7 @@
<string name="supp_service_additional_call_forwarded" msgid="8772753260008398632">"Đã chuyển tiếp cuộc gọi bổ sung."</string>
<string name="supp_service_additional_ect_connected" msgid="8525934162945220237">"Hoàn tất chuyển cuộc gọi ở chế độ rõ."</string>
<string name="supp_service_additional_ect_connecting" msgid="7046240728781222753">"Đang chuyển cuộc gọi ở chế độ rõ."</string>
- <string name="supp_service_call_on_hold" msgid="2836811319594503059">"Cuộc gọi đang chờ."</string>
+ <string name="supp_service_call_on_hold" msgid="2836811319594503059">"Cuộc gọi đang giữ máy."</string>
<string name="supp_service_call_resumed" msgid="3786864005920743546">"Đã tiếp tục cuộc gọi."</string>
<string name="supp_service_deflected_call" msgid="7565979024562921707">"Cuộc gọi đã bị chuyển hướng."</string>
<string name="supp_service_forwarded_call" msgid="6475776013771821457">"Cuộc gọi đã được chuyển tiếp."</string>
@@ -831,7 +831,7 @@
<string name="radio_info_data_connection_enable" msgid="6183729739783252840">"Bật kết nối dữ liệu"</string>
<string name="radio_info_data_connection_disable" msgid="6404751291511368706">"Tắt kết nối dữ liệu"</string>
<string name="volte_provisioned_switch_string" msgid="4812874990480336178">"Đã cấp phép VoLTE"</string>
- <string name="vt_provisioned_switch_string" msgid="8295542122512195979">"Đã cấp phép gọi điện video"</string>
+ <string name="vt_provisioned_switch_string" msgid="8295542122512195979">"Đã cấp phép gọi video"</string>
<string name="wfc_provisioned_switch_string" msgid="3835004640321078988">"Đã cấp phép Gọi qua Wi-Fi"</string>
<string name="eab_provisioned_switch_string" msgid="4449676720736033035">"Đã cấp phép hiện diện/EAB"</string>
<string name="cbrs_data_switch_string" msgid="6060356430838077653">"Dữ liệu Cbrs"</string>
@@ -850,7 +850,7 @@
<string name="radio_info_ims_reg_status_not_registered" msgid="8045821447288876085">"Chưa đăng ký"</string>
<string name="radio_info_ims_feature_status_available" msgid="6493200914756969292">"Có sẵn"</string>
<string name="radio_info_ims_feature_status_unavailable" msgid="8930391136839759778">"Không có sẵn"</string>
- <string name="radio_info_ims_reg_status" msgid="25582845222446390">"Đăng ký IMS: <xliff:g id="STATUS">%1$s</xliff:g>\nThoại qua LTE: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nThoại qua Wi-Fi: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nGọi điện video: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nGiao diện UT: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
+ <string name="radio_info_ims_reg_status" msgid="25582845222446390">"Đăng ký IMS: <xliff:g id="STATUS">%1$s</xliff:g>\nThoại qua LTE: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nThoại qua Wi-Fi: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nGọi video: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nGiao diện UT: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
<string name="radioInfo_service_in" msgid="45753418231446400">"Đang sử dụng"</string>
<string name="radioInfo_service_out" msgid="287972405416142312">"Không có dịch vụ"</string>
<string name="radioInfo_service_emergency" msgid="4763879891415016848">"Chỉ cuộc gọi khẩn cấp"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Mã phụ của SIM dữ liệu mặc định:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Băng thông DL (kb/giây):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Băng thông UL (kb/giây):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Thông tin vị trí mạng di động (không dùng nữa):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Cấu hình kênh LTE thực:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Tốc độ làm mới thông tin mạng di động:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Toàn bộ thông tin về số đo mạng di động:"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index d9e8b78..a5562aa 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -171,7 +171,7 @@
<string name="vm_change_pin_error_mismatch" msgid="5364847280026257331">"旧的 PIN 码不匹配。"</string>
<string name="vm_change_pin_error_invalid" msgid="5230002671175580674">"新的 PIN 码包含无效字符。"</string>
<string name="vm_change_pin_error_system_error" msgid="9116483527909681791">"无法更改 PIN 码"</string>
- <string name="vvm_unsupported_message_format" msgid="4206402558577739713">"不受支持的语音邮件类型,请拨打 <xliff:g id="NUMBER">%s</xliff:g> 收听。"</string>
+ <string name="vvm_unsupported_message_format" msgid="4206402558577739713">"不受支持的语音信息类型,请拨打 <xliff:g id="NUMBER">%s</xliff:g> 收听。"</string>
<string name="network_settings_title" msgid="7560807107123171541">"移动网络"</string>
<string name="label_available" msgid="1316084116670821258">"可用网络"</string>
<string name="load_networks_progress" msgid="4051433047717401683">"正在搜索..."</string>
@@ -524,8 +524,8 @@
<string name="card_title_on_hold" msgid="9028319436626975207">"保持"</string>
<string name="card_title_hanging_up" msgid="814874106866647871">"正在挂断"</string>
<string name="card_title_in_call" msgid="8231896539567594265">"正在通话"</string>
- <string name="notification_voicemail_title" msgid="3932876181831601351">"新语音邮件"</string>
- <string name="notification_voicemail_title_count" msgid="2806950319222327082">"新语音邮件 (<xliff:g id="COUNT">%d</xliff:g>)"</string>
+ <string name="notification_voicemail_title" msgid="3932876181831601351">"新语音信息"</string>
+ <string name="notification_voicemail_title_count" msgid="2806950319222327082">"新语音信息 (<xliff:g id="COUNT">%d</xliff:g>)"</string>
<string name="notification_voicemail_text_format" msgid="5720947141702312537">"拨打 <xliff:g id="VOICEMAIL_NUMBER">%s</xliff:g>"</string>
<string name="notification_voicemail_no_vm_number" msgid="3423686009815186750">"语音信箱号码未知"</string>
<string name="notification_network_selection_title" msgid="255595526707809121">"无服务"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"默认数据 SIM 卡的 SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL 带宽 (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL 带宽 (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"移动网络位置信息(已弃用):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE 物理信道配置:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"移动网络信息刷新频率:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"所有移动网络测量信息:"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index b06a1d8..10888de 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"預設數據 SIM 卡的子 ID:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"下載頻寬 (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"上載頻寬 (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"發射站位置資料 (已淘汰):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE 實體渠道設定:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"發射站資料重新整理頻率:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"所有發射站量度資料:"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index f81f76d..b41e1c5 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -22,7 +22,7 @@
<string name="phoneIconLabel" msgid="3015941229249651419">"電話"</string>
<string name="fdnListLabel" msgid="4119121875004244097">"固定撥號清單"</string>
<string name="unknown" msgid="8279698889921830815">"不明"</string>
- <string name="private_num" msgid="4487990167889159992">"私人號碼"</string>
+ <string name="private_num" msgid="4487990167889159992">"隱藏號碼"</string>
<string name="payphone" msgid="7936735771836716941">"公用電話"</string>
<string name="onHold" msgid="6132725550015899006">"通話保留"</string>
<string name="carrier_mmi_msg_title" msgid="6050165242447507034">"「<xliff:g id="MMICARRIER">%s</xliff:g>」的訊息"</string>
@@ -97,7 +97,7 @@
<string name="sum_hide_caller_id" msgid="131100328602371933">"隱藏本機號碼"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"撥出電話時顯示本機號碼"</string>
<string name="sum_default_caller_id" msgid="1767070797135682959">"使用預設值,在撥出電話時顯示本機號碼"</string>
- <string name="labelCW" msgid="8449327023861428622">"來電等待"</string>
+ <string name="labelCW" msgid="8449327023861428622">"來電等候"</string>
<string name="sum_cw_enabled" msgid="3977308526187139996">"通話時如有來電請通知我"</string>
<string name="sum_cw_disabled" msgid="3658094589461768637">"通話時如有來電請通知我"</string>
<string name="call_forwarding_settings" msgid="8937130467468257671">"來電轉接設定"</string>
@@ -875,7 +875,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"預設資料 SIM 卡的子 ID:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"下行頻寬 (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"上行頻寬 (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"行動網路位置資訊 (已不適用):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE 實體通道設定:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"行動網路資訊重新整理頻率:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"所有行動網路測量資訊:"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index ba63614..eb0f2eb 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -877,7 +877,6 @@
<string name="radio_info_dds" msgid="1122593144425697126">"I-SubId ye-SIM yedatha yokuzenzakalela:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Umkhawulokudonsa we-DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Umkhawulokudonsa we-UL (kbps):"</string>
- <string name="radio_info_signal_location_label" msgid="6188435197086550049">"Ulwazi lwendawo lweseli (kwehlisiwe):"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Ukulungiselelwa okuphathekayo kwesiteshi se-LTE:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Isilinganiso sokuqalisa kabusha solwazi lweseli:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Ulwazi lwesilinganiso seseli:"</string>
diff --git a/sip/res/values-ar/strings.xml b/sip/res/values-ar/strings.xml
index f60f726..4cc9450 100644
--- a/sip/res/values-ar/strings.xml
+++ b/sip/res/values-ar/strings.xml
@@ -61,9 +61,9 @@
<string name="advanced_settings" msgid="2704644977548662872">"الإعدادات الاختيارية"</string>
<string name="auth_username_title" msgid="9002505242616662698">"اسم المستخدِم للمصادقة"</string>
<string name="auth_username_summary" msgid="6346313945275377230">"اسم المستخدِم المستخدَم للمصادقة"</string>
- <string name="default_preference_summary_username" msgid="8788114717555599222">"<لم يتم التعيين>"</string>
- <string name="default_preference_summary_password" msgid="3695366978153175549">"<لم يتم التعيين>"</string>
- <string name="default_preference_summary_domain_address" msgid="443247296785732364">"<لم يتم التعيين>"</string>
+ <string name="default_preference_summary_username" msgid="8788114717555599222">"<لم يتم الضبط>"</string>
+ <string name="default_preference_summary_password" msgid="3695366978153175549">"<لم يتم الضبط>"</string>
+ <string name="default_preference_summary_domain_address" msgid="443247296785732364">"<لم يتم الضبط>"</string>
<string name="display_name_summary" msgid="6749135030093260358">"<مثل اسم المستخدم>"</string>
<string name="optional_summary" msgid="620379377865437488">"<اختياري>"</string>
<string name="advanced_settings_show" msgid="2318728080037568529">"▷ المس لإظهار الكل"</string>
diff --git a/sip/res/values-b+sr+Latn/strings.xml b/sip/res/values-b+sr+Latn/strings.xml
index dadfa20..adb537b 100644
--- a/sip/res/values-b+sr+Latn/strings.xml
+++ b/sip/res/values-b+sr+Latn/strings.xml
@@ -22,7 +22,7 @@
<string name="sip_receive_calls" msgid="3403644006618369349">"Primaj dolazne pozive"</string>
<string name="sip_receive_calls_summary" msgid="5306603671778761443">"Više troši bateriju"</string>
<string name="sip_call_options_title" msgid="5027066677561068192">"Koristite SIP pozivanje"</string>
- <string name="sip_call_options_wifi_only_title" msgid="6663105297927456484">"Koristite SIP pozivanje (samo za Wi-Fi)"</string>
+ <string name="sip_call_options_wifi_only_title" msgid="6663105297927456484">"Koristite SIP pozivanje (samo za WiFi)"</string>
<string name="sip_call_options_entry_1" msgid="4722647332760934261">"Za sve pozive kada je mreža za prenos podataka dostupna"</string>
<string name="sip_call_options_entry_2" msgid="7338504256051655013">"Samo za SIP pozive"</string>
<string name="sip_call_options_wifi_only_entry_1" msgid="922329055414010991">"Za sve pozive"</string>
@@ -41,7 +41,7 @@
<string name="registration_status_still_trying" msgid="7178623685868766282">"I dalje pokušava..."</string>
<string name="registration_status_not_receiving" msgid="3873074208531938401">"Ne primamo pozive."</string>
<string name="registration_status_no_data" msgid="2987064560116584121">"Registracija naloga je zaustavljena zato što ne postoji internet veza."</string>
- <string name="registration_status_no_wifi_data" msgid="685470618241482948">"Registracija naloga je zaustavljena zato što ne postoji Wi-Fi veza."</string>
+ <string name="registration_status_no_wifi_data" msgid="685470618241482948">"Registracija naloga je zaustavljena zato što ne postoji WiFi veza."</string>
<string name="registration_status_not_running" msgid="6236403137652262659">"Registracija naloga nije uspela."</string>
<string name="registration_status_done" msgid="6787397199273357721">"Primamo pozive."</string>
<string name="registration_status_failed_try_later" msgid="7855389184910312091">"Registracija naloga nije uspela: <xliff:g id="REGISTRATION_ERROR_MESSAGE">%s</xliff:g>; pokušaćemo kasnije"</string>
@@ -72,7 +72,7 @@
<string name="empty_alert" msgid="3693655518612836718">"Polje <xliff:g id="INPUT_FIELD_NAME">%s</xliff:g> je obavezno i ne može da bude prazno."</string>
<string name="not_a_valid_port" msgid="3664668836663491376">"Broj porta bi trebalo da bude između 1000 i 65.534."</string>
<string name="no_internet_available" msgid="161720645084325479">"Da biste uputili SIP poziv, prvo proverite internet vezu."</string>
- <string name="no_wifi_available" msgid="1179092018692306312">"Treba da budete povezani sa Wi-Fi mrežom da biste upućivali SIP pozive (koristite Podešavanja bežičnih veza i mreža)."</string>
+ <string name="no_wifi_available" msgid="1179092018692306312">"Treba da budete povezani sa WiFi mrežom da biste upućivali SIP pozive (koristite Podešavanja bežičnih veza i mreža)."</string>
<string name="no_voip" msgid="3366395789297981738">"SIP pozivanje nije podržano"</string>
<string name="sip_system_decide" msgid="197230378376326430">"Automatski"</string>
<string name="sip_always_send_keepalive" msgid="4986533673960084769">"Uvek šalji"</string>
diff --git a/sip/res/values-eu/strings.xml b/sip/res/values-eu/strings.xml
index 0925002..5ad7d9c 100644
--- a/sip/res/values-eu/strings.xml
+++ b/sip/res/values-eu/strings.xml
@@ -41,7 +41,7 @@
<string name="registration_status_still_trying" msgid="7178623685868766282">"Oraindik saiatzen…"</string>
<string name="registration_status_not_receiving" msgid="3873074208531938401">"Ez da deirik jasotzen ari."</string>
<string name="registration_status_no_data" msgid="2987064560116584121">"Kontua erregistratzeko prozesua gelditu da ez zaudelako konektatuta Internetera."</string>
- <string name="registration_status_no_wifi_data" msgid="685470618241482948">"Kontua erregistratzeko prozesua gelditu da ez dagoelako wifi bidezko konexiorik."</string>
+ <string name="registration_status_no_wifi_data" msgid="685470618241482948">"Kontua erregistratzeko prozesua gelditu da ez dagoelako wifi-konexiorik."</string>
<string name="registration_status_not_running" msgid="6236403137652262659">"Ez da kontua erregistratu."</string>
<string name="registration_status_done" msgid="6787397199273357721">"Deiak jasotzen."</string>
<string name="registration_status_failed_try_later" msgid="7855389184910312091">"Ez da kontua erregistratu: (<xliff:g id="REGISTRATION_ERROR_MESSAGE">%s</xliff:g>). Geroago saiatuko gara berriro."</string>
diff --git a/sip/res/values-fa/strings.xml b/sip/res/values-fa/strings.xml
index 6a0f0bf..e2843bc 100644
--- a/sip/res/values-fa/strings.xml
+++ b/sip/res/values-fa/strings.xml
@@ -59,8 +59,8 @@
<string name="transport_title" msgid="1661659138226029178">"نوع حملونقل"</string>
<string name="send_keepalive_title" msgid="5319788151608946049">"ارسال حفظ اتصال"</string>
<string name="advanced_settings" msgid="2704644977548662872">"تنظیمات اختیاری"</string>
- <string name="auth_username_title" msgid="9002505242616662698">"نام کاربری برای احراز هویت"</string>
- <string name="auth_username_summary" msgid="6346313945275377230">"نام کاربری مورد استفاده برای احراز هویت"</string>
+ <string name="auth_username_title" msgid="9002505242616662698">"نام کاربری برای اصالتسنجی"</string>
+ <string name="auth_username_summary" msgid="6346313945275377230">"نام کاربری مورد استفاده برای اصالتسنجی"</string>
<string name="default_preference_summary_username" msgid="8788114717555599222">"<تنظیم نشده>"</string>
<string name="default_preference_summary_password" msgid="3695366978153175549">"<تنظیم نشده>"</string>
<string name="default_preference_summary_domain_address" msgid="443247296785732364">"<تنظیم نشده>"</string>
diff --git a/sip/res/values-mr/strings.xml b/sip/res/values-mr/strings.xml
index 252b3bf..60d9c88 100644
--- a/sip/res/values-mr/strings.xml
+++ b/sip/res/values-mr/strings.xml
@@ -45,13 +45,13 @@
<string name="registration_status_not_running" msgid="6236403137652262659">"खाते नोंदणी अयशस्वी."</string>
<string name="registration_status_done" msgid="6787397199273357721">"कॉल प्राप्त करत आहे."</string>
<string name="registration_status_failed_try_later" msgid="7855389184910312091">"खाते नोंदणी अयशस्वी: (<xliff:g id="REGISTRATION_ERROR_MESSAGE">%s</xliff:g>); नंतर प्रयत्न करू"</string>
- <string name="registration_status_invalid_credentials" msgid="8896714049938660777">"खाते नोंदणी अयशस्वी: चुकीचे वापरकर्तानाव किंवा संकेतशब्द."</string>
+ <string name="registration_status_invalid_credentials" msgid="8896714049938660777">"खाते नोंदणी अयशस्वी: चुकीचे वापरकर्ता नाव किंवा संकेतशब्द."</string>
<string name="registration_status_server_unreachable" msgid="3832339558868965604">"खाते नोंदणी अयशस्वी: सर्व्हर नाव तपासा."</string>
<string name="third_party_account_summary" msgid="5918779106950859167">"हे खाते सध्या <xliff:g id="ACCOUNT_OWNER">%s</xliff:g> अॅपद्वारे वापरात आहे."</string>
<string name="sip_edit_title" msgid="7438891546610820307">"SIP खाते तपशील"</string>
<string name="sip_edit_new_title" msgid="8394790068979636381">"SIP खाते तपशील"</string>
<string name="domain_address_title" msgid="8238078615181248579">"सर्व्हर"</string>
- <string name="username_title" msgid="298416796886107970">"वापरकर्तानाव"</string>
+ <string name="username_title" msgid="298416796886107970">"वापरकर्ता नाव"</string>
<string name="password_title" msgid="8035579335591959021">"पासवर्ड"</string>
<string name="display_name_title" msgid="3730105783656830160">"प्रदर्शन नाव"</string>
<string name="proxy_address_title" msgid="4120361943254795287">"आउटबाउंड प्रॉक्सी पत्ता"</string>
@@ -60,7 +60,7 @@
<string name="send_keepalive_title" msgid="5319788151608946049">"चैतन्यमय-ठेवा पाठवा"</string>
<string name="advanced_settings" msgid="2704644977548662872">"पर्यायी सेटिंग्ज"</string>
<string name="auth_username_title" msgid="9002505242616662698">"ऑथेंटिकेशन वापरकर्ता नाव"</string>
- <string name="auth_username_summary" msgid="6346313945275377230">"प्रमाणीकरणासाठी वापरकर्तानाव वापरले"</string>
+ <string name="auth_username_summary" msgid="6346313945275377230">"प्रमाणीकरणासाठी वापरकर्ता नाव वापरले"</string>
<string name="default_preference_summary_username" msgid="8788114717555599222">"<सेट नाही>"</string>
<string name="default_preference_summary_password" msgid="3695366978153175549">"<सेट नाही>"</string>
<string name="default_preference_summary_domain_address" msgid="443247296785732364">"<सेट नाही>"</string>
diff --git a/sip/res/values-pt-rPT/strings.xml b/sip/res/values-pt-rPT/strings.xml
index ae1b2ed..35aca3e 100644
--- a/sip/res/values-pt-rPT/strings.xml
+++ b/sip/res/values-pt-rPT/strings.xml
@@ -47,7 +47,7 @@
<string name="registration_status_failed_try_later" msgid="7855389184910312091">"O registo da conta não teve êxito: (<xliff:g id="REGISTRATION_ERROR_MESSAGE">%s</xliff:g>); tentaremos mais tarde"</string>
<string name="registration_status_invalid_credentials" msgid="8896714049938660777">"O registo da conta não teve êxito: palavra-passe ou nome de utilizador incorreto"</string>
<string name="registration_status_server_unreachable" msgid="3832339558868965604">"O registo da conta não teve êxito: verifique o nome do servidor."</string>
- <string name="third_party_account_summary" msgid="5918779106950859167">"Esta conta está atualmente a ser utilizada pela aplicação <xliff:g id="ACCOUNT_OWNER">%s</xliff:g>."</string>
+ <string name="third_party_account_summary" msgid="5918779106950859167">"Esta conta está atualmente a ser utilizada pela app <xliff:g id="ACCOUNT_OWNER">%s</xliff:g>."</string>
<string name="sip_edit_title" msgid="7438891546610820307">"Detalhes da conta SIP"</string>
<string name="sip_edit_new_title" msgid="8394790068979636381">"Detalhes da conta SIP"</string>
<string name="domain_address_title" msgid="8238078615181248579">"Servidor"</string>
diff --git a/sip/res/values-sq/strings.xml b/sip/res/values-sq/strings.xml
index 1b83380..5c50085 100644
--- a/sip/res/values-sq/strings.xml
+++ b/sip/res/values-sq/strings.xml
@@ -32,7 +32,7 @@
<string name="saving_account" msgid="3390358043846687266">"Po ruan llogarinë…"</string>
<string name="removing_account" msgid="1544132880414780408">"Po heq llogarinë…"</string>
<string name="sip_menu_save" msgid="4377112554203123060">"Ruaj"</string>
- <string name="sip_menu_discard" msgid="1883166691772895243">"Injoro"</string>
+ <string name="sip_menu_discard" msgid="1883166691772895243">"Hiq"</string>
<string name="alert_dialog_close" msgid="1734746505531110706">"Mbyll profilin"</string>
<string name="alert_dialog_ok" msgid="7806760618798687406">"Në rregull"</string>
<string name="close_profile" msgid="3756064641769751774">"Mbyll"</string>
diff --git a/sip/res/values-sr/strings.xml b/sip/res/values-sr/strings.xml
index f877e1b..4c15528 100644
--- a/sip/res/values-sr/strings.xml
+++ b/sip/res/values-sr/strings.xml
@@ -22,7 +22,7 @@
<string name="sip_receive_calls" msgid="3403644006618369349">"Примај долазне позиве"</string>
<string name="sip_receive_calls_summary" msgid="5306603671778761443">"Више троши батерију"</string>
<string name="sip_call_options_title" msgid="5027066677561068192">"Користите SIP позивање"</string>
- <string name="sip_call_options_wifi_only_title" msgid="6663105297927456484">"Користите SIP позивање (само за Wi-Fi)"</string>
+ <string name="sip_call_options_wifi_only_title" msgid="6663105297927456484">"Користите SIP позивање (само за WiFi)"</string>
<string name="sip_call_options_entry_1" msgid="4722647332760934261">"За све позиве када је мрежа за пренос података доступна"</string>
<string name="sip_call_options_entry_2" msgid="7338504256051655013">"Само за SIP позиве"</string>
<string name="sip_call_options_wifi_only_entry_1" msgid="922329055414010991">"За све позиве"</string>
@@ -41,7 +41,7 @@
<string name="registration_status_still_trying" msgid="7178623685868766282">"И даље покушава..."</string>
<string name="registration_status_not_receiving" msgid="3873074208531938401">"Не примамо позиве."</string>
<string name="registration_status_no_data" msgid="2987064560116584121">"Регистрација налога је заустављена зато што не постоји интернет веза."</string>
- <string name="registration_status_no_wifi_data" msgid="685470618241482948">"Регистрација налога је заустављена зато што не постоји Wi-Fi веза."</string>
+ <string name="registration_status_no_wifi_data" msgid="685470618241482948">"Регистрација налога је заустављена зато што не постоји WiFi веза."</string>
<string name="registration_status_not_running" msgid="6236403137652262659">"Регистрација налога није успела."</string>
<string name="registration_status_done" msgid="6787397199273357721">"Примамо позиве."</string>
<string name="registration_status_failed_try_later" msgid="7855389184910312091">"Регистрација налога није успела: <xliff:g id="REGISTRATION_ERROR_MESSAGE">%s</xliff:g>; покушаћемо касније"</string>
@@ -72,7 +72,7 @@
<string name="empty_alert" msgid="3693655518612836718">"Поље <xliff:g id="INPUT_FIELD_NAME">%s</xliff:g> је обавезно и не може да буде празно."</string>
<string name="not_a_valid_port" msgid="3664668836663491376">"Број порта би требало да буде између 1000 и 65.534."</string>
<string name="no_internet_available" msgid="161720645084325479">"Да бисте упутили SIP позив, прво проверите интернет везу."</string>
- <string name="no_wifi_available" msgid="1179092018692306312">"Треба да будете повезани са Wi-Fi мрежом да бисте упућивали SIP позиве (користите Подешавања бежичних веза и мрежа)."</string>
+ <string name="no_wifi_available" msgid="1179092018692306312">"Треба да будете повезани са WiFi мрежом да бисте упућивали SIP позиве (користите Подешавања бежичних веза и мрежа)."</string>
<string name="no_voip" msgid="3366395789297981738">"SIP позивање није подржано"</string>
<string name="sip_system_decide" msgid="197230378376326430">"Аутоматски"</string>
<string name="sip_always_send_keepalive" msgid="4986533673960084769">"Увек шаљи"</string>
diff --git a/src/com/android/phone/CallForwardEditPreference.java b/src/com/android/phone/CallForwardEditPreference.java
index 8e0b685..bf296f9 100644
--- a/src/com/android/phone/CallForwardEditPreference.java
+++ b/src/com/android/phone/CallForwardEditPreference.java
@@ -384,7 +384,9 @@
CallForwardInfo cfInfoArray[] = (CallForwardInfo[]) ar.result;
if (cfInfoArray == null || cfInfoArray.length == 0) {
Log.d(LOG_TAG, "handleGetCFResponse: cfInfoArray.length==0");
- mTcpListener.onError(CallForwardEditPreference.this, RESPONSE_ERROR);
+ if (!(ar.userObj instanceof Throwable)) {
+ mTcpListener.onError(CallForwardEditPreference.this, RESPONSE_ERROR);
+ }
} else {
for (int i = 0, length = cfInfoArray.length; i < length; i++) {
Log.d(LOG_TAG, "handleGetCFResponse, cfInfoArray[" + i + "]="
diff --git a/src/com/android/phone/ImsRcsController.java b/src/com/android/phone/ImsRcsController.java
index f5f24d3..52069b8 100644
--- a/src/com/android/phone/ImsRcsController.java
+++ b/src/com/android/phone/ImsRcsController.java
@@ -16,31 +16,42 @@
package com.android.phone;
+import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
+import android.os.UserHandle;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
+import android.telephony.ims.DelegateRequest;
import android.telephony.ims.ImsException;
+import android.telephony.ims.RcsUceAdapter.PublishState;
import android.telephony.ims.RegistrationManager;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsRcsController;
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.aidl.IRcsUceControllerCallback;
import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.RcsFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.Log;
import com.android.ims.ImsManager;
+import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyPermissions;
+import com.android.internal.telephony.ims.ImsResolver;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.services.telephony.rcs.RcsFeatureController;
+import com.android.services.telephony.rcs.SipTransportController;
import com.android.services.telephony.rcs.TelephonyRcsService;
-import com.android.services.telephony.rcs.UserCapabilityExchangeImpl;
+import com.android.services.telephony.rcs.UceControllerManager;
import java.util.List;
@@ -55,6 +66,7 @@
private PhoneGlobals mApp;
private TelephonyRcsService mRcsService;
+ private ImsResolver mImsResolver;
/**
* Initialize the singleton ImsRcsController instance.
@@ -77,6 +89,7 @@
mApp = app;
TelephonyFrameworkInitializer
.getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
+ mImsResolver = mApp.getImsResolver();
}
/**
@@ -197,40 +210,6 @@
}
}
- @Override
- public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
- enforceReadPrivilegedPermission("registerUcePublishStateCallback");
- final long token = Binder.clearCallingIdentity();
- try {
- UserCapabilityExchangeImpl uce = getRcsFeatureController(subId).getFeature(
- UserCapabilityExchangeImpl.class);
- if (uce == null) {
- throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
- "This subscription does not support UCE.");
- }
- uce.registerPublishStateCallback(c);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
- enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
- final long token = Binder.clearCallingIdentity();
- try {
- UserCapabilityExchangeImpl uce = getRcsFeatureController(subId).getFeature(
- UserCapabilityExchangeImpl.class);
- if (uce == null) {
- throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
- "This subscription does not support UCE.");
- }
- uce.unregisterUcePublishStateCallback(c);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
/**
* Query for the capability of an IMS RCS service
*
@@ -290,30 +269,94 @@
}
final long token = Binder.clearCallingIdentity();
try {
- UserCapabilityExchangeImpl uce = getRcsFeatureController(subId).getFeature(
- UserCapabilityExchangeImpl.class);
- if (uce == null) {
+ UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
+ UceControllerManager.class);
+ if (uceCtrlManager == null) {
throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
"This subscription does not support UCE.");
}
- uce.requestCapabilities(contactNumbers, c);
+ uceCtrlManager.requestCapabilities(contactNumbers, c);
+ } catch (ImsException e) {
+ throw new ServiceSpecificException(e.getCode(), e.getMessage());
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
- public int getUcePublishState(int subId) {
- enforceReadPrivilegedPermission("getUcePublishState");
+ public void requestNetworkAvailability(int subId, String callingPackage,
+ String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c) {
+ enforceReadPrivilegedPermission("requestNetworkAvailability");
+ if (!isUceSettingEnabled(subId, callingPackage, callingFeatureId)) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "The user has not enabled UCE for this subscription.");
+ }
final long token = Binder.clearCallingIdentity();
try {
- UserCapabilityExchangeImpl uce = getRcsFeatureController(subId).getFeature(
- UserCapabilityExchangeImpl.class);
- if (uce == null) {
+ UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
+ UceControllerManager.class);
+ if (uceCtrlManager == null) {
throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
"This subscription does not support UCE.");
}
- return uce.getUcePublishState();
+ uceCtrlManager.requestNetworkAvailability(contactNumber, c);
+ } catch (ImsException e) {
+ throw new ServiceSpecificException(e.getCode(), e.getMessage());
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public @PublishState int getUcePublishState(int subId) {
+ enforceReadPrivilegedPermission("getUcePublishState");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
+ UceControllerManager.class);
+ if (uceCtrlManager == null) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "This subscription does not support UCE.");
+ }
+ return uceCtrlManager.getUcePublishState();
+ } catch (ImsException e) {
+ throw new ServiceSpecificException(e.getCode(), e.getMessage());
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
+ enforceReadPrivilegedPermission("registerUcePublishStateCallback");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
+ UceControllerManager.class);
+ if (uceCtrlManager == null) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "This subscription does not support UCE.");
+ }
+ uceCtrlManager.registerPublishStateCallback(c);
+ } catch (ImsException e) {
+ throw new ServiceSpecificException(e.getCode(), e.getMessage());
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
+ enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
+ UceControllerManager.class);
+ if (uceCtrlManager == null) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "This subscription does not support UCE.");
+ }
+ uceCtrlManager.unregisterPublishStateCallback(c);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -348,6 +391,117 @@
}
}
+ @Override
+ public boolean isSipDelegateSupported(int subId) {
+ enforceReadPrivilegedPermission("isSipDelegateSupported");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ SipTransportController transport = getRcsFeatureController(subId).getFeature(
+ SipTransportController.class);
+ if (transport == null) {
+ return false;
+ }
+ return transport.isSupported(subId);
+ } catch (ImsException e) {
+ throw new ServiceSpecificException(e.getCode(), e.getMessage());
+ } catch (ServiceSpecificException e) {
+ if (e.errorCode == ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
+ return false;
+ }
+ throw e;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void createSipDelegate(int subId, DelegateRequest request, String packageName,
+ ISipDelegateConnectionStateCallback delegateState,
+ ISipDelegateMessageCallback delegateMessage) {
+ enforceModifyPermission();
+ if (!UserHandle.getUserHandleForUid(Binder.getCallingUid()).isSystem()) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "SipDelegate creation is only available to primary user.");
+ }
+ try {
+ int remoteUid = mApp.getPackageManager().getPackageUid(packageName, 0 /*flags*/);
+ if (Binder.getCallingUid() != remoteUid) {
+ throw new SecurityException("passed in packageName does not match the caller");
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new SecurityException("Passed in PackageName can not be found on device");
+ }
+
+ final long identity = Binder.clearCallingIdentity();
+ SipTransportController transport = getRcsFeatureController(subId).getFeature(
+ SipTransportController.class);
+ if (transport == null) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "This subscription does not support the creation of SIP delegates");
+ }
+ try {
+ transport.createSipDelegate(subId, request, packageName, delegateState,
+ delegateMessage);
+ } catch (ImsException e) {
+ throw new ServiceSpecificException(e.getCode(), e.getMessage());
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
+ enforceModifyPermission();
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ SipTransportController transport = getRcsFeatureController(subId).getFeature(
+ SipTransportController.class);
+ if (transport == null) {
+ return;
+ }
+ transport.destroySipDelegate(subId, connection, reason);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
+ * callback.
+ */
+ @Override
+ public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
+ enforceModifyPermission();
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ if (mImsResolver == null) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "Device does not support IMS");
+ }
+ mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
+ */
+ @Override
+ public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
+ enforceModifyPermission();
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ if (mImsResolver == null) return;
+ mImsResolver.unregisterImsFeatureCallback(callback);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
/**
* Make sure either called from same process as self (phone) or IPC caller has read privilege.
*
diff --git a/src/com/android/phone/ImsUtil.java b/src/com/android/phone/ImsUtil.java
index 38936ec..0825cfb 100644
--- a/src/com/android/phone/ImsUtil.java
+++ b/src/com/android/phone/ImsUtil.java
@@ -25,6 +25,8 @@
import com.android.ims.ImsConfig;
import com.android.ims.ImsManager;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.imsphone.ImsPhone;
public class ImsUtil {
private static final String LOG_TAG = ImsUtil.class.getSimpleName();
@@ -128,6 +130,13 @@
return false;
}
+ // Do not promote WFC if in roaming and WFC roaming not allowed.
+ // WFC roaming setting is not modifiable, so its value is decided by the default value
+ // chosen by the carrier, hence it really means if the carrier supports WFC roaming.
+ if (getLastKnownRoamingState(phoneId) && !imsManager.isWfcRoamingEnabledByUser()) {
+ return false;
+ }
+
ConnectivityManager cm =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm != null) {
@@ -152,4 +161,13 @@
}
return subId;
}
+
+ private static boolean getLastKnownRoamingState(int phoneId) {
+ try {
+ ImsPhone imsPhone = (ImsPhone) (PhoneFactory.getPhone(phoneId).getImsPhone());
+ return imsPhone.getRoamingState();
+ } catch (NullPointerException | ClassCastException e) {
+ return false;
+ }
+ }
}
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index c2dece5..fe4a0ba 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -536,7 +536,11 @@
int slotId = SubscriptionManager.getSlotIndex(subId);
resId = (slotId == 0) ? R.drawable.stat_sys_phone_call_forward_sub1
: R.drawable.stat_sys_phone_call_forward_sub2;
- notificationTitle = subInfo.getDisplayName().toString();
+ if (subInfo.getDisplayName() != null) {
+ notificationTitle = subInfo.getDisplayName().toString();
+ } else {
+ notificationTitle = mContext.getString(R.string.labelCF);
+ }
} else {
notificationTitle = mContext.getString(R.string.labelCF);
}
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index bd2b2ed..509aa57 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -55,6 +55,7 @@
import android.util.Log;
import android.widget.Toast;
+import com.android.ims.ImsFeatureBinderRepository;
import com.android.internal.telephony.CallManager;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.MmiCode;
@@ -356,7 +357,8 @@
String defaultImsRcsPackage = getResources().getString(
R.string.config_ims_rcs_package);
mImsResolver = new ImsResolver(this, defaultImsMmtelPackage,
- defaultImsRcsPackage, PhoneFactory.getPhones().length);
+ defaultImsRcsPackage, PhoneFactory.getPhones().length,
+ new ImsFeatureBinderRepository());
mImsResolver.initialize();
}
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index c22a8a4..2834845 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -64,7 +64,9 @@
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.Annotation.ApnType;
+import android.telephony.Annotation.ThermalMitigationResult;
import android.telephony.CallForwardingInfo;
+import android.telephony.CarrierBandwidth;
import android.telephony.CarrierConfigManager;
import android.telephony.CarrierRestrictionRules;
import android.telephony.CellIdentity;
@@ -74,6 +76,7 @@
import android.telephony.CellInfoGsm;
import android.telephony.CellInfoWcdma;
import android.telephony.ClientRequestStats;
+import android.telephony.DataThrottlingRequest;
import android.telephony.ICellInfoCallback;
import android.telephony.IccOpenLogicalChannelResponse;
import android.telephony.LocationAccessPolicy;
@@ -92,6 +95,7 @@
import android.telephony.TelephonyHistogram;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyScanManager;
+import android.telephony.ThermalMitigationRequest;
import android.telephony.UiccCardInfo;
import android.telephony.UiccSlotInfo;
import android.telephony.UssdResponse;
@@ -104,8 +108,6 @@
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsConfigCallback;
-import android.telephony.ims.aidl.IImsMmTelFeature;
-import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.feature.ImsFeature;
@@ -132,6 +134,7 @@
import com.android.internal.telephony.DefaultPhoneNotifier;
import com.android.internal.telephony.HalVersion;
import com.android.internal.telephony.IBooleanConsumer;
+import com.android.internal.telephony.ICallForwardingInfoCallback;
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.INumberVerificationCallback;
import com.android.internal.telephony.ITelephony;
@@ -172,12 +175,15 @@
import com.android.internal.telephony.uicc.UiccSlot;
import com.android.internal.telephony.util.LocaleUtils;
import com.android.internal.telephony.util.VoicemailNotificationSettingsUtil;
+import com.android.internal.util.FunctionalUtils;
import com.android.internal.util.HexDump;
import com.android.phone.settings.PickSmsSubscriptionActivity;
import com.android.phone.vvm.PhoneAccountHandleConverter;
import com.android.phone.vvm.RemoteVvmTaskManager;
import com.android.phone.vvm.VisualVoicemailSettingsUtil;
import com.android.phone.vvm.VisualVoicemailSmsFilterConfig;
+import com.android.services.telephony.TelecomAccountRegistry;
+import com.android.services.telephony.TelephonyConnectionService;
import com.android.telephony.Rlog;
import java.io.FileDescriptor;
@@ -289,6 +295,16 @@
private static final int EVENT_GET_CALL_WAITING_DONE = 88;
private static final int CMD_SET_CALL_WAITING = 89;
private static final int EVENT_SET_CALL_WAITING_DONE = 90;
+ private static final int CMD_ENABLE_NR_DUAL_CONNECTIVITY = 91;
+ private static final int EVENT_ENABLE_NR_DUAL_CONNECTIVITY_DONE = 92;
+ private static final int CMD_IS_NR_DUAL_CONNECTIVITY_ENABLED = 93;
+ private static final int EVENT_IS_NR_DUAL_CONNECTIVITY_ENABLED_DONE = 94;
+ private static final int CMD_GET_CDMA_SUBSCRIPTION_MODE = 95;
+ private static final int EVENT_GET_CDMA_SUBSCRIPTION_MODE_DONE = 96;
+ private static final int CMD_GET_SYSTEM_SELECTION_CHANNELS = 97;
+ private static final int EVENT_GET_SYSTEM_SELECTION_CHANNELS_DONE = 98;
+ private static final int CMD_SET_DATA_THROTTLING = 99;
+ private static final int EVENT_SET_DATA_THROTTLING_DONE = 100;
// Parameters of select command.
private static final int SELECT_COMMAND = 0xA4;
@@ -313,6 +329,8 @@
private AtomicBoolean mNotifyUserActivity;
private static final int USER_ACTIVITY_NOTIFICATION_DELAY = 200;
+ private Set<Integer> mCarrierPrivilegeTestOverrideSubIds = new ArraySet<>();
+
private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
private static final String PREF_CARRIERS_SUBSCRIBER_PREFIX = "carrier_subscriber_";
@@ -329,6 +347,8 @@
private static final int TYPE_ALLOCATION_CODE_LENGTH = 8;
private static final int MANUFACTURER_CODE_LENGTH = 8;
+ private static final int SET_DATA_THROTTLING_MODEM_THREW_INVALID_PARAMS = -1;
+
/**
* Experiment flag to enable erase modem config on reset network, default value is false
*/
@@ -749,6 +769,90 @@
handleNullReturnEvent(msg, "resetModemConfig");
break;
+ case CMD_IS_NR_DUAL_CONNECTIVITY_ENABLED: {
+ request = (MainThreadRequest) msg.obj;
+ onCompleted = obtainMessage(EVENT_IS_NR_DUAL_CONNECTIVITY_ENABLED_DONE,
+ request);
+ Phone phone = getPhoneFromRequest(request);
+ if (phone != null) {
+ phone.isNrDualConnectivityEnabled(onCompleted, request.workSource);
+ } else {
+ loge("isNRDualConnectivityEnabled: No phone object");
+ request.result = false;
+ notifyRequester(request);
+ }
+ break;
+ }
+
+ case EVENT_IS_NR_DUAL_CONNECTIVITY_ENABLED_DONE:
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+ if (ar.exception == null && ar.result != null) {
+ request.result = ar.result;
+ } else {
+ // request.result must be set to something non-null
+ // for the calling thread to unblock
+ if (request.result != null) {
+ request.result = ar.result;
+ } else {
+ request.result = false;
+ }
+ if (ar.result == null) {
+ loge("isNRDualConnectivityEnabled: Empty response");
+ } else if (ar.exception instanceof CommandException) {
+ loge("isNRDualConnectivityEnabled: CommandException: "
+ + ar.exception);
+ } else {
+ loge("isNRDualConnectivityEnabled: Unknown exception");
+ }
+ }
+ notifyRequester(request);
+ break;
+
+ case CMD_ENABLE_NR_DUAL_CONNECTIVITY: {
+ request = (MainThreadRequest) msg.obj;
+ onCompleted = obtainMessage(EVENT_ENABLE_NR_DUAL_CONNECTIVITY_DONE, request);
+ Phone phone = getPhoneFromRequest(request);
+ if (phone != null) {
+ phone.setNrDualConnectivityState((int) request.argument, onCompleted,
+ request.workSource);
+ } else {
+ loge("enableNrDualConnectivity: No phone object");
+ request.result =
+ TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_RADIO_NOT_AVAILABLE;
+ notifyRequester(request);
+ }
+ break;
+ }
+
+ case EVENT_ENABLE_NR_DUAL_CONNECTIVITY_DONE: {
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+ if (ar.exception == null) {
+ request.result =
+ TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_SUCCESS;
+ } else {
+ request.result =
+ TelephonyManager
+ .ENABLE_NR_DUAL_CONNECTIVITY_RADIO_ERROR;
+ if (ar.exception instanceof CommandException) {
+ CommandException.Error error =
+ ((CommandException) (ar.exception)).getCommandError();
+ if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
+ request.result =
+ TelephonyManager
+ .ENABLE_NR_DUAL_CONNECTIVITY_RADIO_NOT_AVAILABLE;
+ }
+ loge("enableNrDualConnectivity" + ": CommandException: "
+ + ar.exception);
+ } else {
+ loge("enableNrDualConnectivity" + ": Unknown exception");
+ }
+ }
+ notifyRequester(request);
+ break;
+ }
+
case CMD_GET_PREFERRED_NETWORK_TYPE:
request = (MainThreadRequest) msg.obj;
onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
@@ -829,38 +933,43 @@
getPhoneFromRequest(request).getAvailableNetworks(onCompleted);
break;
- case CMD_GET_CALL_FORWARDING:
+ case CMD_GET_CALL_FORWARDING: {
request = (MainThreadRequest) msg.obj;
onCompleted = obtainMessage(EVENT_GET_CALL_FORWARDING_DONE, request);
- int callForwardingReason = (Integer) request.argument;
- getPhoneFromRequest(request).getCallForwardingOption(
- callForwardingReason, onCompleted);
+ Pair<Integer, TelephonyManager.CallForwardingInfoCallback> args =
+ (Pair<Integer, TelephonyManager.CallForwardingInfoCallback>)
+ request.argument;
+ int callForwardingReason = args.first;
+ request.phone.getCallForwardingOption(callForwardingReason, onCompleted);
break;
-
- case EVENT_GET_CALL_FORWARDING_DONE:
+ }
+ case EVENT_GET_CALL_FORWARDING_DONE: {
ar = (AsyncResult) msg.obj;
request = (MainThreadRequest) ar.userObj;
- CallForwardingInfo callForwardingInfo = null;
+ TelephonyManager.CallForwardingInfoCallback callback =
+ ((Pair<Integer, TelephonyManager.CallForwardingInfoCallback>)
+ request.argument).second;
if (ar.exception == null && ar.result != null) {
+ CallForwardingInfo callForwardingInfo = null;
CallForwardInfo[] callForwardInfos = (CallForwardInfo[]) ar.result;
for (CallForwardInfo callForwardInfo : callForwardInfos) {
// Service Class is a bit mask per 3gpp 27.007. Search for
// any service for voice call.
if ((callForwardInfo.serviceClass
& CommandsInterface.SERVICE_CLASS_VOICE) > 0) {
- callForwardingInfo = new CallForwardingInfo(
- callForwardInfo.serviceClass, callForwardInfo.reason,
- callForwardInfo.number,
- callForwardInfo.timeSeconds);
+ callForwardingInfo = new CallForwardingInfo(true,
+ callForwardInfo.reason,
+ callForwardInfo.number,
+ callForwardInfo.timeSeconds);
break;
}
}
// Didn't find a call forward info for voice call.
if (callForwardingInfo == null) {
- callForwardingInfo = new CallForwardingInfo(
- CallForwardingInfo.STATUS_UNKNOWN_ERROR,
- 0 /* reason */, null /* number */, 0 /* timeout */);
+ callForwardingInfo = new CallForwardingInfo(false /* enabled */,
+ 0 /* reason */, null /* number */, 0 /* timeout */);
}
+ callback.onCallForwardingInfoAvailable(callForwardingInfo);
} else {
if (ar.result == null) {
loge("EVENT_GET_CALL_FORWARDING_DONE: Empty response");
@@ -868,56 +977,80 @@
if (ar.exception != null) {
loge("EVENT_GET_CALL_FORWARDING_DONE: Exception: " + ar.exception);
}
- int errorCode = CallForwardingInfo.STATUS_UNKNOWN_ERROR;
+ int errorCode = TelephonyManager
+ .CallForwardingInfoCallback.RESULT_ERROR_UNKNOWN;
if (ar.exception instanceof CommandException) {
CommandException.Error error =
((CommandException) (ar.exception)).getCommandError();
if (error == CommandException.Error.FDN_CHECK_FAILURE) {
- errorCode = CallForwardingInfo.STATUS_FDN_CHECK_FAILURE;
+ errorCode = TelephonyManager
+ .CallForwardingInfoCallback.RESULT_ERROR_FDN_CHECK_FAILURE;
} else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
- errorCode = CallForwardingInfo.STATUS_NOT_SUPPORTED;
+ errorCode = TelephonyManager
+ .CallForwardingInfoCallback.RESULT_ERROR_NOT_SUPPORTED;
}
}
- callForwardingInfo = new CallForwardingInfo(
- errorCode, 0 /* reason */, null /* number */, 0 /* timeout */);
+ callback.onError(errorCode);
}
- request.result = callForwardingInfo;
- notifyRequester(request);
break;
+ }
- case CMD_SET_CALL_FORWARDING:
+ case CMD_SET_CALL_FORWARDING: {
request = (MainThreadRequest) msg.obj;
onCompleted = obtainMessage(EVENT_SET_CALL_FORWARDING_DONE, request);
+ request = (MainThreadRequest) msg.obj;
CallForwardingInfo callForwardingInfoToSet =
- (CallForwardingInfo) request.argument;
- getPhoneFromRequest(request).setCallForwardingOption(
- callForwardingInfoToSet.getStatus(),
+ ((Pair<CallForwardingInfo, Consumer<Integer>>)
+ request.argument).first;
+ request.phone.setCallForwardingOption(
+ callForwardingInfoToSet.isEnabled()
+ ? CommandsInterface.CF_ACTION_ENABLE
+ : CommandsInterface.CF_ACTION_DISABLE,
callForwardingInfoToSet.getReason(),
callForwardingInfoToSet.getNumber(),
callForwardingInfoToSet.getTimeoutSeconds(), onCompleted);
break;
+ }
- case EVENT_SET_CALL_FORWARDING_DONE:
+ case EVENT_SET_CALL_FORWARDING_DONE: {
ar = (AsyncResult) msg.obj;
request = (MainThreadRequest) ar.userObj;
- if (ar.exception == null) {
- request.result = true;
- } else {
- request.result = false;
+ Consumer<Integer> callback =
+ ((Pair<CallForwardingInfo, Consumer<Integer>>)
+ request.argument).second;
+ if (ar.exception != null) {
loge("setCallForwarding exception: " + ar.exception);
+ int errorCode = TelephonyManager.CallForwardingInfoCallback
+ .RESULT_ERROR_UNKNOWN;
+ if (ar.exception instanceof CommandException) {
+ CommandException.Error error =
+ ((CommandException) (ar.exception)).getCommandError();
+ if (error == CommandException.Error.FDN_CHECK_FAILURE) {
+ errorCode = TelephonyManager.CallForwardingInfoCallback
+ .RESULT_ERROR_FDN_CHECK_FAILURE;
+ } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
+ errorCode = TelephonyManager.CallForwardingInfoCallback
+ .RESULT_ERROR_NOT_SUPPORTED;
+ }
+ }
+ callback.accept(errorCode);
+ } else {
+ callback.accept(TelephonyManager.CallForwardingInfoCallback.RESULT_SUCCESS);
}
- notifyRequester(request);
break;
+ }
- case CMD_GET_CALL_WAITING:
+ case CMD_GET_CALL_WAITING: {
request = (MainThreadRequest) msg.obj;
onCompleted = obtainMessage(EVENT_GET_CALL_WAITING_DONE, request);
getPhoneFromRequest(request).getCallWaiting(onCompleted);
break;
+ }
- case EVENT_GET_CALL_WAITING_DONE:
+ case EVENT_GET_CALL_WAITING_DONE: {
ar = (AsyncResult) msg.obj;
request = (MainThreadRequest) ar.userObj;
+ Consumer<Integer> callback = (Consumer<Integer>) request.argument;
int callForwardingStatus = TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR;
if (ar.exception == null && ar.result != null) {
int[] callForwardResults = (int[]) ar.result;
@@ -925,12 +1058,12 @@
// Search for any service for voice call.
if (callForwardResults.length > 1
&& ((callForwardResults[1]
- & CommandsInterface.SERVICE_CLASS_VOICE) > 0)) {
+ & CommandsInterface.SERVICE_CLASS_VOICE) > 0)) {
callForwardingStatus = callForwardResults[0] == 0
- ? TelephonyManager.CALL_WAITING_STATUS_INACTIVE
- : TelephonyManager.CALL_WAITING_STATUS_ACTIVE;
+ ? TelephonyManager.CALL_WAITING_STATUS_DISABLED
+ : TelephonyManager.CALL_WAITING_STATUS_ENABLED;
} else {
- callForwardingStatus = TelephonyManager.CALL_WAITING_STATUS_INACTIVE;
+ callForwardingStatus = TelephonyManager.CALL_WAITING_STATUS_DISABLED;
}
} else {
if (ar.result == null) {
@@ -948,28 +1081,43 @@
}
}
}
- request.result = callForwardingStatus;
- notifyRequester(request);
+ callback.accept(callForwardingStatus);
break;
+ }
- case CMD_SET_CALL_WAITING:
+ case CMD_SET_CALL_WAITING: {
request = (MainThreadRequest) msg.obj;
onCompleted = obtainMessage(EVENT_SET_CALL_WAITING_DONE, request);
- boolean isEnable = (Boolean) request.argument;
- getPhoneFromRequest(request).setCallWaiting(isEnable, onCompleted);
+ boolean enable = ((Pair<Boolean, Consumer<Integer>>) request.argument).first;
+ getPhoneFromRequest(request).setCallWaiting(enable, onCompleted);
break;
+ }
- case EVENT_SET_CALL_WAITING_DONE:
+ case EVENT_SET_CALL_WAITING_DONE: {
ar = (AsyncResult) msg.obj;
request = (MainThreadRequest) ar.userObj;
- if (ar.exception == null) {
- request.result = true;
- } else {
- request.result = false;
+ boolean enable = ((Pair<Boolean, Consumer<Integer>>) request.argument).first;
+ Consumer<Integer> callback =
+ ((Pair<Boolean, Consumer<Integer>>) request.argument).second;
+ if (ar.exception != null) {
loge("setCallWaiting exception: " + ar.exception);
+ if (ar.exception instanceof CommandException) {
+ CommandException.Error error =
+ ((CommandException) (ar.exception)).getCommandError();
+ if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
+ callback.accept(TelephonyManager.CALL_WAITING_STATUS_NOT_SUPPORTED);
+ } else {
+ callback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
+ }
+ } else {
+ callback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
+ }
+ } else {
+ callback.accept(enable ? TelephonyManager.CALL_WAITING_STATUS_ENABLED
+ : TelephonyManager.CALL_WAITING_STATUS_DISABLED);
}
- notifyRequester(request);
break;
+ }
case EVENT_PERFORM_NETWORK_SCAN_DONE:
ar = (AsyncResult) msg.obj;
@@ -1248,11 +1396,27 @@
request.result = ar.exception == null;
notifyRequester(request);
break;
+ case CMD_GET_CDMA_SUBSCRIPTION_MODE:
+ request = (MainThreadRequest) msg.obj;
+ onCompleted = obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_MODE_DONE, request);
+ getPhoneFromRequest(request).queryCdmaSubscriptionMode(onCompleted);
+ break;
+ case EVENT_GET_CDMA_SUBSCRIPTION_MODE_DONE:
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+ if (ar.exception != null) {
+ request.result = TelephonyManager.CDMA_SUBSCRIPTION_RUIM_SIM;
+ } else {
+ request.result = ((int[]) ar.result)[0];
+ }
+ notifyRequester(request);
+ break;
case CMD_SET_CDMA_SUBSCRIPTION_MODE:
request = (MainThreadRequest) msg.obj;
onCompleted = obtainMessage(EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE, request);
int subscriptionMode = (int) request.argument;
- getPhoneFromRequest(request).setCdmaSubscription(subscriptionMode, onCompleted);
+ getPhoneFromRequest(request).setCdmaSubscriptionMode(
+ subscriptionMode, onCompleted);
break;
case EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE:
ar = (AsyncResult) msg.obj;
@@ -1302,19 +1466,20 @@
Log.w(LOG_TAG, "Discarded CellInfo due to Callback RemoteException");
}
break;
- case CMD_GET_CELL_LOCATION:
+ case CMD_GET_CELL_LOCATION: {
request = (MainThreadRequest) msg.obj;
WorkSource ws = (WorkSource) request.argument;
Phone phone = getPhoneFromRequest(request);
phone.getCellIdentity(ws, obtainMessage(EVENT_GET_CELL_LOCATION_DONE, request));
break;
- case EVENT_GET_CELL_LOCATION_DONE:
+ }
+ case EVENT_GET_CELL_LOCATION_DONE: {
ar = (AsyncResult) msg.obj;
request = (MainThreadRequest) ar.userObj;
if (ar.exception == null) {
request.result = ar.result;
} else {
- phone = getPhoneFromRequest(request);
+ Phone phone = getPhoneFromRequest(request);
request.result = (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA)
? new CellIdentityCdma() : new CellIdentityGsm();
}
@@ -1323,6 +1488,7 @@
request.notifyAll();
}
break;
+ }
case CMD_MODEM_REBOOT:
request = (MainThreadRequest) msg.obj;
onCompleted = obtainMessage(EVENT_RESET_MODEM_CONFIG_DONE, request);
@@ -1398,6 +1564,35 @@
notifyRequester(request);
break;
}
+ case CMD_GET_SYSTEM_SELECTION_CHANNELS: {
+ request = (MainThreadRequest) msg.obj;
+ onCompleted = obtainMessage(EVENT_GET_SYSTEM_SELECTION_CHANNELS_DONE, request);
+ Phone phone = getPhoneFromRequest(request);
+ if (phone != null) {
+ phone.getSystemSelectionChannels(onCompleted);
+ } else {
+ loge("getSystemSelectionChannels: No phone object");
+ request.result = new ArrayList<RadioAccessSpecifier>();
+ notifyRequester(request);
+ }
+ break;
+ }
+ case EVENT_GET_SYSTEM_SELECTION_CHANNELS_DONE:
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+ if (ar.exception == null && ar.result != null) {
+ request.result = ar.result;
+ } else {
+ request.result = new IllegalArgumentException(
+ "Failed to retrieve system selection channels");
+ if (ar.result == null) {
+ loge("getSystemSelectionChannels: Empty response");
+ } else {
+ loge("getSystemSelectionChannels: Unknown exception");
+ }
+ }
+ notifyRequester(request);
+ break;
case EVENT_SET_FORBIDDEN_PLMNS_DONE:
ar = (AsyncResult) msg.obj;
request = (MainThreadRequest) ar.userObj;
@@ -1494,6 +1689,52 @@
getDefaultPhone().getContext().sendBroadcastAsUser(
intent, UserHandle.ALL, permission.USER_ACTIVITY);
break;
+
+ case CMD_SET_DATA_THROTTLING: {
+ request = (MainThreadRequest) msg.obj;
+ onCompleted = obtainMessage(EVENT_SET_DATA_THROTTLING_DONE, request);
+ DataThrottlingRequest dataThrottlingRequest =
+ (DataThrottlingRequest) request.argument;
+ Phone phone = getPhoneFromRequest(request);
+ if (phone != null) {
+ phone.setDataThrottling(onCompleted,
+ request.workSource, dataThrottlingRequest.getDataThrottlingAction(),
+ dataThrottlingRequest.getCompletionDurationMillis());
+ } else {
+ loge("setDataThrottling: No phone object");
+ request.result =
+ TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
+ notifyRequester(request);
+ }
+
+ break;
+ }
+ case EVENT_SET_DATA_THROTTLING_DONE:
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+
+ if (ar.exception == null) {
+ request.result = TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
+ } else if (ar.exception instanceof CommandException) {
+ loge("setDataThrottling: CommandException: " + ar.exception);
+ CommandException.Error error =
+ ((CommandException) (ar.exception)).getCommandError();
+
+ if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
+ request.result = TelephonyManager
+ .THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
+ } else if (error == CommandException.Error.INVALID_ARGUMENTS) {
+ request.result = SET_DATA_THROTTLING_MODEM_THREW_INVALID_PARAMS;
+ } else {
+ request.result =
+ TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_ERROR;
+ }
+ } else {
+ request.result = TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_ERROR;
+ }
+ Log.w(LOG_TAG, "DataThrottlingResult = " + request.result);
+ notifyRequester(request);
+ break;
default:
Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
break;
@@ -2174,7 +2415,8 @@
int subId = mSubscriptionController.getDefaultDataSubId();
final Phone phone = getPhone(subId);
if (phone != null) {
- phone.getDataEnabledSettings().setUserDataEnabled(true);
+ phone.getDataEnabledSettings().setDataEnabled(
+ TelephonyManager.DATA_ENABLED_REASON_USER, true);
return true;
} else {
return false;
@@ -2194,7 +2436,8 @@
int subId = mSubscriptionController.getDefaultDataSubId();
final Phone phone = getPhone(subId);
if (phone != null) {
- phone.getDataEnabledSettings().setUserDataEnabled(false);
+ phone.getDataEnabledSettings().setDataEnabled(
+ TelephonyManager.DATA_ENABLED_REASON_USER, false);
return true;
} else {
return false;
@@ -5007,58 +5250,35 @@
}
/**
- * Returns the {@link IImsMmTelFeature} that corresponds to the given slot Id for the MMTel
- * feature or {@link null} if the service is not available. If the feature is available, the
- * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates.
+ * Registers for updates to the MmTelFeature connection through the IImsServiceFeatureCallback
+ * callback.
*/
- public IImsMmTelFeature getMmTelFeatureAndListen(int slotId,
- IImsServiceFeatureCallback callback) {
+ @Override
+ public void registerMmTelFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
enforceModifyPermission();
final long identity = Binder.clearCallingIdentity();
try {
if (mImsResolver == null) {
- // may happen if the device does not support IMS.
- return null;
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "Device does not support IMS");
}
- return mImsResolver.getMmTelFeatureAndListen(slotId, callback);
+ mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_MMTEL, callback);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
-
- /**
- * Returns the {@link IImsRcsFeature} that corresponds to the given slot Id for the RCS
- * feature during emergency calling or {@link null} if the service is not available. If the
- * feature is available, the {@link IImsServiceFeatureCallback} callback is registered as a
- * listener for feature updates.
- */
- public IImsRcsFeature getRcsFeatureAndListen(int slotId, IImsServiceFeatureCallback callback) {
- enforceModifyPermission();
-
- final long identity = Binder.clearCallingIdentity();
- try {
- if (mImsResolver == null) {
- // may happen if the device does not support IMS.
- return null;
- }
- return mImsResolver.getRcsFeatureAndListen(slotId, callback);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
/**
* Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
*/
- public void unregisterImsFeatureCallback(int slotId, int featureType,
- IImsServiceFeatureCallback callback) {
+ @Override
+ public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
enforceModifyPermission();
final long identity = Binder.clearCallingIdentity();
try {
if (mImsResolver == null) return;
- mImsResolver.unregisterImsFeatureCallback(slotId, featureType, callback);
+ mImsResolver.unregisterImsFeatureCallback(callback);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -5139,6 +5359,36 @@
}
/**
+ * Clears any carrier ImsService overrides for the slot index specified that were previously
+ * set with {@link #setBoundImsServiceOverride(int, boolean, int[], String)}.
+ *
+ * This should only be used for testing.
+ *
+ * @param slotIndex the slot ID that the ImsService should bind for.
+ * @return true if clearing the carrier ImsService override succeeded or false if it did not.
+ */
+ @Override
+ public boolean clearCarrierImsServiceOverride(int slotIndex) {
+ int[] subIds = SubscriptionManager.getSubId(slotIndex);
+ TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
+ "clearCarrierImsServiceOverride");
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
+ (subIds != null ? subIds[0] : SubscriptionManager.INVALID_SUBSCRIPTION_ID),
+ "clearCarrierImsServiceOverride");
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ if (mImsResolver == null) {
+ // may happen if the device does not support IMS.
+ return false;
+ }
+ return mImsResolver.clearCarrierImsServiceConfiguration(slotIndex);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
* Return the package name of the currently bound ImsService.
*
* @param slotId The slot that the ImsService is associated with.
@@ -5235,7 +5485,7 @@
}
}
- /**
+ /**
* Ask the radio to connect to the input network and change selection mode to manual.
*
* @param subId the id of the subscription.
@@ -5339,7 +5589,8 @@
* Get the call forwarding info, given the call forwarding reason.
*/
@Override
- public CallForwardingInfo getCallForwarding(int subId, int callForwardingReason) {
+ public void getCallForwarding(int subId, int callForwardingReason,
+ ICallForwardingInfoCallback callback) {
enforceReadPrivilegedPermission("getCallForwarding");
long identity = Binder.clearCallingIdentity();
try {
@@ -5347,8 +5598,39 @@
log("getCallForwarding: subId " + subId
+ " callForwardingReason" + callForwardingReason);
}
- return (CallForwardingInfo) sendRequest(
- CMD_GET_CALL_FORWARDING, callForwardingReason, subId);
+
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ try {
+ callback.onError(
+ TelephonyManager.CallForwardingInfoCallback.RESULT_ERROR_UNKNOWN);
+ } catch (RemoteException e) {
+ // ignore
+ }
+ return;
+ }
+
+ Pair<Integer, TelephonyManager.CallForwardingInfoCallback> argument = Pair.create(
+ callForwardingReason, new TelephonyManager.CallForwardingInfoCallback() {
+ @Override
+ public void onCallForwardingInfoAvailable(CallForwardingInfo info) {
+ try {
+ callback.onCallForwardingInfoAvailable(info);
+ } catch (RemoteException e) {
+ // ignore
+ }
+ }
+
+ @Override
+ public void onError(int error) {
+ try {
+ callback.onError(error);
+ } catch (RemoteException e) {
+ // ignore
+ }
+ }
+ });
+ sendRequestAsync(CMD_GET_CALL_FORWARDING, argument, phone, null);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -5359,7 +5641,8 @@
* reason, the number to forward, and the timeout before the forwarding is attempted.
*/
@Override
- public boolean setCallForwarding(int subId, CallForwardingInfo callForwardingInfo) {
+ public void setCallForwarding(int subId, CallForwardingInfo callForwardingInfo,
+ IIntegerConsumer callback) {
enforceModifyPermission();
long identity = Binder.clearCallingIdentity();
try {
@@ -5367,38 +5650,79 @@
log("setCallForwarding: subId " + subId
+ " callForwardingInfo" + callForwardingInfo);
}
- return (Boolean) sendRequest(CMD_SET_CALL_FORWARDING, callForwardingInfo, subId);
+
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ try {
+ callback.accept(
+ TelephonyManager.CallForwardingInfoCallback.RESULT_ERROR_UNKNOWN);
+ } catch (RemoteException e) {
+ // ignore
+ }
+ return;
+ }
+
+ Pair<CallForwardingInfo, Consumer<Integer>> arguments = Pair.create(callForwardingInfo,
+ FunctionalUtils.ignoreRemoteException(callback::accept));
+
+ sendRequestAsync(CMD_SET_CALL_FORWARDING, arguments, phone, null);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
/**
- * Get the call forwarding info, given the call forwarding reason.
+ * Get the call waiting status for a subId.
*/
@Override
- public int getCallWaitingStatus(int subId) {
+ public void getCallWaitingStatus(int subId, IIntegerConsumer callback) {
enforceReadPrivilegedPermission("getCallForwarding");
long identity = Binder.clearCallingIdentity();
try {
+
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ try {
+ callback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
+ } catch (RemoteException e) {
+ // ignore
+ }
+ return;
+ }
+
+ Consumer<Integer> argument = FunctionalUtils.ignoreRemoteException(callback::accept);
+
if (DBG) log("getCallWaitingStatus: subId " + subId);
- return (Integer) sendRequest(CMD_GET_CALL_WAITING, null, subId);
+ sendRequestAsync(CMD_GET_CALL_WAITING, argument, phone, null);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
/**
- * Sets the voice call forwarding info including status (enable/disable), call forwarding
- * reason, the number to forward, and the timeout before the forwarding is attempted.
+ * Sets whether call waiting is enabled for a given subId.
*/
@Override
- public boolean setCallWaitingStatus(int subId, boolean isEnable) {
+ public void setCallWaitingStatus(int subId, boolean enable, IIntegerConsumer callback) {
enforceModifyPermission();
long identity = Binder.clearCallingIdentity();
try {
- if (DBG) log("setCallWaitingStatus: subId " + subId + " isEnable: " + isEnable);
- return (Boolean) sendRequest(CMD_SET_CALL_WAITING, isEnable, subId);
+ if (DBG) log("setCallWaitingStatus: subId " + subId + " enable: " + enable);
+
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ try {
+ callback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
+ } catch (RemoteException e) {
+ // ignore
+ }
+ return;
+ }
+
+ Pair<Boolean, Consumer<Integer>> arguments = Pair.create(enable,
+ FunctionalUtils.ignoreRemoteException(callback::accept));
+
+ sendRequestAsync(CMD_SET_CALL_WAITING, arguments, phone, null);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -5429,7 +5753,8 @@
.setMinSdkVersionForFine(Build.VERSION_CODES.Q)
.build());
if (locationResult != LocationAccessPolicy.LocationPermissionResult.ALLOWED) {
- SecurityException e = checkNetworkRequestForSanitizedLocationAccess(request, subId);
+ SecurityException e = checkNetworkRequestForSanitizedLocationAccess(
+ request, subId, callingPackage);
if (e != null) {
if (locationResult == LocationAccessPolicy.LocationPermissionResult.DENIED_HARD) {
throw e;
@@ -5452,8 +5777,8 @@
}
private SecurityException checkNetworkRequestForSanitizedLocationAccess(
- NetworkScanRequest request, int subId) {
- boolean hasCarrierPriv = getCarrierPrivilegeStatusForUid(subId, Binder.getCallingUid())
+ NetworkScanRequest request, int subId, String callingPackage) {
+ boolean hasCarrierPriv = checkCarrierPrivilegesForPackage(subId, callingPackage)
== TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
boolean hasNetworkScanPermission =
mApp.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_SCAN)
@@ -5633,6 +5958,80 @@
}
/**
+ * Enable/Disable E-UTRA-NR Dual Connectivity
+ * @param subId subscription id of the sim card
+ * @param nrDualConnectivityState expected NR dual connectivity state
+ * This can be passed following states
+ * <ol>
+ * <li>Enable NR dual connectivity {@link TelephonyManager#NR_DUAL_CONNECTIVITY_ENABLE}
+ * <li>Disable NR dual connectivity {@link TelephonyManager#NR_DUAL_CONNECTIVITY_DISABLE}
+ * <li>Disable NR dual connectivity and force secondary cell to be released
+ * {@link TelephonyManager#NR_DUAL_CONNECTIVITY_DISABLE_IMMEDIATE}
+ * </ol>
+ * @return operation result.
+ */
+ @Override
+ public int setNrDualConnectivityState(int subId,
+ @TelephonyManager.NrDualConnectivityState int nrDualConnectivityState) {
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+ mApp, subId, "enableNRDualConnectivity");
+ WorkSource workSource = getWorkSource(Binder.getCallingUid());
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ int result = (int) sendRequest(CMD_ENABLE_NR_DUAL_CONNECTIVITY,
+ nrDualConnectivityState, subId,
+ workSource);
+ if (DBG) log("enableNRDualConnectivity result: " + result);
+ return result;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Is E-UTRA-NR Dual Connectivity enabled
+ * @return true if dual connectivity is enabled else false
+ */
+ @Override
+ public boolean isNrDualConnectivityEnabled(int subId) {
+ TelephonyPermissions
+ .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ mApp, subId, "isNRDualConnectivityEnabled");
+ WorkSource workSource = getWorkSource(Binder.getCallingUid());
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ boolean isEnabled = (boolean) sendRequest(CMD_IS_NR_DUAL_CONNECTIVITY_ENABLED,
+ null, subId, workSource);
+ if (DBG) log("isNRDualConnectivityEnabled: " + isEnabled);
+ return isEnabled;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * get carrier bandwidth per primary and secondary carrier
+ * @param subId subscription id of the sim card
+ * @return CarrierBandwidth with bandwidth of both primary and secondary carrier..
+ */
+ @Override
+ public CarrierBandwidth getCarrierBandwidth(int subId) {
+ TelephonyPermissions
+ .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ mApp, subId, "isNRDualConnectivityEnabled");
+ WorkSource workSource = getWorkSource(Binder.getCallingUid());
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ CarrierBandwidth carrierBandwidth =
+ getPhoneFromSubId(subId).getCarrierBandwidth();
+ if (DBG) log("getCarrierBandwidth: " + carrierBandwidth);
+ return carrierBandwidth;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
* Get the effective allowed network types on the device.
* This API will return an intersection of allowed network types for all reasons,
* including the configuration done through setAllowedNetworkTypes
@@ -5703,33 +6102,6 @@
}
/**
- * Set mobile data enabled
- * Used by the user through settings etc to turn on/off mobile data
- *
- * @param enable {@code true} turn turn data on, else {@code false}
- */
- @Override
- public void setUserDataEnabled(int subId, boolean enable) {
- TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
- mApp, subId, "setUserDataEnabled");
-
- final long identity = Binder.clearCallingIdentity();
- try {
- int phoneId = mSubscriptionController.getPhoneId(subId);
- if (DBG) log("setUserDataEnabled: subId=" + subId + " phoneId=" + phoneId);
- Phone phone = PhoneFactory.getPhone(phoneId);
- if (phone != null) {
- if (DBG) log("setUserDataEnabled: subId=" + subId + " enable=" + enable);
- phone.getDataEnabledSettings().setUserDataEnabled(enable);
- } else {
- loge("setUserDataEnabled: no phone found. Invalid subId=" + subId);
- }
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- /**
* Enable or disable always reporting signal strength changes from radio.
*
* @param isEnable {@code true} for enabling; {@code false} for disabling.
@@ -5819,7 +6191,18 @@
*/
@Override
public boolean isDataEnabled(int subId) {
- enforceReadPrivilegedPermission("isDataEnabled");
+ try {
+ try {
+ mApp.enforceCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_NETWORK_STATE,
+ null);
+ } catch (Exception e) {
+ mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
+ "isDataEnabled");
+ }
+ } catch (Exception e) {
+ enforceReadPrivilegedPermission("isDataEnabled");
+ }
final long identity = Binder.clearCallingIdentity();
try {
@@ -5839,6 +6222,53 @@
}
}
+ /**
+ * Check if data is enabled for a specific reason
+ * @param subId Subscription index
+ * @param reason the reason the data enable change is taking place
+ * @return {@code true} if the overall data is enabled; {@code false} if not.
+ */
+ @Override
+ public boolean isDataEnabledForReason(int subId,
+ @TelephonyManager.DataEnabledReason int reason) {
+ try {
+ mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
+ null);
+ } catch (Exception e) {
+ mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
+ "isDataEnabledForReason");
+ }
+
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ int phoneId = mSubscriptionController.getPhoneId(subId);
+ if (DBG) {
+ log("isDataEnabledForReason: subId=" + subId + " phoneId=" + phoneId
+ + " reason=" + reason);
+ }
+ Phone phone = PhoneFactory.getPhone(phoneId);
+ if (phone != null) {
+ boolean retVal;
+ if (reason == TelephonyManager.DATA_ENABLED_REASON_USER) {
+ retVal = phone.isUserDataEnabled();
+ } else {
+ retVal = phone.getDataEnabledSettings().isDataEnabledForReason(reason);
+ }
+ if (DBG) log("isDataEnabledForReason: retVal=" + retVal);
+ return retVal;
+ } else {
+ if (DBG) {
+ loge("isDataEnabledForReason: no phone subId="
+ + subId + " retVal=false");
+ }
+ return false;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
private int getCarrierPrivilegeStatusFromCarrierConfigRules(int privilegeFromSim, int uid,
Phone phone) {
if (uid == Process.SYSTEM_UID || uid == Process.PHONE_UID) {
@@ -5856,7 +6286,13 @@
final long identity = Binder.clearCallingIdentity();
try {
- SubscriptionInfo subInfo = subController.getSubscriptionInfo(phone.getSubId());
+ int subId = phone.getSubId();
+ if (mCarrierPrivilegeTestOverrideSubIds.contains(subId)) {
+ // A test override is in place for the privileges for this subId, so don't try to
+ // read the subscription privileges.
+ return privilegeFromSim;
+ }
+ SubscriptionInfo subInfo = subController.getSubscriptionInfo(subId);
SubscriptionManager subManager = (SubscriptionManager)
phone.getContext().getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
for (String pkg : packages) {
@@ -5879,7 +6315,13 @@
final long identity = Binder.clearCallingIdentity();
try {
- SubscriptionInfo subInfo = subController.getSubscriptionInfo(phone.getSubId());
+ int subId = phone.getSubId();
+ if (mCarrierPrivilegeTestOverrideSubIds.contains(subId)) {
+ // A test override is in place for the privileges for this subId, so don't try to
+ // read the subscription privileges.
+ return privilegeFromSim;
+ }
+ SubscriptionInfo subInfo = subController.getSubscriptionInfo(subId);
SubscriptionManager subManager = (SubscriptionManager)
phone.getContext().getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
return subManager.canManageSubscription(subInfo, pkgName)
@@ -6031,12 +6473,10 @@
final Phone phone = getPhone(subId);
UiccCard card = phone == null ? null : phone.getUiccCard();
if (card == null) {
- loge("getIccId: No UICC");
return null;
}
String iccId = card.getIccId();
if (TextUtils.isEmpty(iccId)) {
- loge("getIccId: ICC ID is null or empty.");
return null;
}
return iccId;
@@ -6655,7 +7095,8 @@
try {
if (SubscriptionManager.isUsableSubIdValue(subId) && !mUserManager.hasUserRestriction(
UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
- setUserDataEnabled(subId, getDefaultDataEnabled());
+ setDataEnabledForReason(subId, TelephonyManager.DATA_ENABLED_REASON_USER,
+ getDefaultDataEnabled());
setNetworkSelectionModeAutomatic(subId);
setPreferredNetworkType(subId, getDefaultNetworkType(subId));
setDataRoamingEnabled(subId, getDefaultDataRoamingEnabled(subId));
@@ -7175,31 +7616,6 @@
}
/**
- * Action set from carrier signalling broadcast receivers to enable/disable metered apns
- * @param subId the subscription ID that this action applies to.
- * @param enabled control enable or disable metered apns.
- * {@hide}
- */
- @Override
- public void carrierActionSetMeteredApnsEnabled(int subId, boolean enabled) {
- enforceModifyPermission();
- final Phone phone = getPhone(subId);
-
- final long identity = Binder.clearCallingIdentity();
- if (phone == null) {
- loge("carrierAction: SetMeteredApnsEnabled fails with invalid subId: " + subId);
- return;
- }
- try {
- phone.carrierActionSetMeteredApnsEnabled(enabled);
- } catch (Exception e) {
- Log.e(LOG_TAG, "carrierAction: SetMeteredApnsEnabled fails. Exception ex=" + e);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- /**
* Action set from carrier signalling broadcast receivers to enable/disable radio
* @param subId the subscription ID that this action applies to.
* @param enabled control enable or disable radio.
@@ -7300,20 +7716,36 @@
}
/**
- * Policy control of data connection. Usually used when data limit is passed.
- * @param enabled True if enabling the data, otherwise disabling.
+ * Policy control of data connection with reason {@@TelephonyManager.DataEnabledReason}
* @param subId Subscription index
- * {@hide}
+ * @param reason the reason the data enable change is taking place
+ * @param enabled True if enabling the data, otherwise disabling.
+ * @hide
*/
@Override
- public void setPolicyDataEnabled(boolean enabled, int subId) {
- enforceModifyPermission();
+ public void setDataEnabledForReason(int subId, @TelephonyManager.DataEnabledReason int reason,
+ boolean enabled) {
+ if (reason == TelephonyManager.DATA_ENABLED_REASON_USER
+ || reason == TelephonyManager.DATA_ENABLED_REASON_CARRIER) {
+ try {
+ TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
+ mApp, subId, "setDataEnabledForReason");
+ } catch (SecurityException se) {
+ enforceModifyPermission();
+ }
+ } else {
+ enforceModifyPermission();
+ }
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subId);
if (phone != null) {
- phone.getDataEnabledSettings().setPolicyDataEnabled(enabled);
+ if (reason == TelephonyManager.DATA_ENABLED_REASON_CARRIER) {
+ phone.carrierActionSetMeteredApnsEnabled(enabled);
+ } else {
+ phone.getDataEnabledSettings().setDataEnabled(reason, enabled);
+ }
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -7764,6 +8196,11 @@
}
phone.setCarrierTestOverride(mccmnc, imsi, iccid, gid1, gid2, plmn, spn,
carrierPrivilegeRules, apn);
+ if (carrierPrivilegeRules == null) {
+ mCarrierPrivilegeTestOverrideSubIds.remove(subId);
+ } else {
+ mCarrierPrivilegeTestOverrideSubIds.add(subId);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -7831,6 +8268,20 @@
}
@Override
+ public int getCdmaSubscriptionMode(int subId) {
+ TelephonyPermissions
+ .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ mApp, subId, "getCdmaSubscriptionMode");
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return (int) sendRequest(CMD_GET_CDMA_SUBSCRIPTION_MODE, null /* argument */, subId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public boolean setCdmaSubscriptionMode(int subId, int mode) {
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "setCdmaSubscriptionMode");
@@ -7880,11 +8331,9 @@
try {
for (Phone phone: PhoneFactory.getPhones()) {
if (phone.getEmergencyNumberTracker() != null
- && phone.getEmergencyNumberTracker() != null) {
- if (phone.getEmergencyNumberTracker().isEmergencyNumber(
- number, exactMatch)) {
- return true;
- }
+ && phone.getEmergencyNumberTracker()
+ .isEmergencyNumber(number, exactMatch)) {
+ return true;
}
}
return false;
@@ -8265,7 +8714,7 @@
* 1) user data is turned on, or
* 2) APN is un-metered for this subscription, or
* 3) APN type is whitelisted. E.g. MMS is whitelisted if
- * {@link TelephonyManager#setAlwaysAllowMmsData} is turned on.
+ * {@link TelephonyManager#MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED} is enabled.
*
* @return whether data is allowed for a apn type.
*
@@ -8339,6 +8788,24 @@
}
@Override
+ public List<RadioAccessSpecifier> getSystemSelectionChannels(int subId) {
+ TelephonyPermissions
+ .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ mApp, subId, "getSystemSelectionChannels");
+ WorkSource workSource = getWorkSource(Binder.getCallingUid());
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ List<RadioAccessSpecifier> specifiers =
+ (List<RadioAccessSpecifier>) sendRequest(CMD_GET_SYSTEM_SELECTION_CHANNELS,
+ null, subId, workSource);
+ if (DBG) log("getSystemSelectionChannels: " + specifiers);
+ return specifiers;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public boolean isMvnoMatched(int subId, int mvnoType, @NonNull String mvnoMatchData) {
enforceReadPrivilegedPermission("isMvnoMatched");
IccRecords iccRecords = UiccController.getInstance().getIccRecords(
@@ -8407,55 +8874,54 @@
}
@Override
- public boolean setDataAllowedDuringVoiceCall(int subId, boolean allow) {
- enforceModifyPermission();
+ public boolean isMobileDataPolicyEnabled(int subscriptionId, int policy) {
+ enforceReadPrivilegedPermission("isMobileDataPolicyEnabled");
- // Now that all security checks passes, perform the operation as ourselves.
final long identity = Binder.clearCallingIdentity();
try {
- Phone phone = getPhone(subId);
+ Phone phone = getPhone(subscriptionId);
if (phone == null) return false;
- return phone.getDataEnabledSettings().setAllowDataDuringVoiceCall(allow);
+ switch (policy) {
+ case TelephonyManager.MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL:
+ return phone.getDataEnabledSettings().isDataAllowedInVoiceCall();
+ case TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED:
+ return phone.getDataEnabledSettings().isMmsAlwaysAllowed();
+ default:
+ throw new IllegalArgumentException(policy + " is not a valid policy");
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
- public boolean isDataAllowedInVoiceCall(int subId) {
- enforceReadPrivilegedPermission("isDataAllowedInVoiceCall");
-
- // Now that all security checks passes, perform the operation as ourselves.
- final long identity = Binder.clearCallingIdentity();
- try {
- Phone phone = getPhone(subId);
- if (phone == null) return false;
-
- return phone.getDataEnabledSettings().isDataAllowedInVoiceCall();
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public boolean setAlwaysAllowMmsData(int subId, boolean alwaysAllow) {
+ public void setMobileDataPolicyEnabledStatus(int subscriptionId, int policy,
+ boolean enabled) {
enforceModifyPermission();
- // Now that all security checks passes, perform the operation as ourselves.
final long identity = Binder.clearCallingIdentity();
try {
- Phone phone = getPhone(subId);
- if (phone == null) return false;
+ Phone phone = getPhone(subscriptionId);
+ if (phone == null) return;
- return phone.getDataEnabledSettings().setAlwaysAllowMmsData(alwaysAllow);
+ switch (policy) {
+ case TelephonyManager.MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL:
+ phone.getDataEnabledSettings().setAllowDataDuringVoiceCall(enabled);
+ break;
+ case TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED:
+ phone.getDataEnabledSettings().setAlwaysAllowMmsData(enabled);
+ break;
+ default:
+ throw new IllegalArgumentException(policy + " is not a valid policy");
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
}
/**
- * Updates whether conference event pacakge handling is enabled.
+ * Updates whether conference event package handling is enabled.
* @param isCepEnabled {@code true} if CEP handling is enabled (default), or {@code false}
* otherwise.
*/
@@ -8632,4 +9098,178 @@
public boolean canConnectTo5GInDsdsMode() {
return mApp.getResources().getBoolean(R.bool.config_5g_connection_in_dsds_mode);
}
+
+ @Override
+ public @NonNull List<String> getEquivalentHomePlmns(int subId, String callingPackage,
+ String callingFeatureId) {
+ if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+ mApp, subId, callingPackage, callingFeatureId, "getEquivalentHomePlmns")) {
+ throw new SecurityException("Requires READ_PHONE_STATE permission.");
+ }
+
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ throw new RuntimeException("phone is not available");
+ }
+ // Now that all security checks passes, perform the operation as ourselves.
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return phone.getEquivalentHomePlmns();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Attempts to set the radio power state for thermal reason. This does not guarantee that the
+ * requested radio power state will actually be set. See {@link
+ * PhoneInternalInterface#setRadioPowerForReason} for more details.
+ *
+ * @param subId the subscription ID of the phone requesting to set the radio power state.
+ * @param enable {@code true} if trying to turn radio on.
+ * @return {@code true} if phone setRadioPowerForReason was called. Otherwise, returns {@code
+ * false}.
+ */
+ private boolean setRadioPowerForThermal(int subId, boolean enable) {
+ Phone phone = getPhone(subId);
+ if (phone != null) {
+ phone.setRadioPowerForReason(enable, Phone.RADIO_POWER_REASON_THERMAL);
+ return true;
+ }
+ return false;
+ }
+
+ private int handleDataThrottlingRequest(int subId,
+ DataThrottlingRequest dataThrottlingRequest) {
+ // Ensure that radio is on. If not able to power on due to phone being unavailable, return
+ // THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE.
+ if (!setRadioPowerForThermal(subId, true)) {
+ return TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
+ }
+
+ setDataEnabledForReason(subId, TelephonyManager.DATA_ENABLED_REASON_THERMAL, true);
+
+ int thermalMitigationResult =
+ (int) sendRequest(CMD_SET_DATA_THROTTLING, dataThrottlingRequest, subId);
+ if (thermalMitigationResult == SET_DATA_THROTTLING_MODEM_THREW_INVALID_PARAMS) {
+ throw new IllegalArgumentException("modem returned INVALID_ARGUMENTS");
+ }
+ return thermalMitigationResult;
+ }
+
+ /**
+ * Thermal mitigation request to control functionalities at modem.
+ *
+ * @param subId the id of the subscription.
+ * @param thermalMitigationRequest holds all necessary information to be passed down to modem.
+ *
+ * @return thermalMitigationResult enum as defined in android.telephony.Annotation.
+ */
+ @Override
+ @ThermalMitigationResult
+ public int sendThermalMitigationRequest(
+ int subId,
+ ThermalMitigationRequest thermalMitigationRequest) throws IllegalArgumentException {
+ enforceModifyPermission();
+
+ WorkSource workSource = getWorkSource(Binder.getCallingUid());
+ final long identity = Binder.clearCallingIdentity();
+
+ int thermalMitigationResult = TelephonyManager.THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR;
+ try {
+ int thermalMitigationAction = thermalMitigationRequest.getThermalMitigationAction();
+ switch (thermalMitigationAction) {
+ case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_DATA_THROTTLING:
+ thermalMitigationResult =
+ handleDataThrottlingRequest(subId,
+ thermalMitigationRequest.getDataThrottlingRequest());
+ break;
+ case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_VOICE_ONLY:
+ if (thermalMitigationRequest.getDataThrottlingRequest() != null) {
+ throw new IllegalArgumentException("dataThrottlingRequest must be null for "
+ + "ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_VOICE_ONLY");
+ }
+
+ // Ensure that radio is on. If not able to power on due to phone being
+ // unavailable, return THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE.
+ if (!setRadioPowerForThermal(subId, true)) {
+ thermalMitigationResult =
+ TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
+ break;
+ }
+
+ setDataEnabledForReason(subId, TelephonyManager.DATA_ENABLED_REASON_THERMAL,
+ false);
+ thermalMitigationResult = TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
+ break;
+ case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_RADIO_OFF:
+ if (thermalMitigationRequest.getDataThrottlingRequest() != null) {
+ throw new IllegalArgumentException("dataThrottlingRequest must be null for"
+ + " ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_RADIO_OFF");
+ }
+
+ TelecomAccountRegistry registry = TelecomAccountRegistry.getInstance(null);
+ if (registry != null) {
+ TelephonyConnectionService service =
+ registry.getTelephonyConnectionService();
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ thermalMitigationResult =
+ TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
+ break;
+ }
+
+ if (PhoneConstantConversions.convertCallState(phone.getState())
+ != TelephonyManager.CALL_STATE_IDLE
+ || phone.isInEmergencySmsMode() || phone.isInEcm()
+ || (service != null && service.isEmergencyCallPending())) {
+ String errorMessage = "Phone state is not valid. call state = "
+ + PhoneConstantConversions.convertCallState(phone.getState())
+ + " isInEmergencySmsMode = " + phone.isInEmergencySmsMode()
+ + " isInEmergencyCallbackMode = " + phone.isInEcm();
+ errorMessage += service == null
+ ? " TelephonyConnectionService is null"
+ : " isEmergencyCallPending = "
+ + service.isEmergencyCallPending();
+ Log.e(LOG_TAG, errorMessage);
+ thermalMitigationResult =
+ TelephonyManager.THERMAL_MITIGATION_RESULT_INVALID_STATE;
+ break;
+ }
+ } else {
+ thermalMitigationResult =
+ TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
+ break;
+ }
+
+ // Turn radio off. If not able to power off due to phone being unavailable,
+ // return THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE.
+ if (!setRadioPowerForThermal(subId, false)) {
+ thermalMitigationResult =
+ TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
+ break;
+ }
+ thermalMitigationResult =
+ TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
+ break;
+ default:
+ throw new IllegalArgumentException("the requested thermalMitigationAction does "
+ + "not exist. Requested action: " + thermalMitigationAction);
+ }
+ } catch (IllegalArgumentException e) {
+ throw e;
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "thermalMitigationRequest. Exception e =" + e);
+ thermalMitigationResult = TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_ERROR;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+
+ if (DBG) {
+ log("thermalMitigationRequest returning with thermalMitigationResult: "
+ + thermalMitigationResult);
+ }
+
+ return thermalMitigationResult;
+ }
}
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index c3f2974..33d0721 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -17,7 +17,6 @@
package com.android.phone;
import android.content.Context;
-import android.os.BasicShellCommandHandler;
import android.os.Binder;
import android.os.PersistableBundle;
import android.os.Process;
@@ -34,6 +33,7 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.modules.utils.BasicShellCommandHandler;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -64,8 +64,9 @@
private static final String DATA_ENABLE = "enable";
private static final String DATA_DISABLE = "disable";
- private static final String IMS_SET_CARRIER_SERVICE = "set-ims-service";
- private static final String IMS_GET_CARRIER_SERVICE = "get-ims-service";
+ private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
+ private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
+ private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
private static final String IMS_ENABLE = "enable";
private static final String IMS_DISABLE = "disable";
// Used to disable or enable processing of conference event package data from the network.
@@ -210,6 +211,11 @@
pw.println(" -d: The ImsService defined as the device default ImsService.");
pw.println(" -f: The feature type that the query will be requested for. If none is");
pw.println(" specified, the returned package name will correspond to MMTEL.");
+ pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
+ pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
+ pw.println(" configuration overrides. Options are:");
+ pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
+ pw.println(" is specified, it will choose the default voice SIM slot.");
pw.println(" ims enable [-s SLOT_ID]");
pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
pw.println(" if none is specified.");
@@ -295,12 +301,15 @@
}
switch (arg) {
- case IMS_SET_CARRIER_SERVICE: {
+ case IMS_SET_IMS_SERVICE: {
return handleImsSetServiceCommand();
}
- case IMS_GET_CARRIER_SERVICE: {
+ case IMS_GET_IMS_SERVICE: {
return handleImsGetServiceCommand();
}
+ case IMS_CLEAR_SERVICE_OVERRIDE: {
+ return handleImsClearCarrierServiceCommand();
+ }
case IMS_ENABLE: {
return handleEnableIms();
}
@@ -547,6 +556,42 @@
return 0;
}
+ // ims clear-ims-service-override
+ private int handleImsClearCarrierServiceCommand() {
+ PrintWriter errPw = getErrPrintWriter();
+ int slotId = getDefaultSlot();
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "-s": {
+ try {
+ slotId = Integer.parseInt(getNextArgRequired());
+ } catch (NumberFormatException e) {
+ errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
+ return -1;
+ }
+ break;
+ }
+ }
+ }
+
+ try {
+ boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
+ if (VDBG) {
+ Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
+ + ", result=" + result);
+ }
+ getOutPrintWriter().println(result);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
+ + ", error" + e.getMessage());
+ errPw.println("Exception: " + e.getMessage());
+ return -1;
+ }
+ return 0;
+ }
+
// ims get-ims-service
private int handleImsGetServiceCommand() {
PrintWriter errPw = getErrPrintWriter();
diff --git a/src/com/android/phone/TimeConsumingPreferenceActivity.java b/src/com/android/phone/TimeConsumingPreferenceActivity.java
index 3b5fe21..8c5ae6d 100644
--- a/src/com/android/phone/TimeConsumingPreferenceActivity.java
+++ b/src/com/android/phone/TimeConsumingPreferenceActivity.java
@@ -187,11 +187,6 @@
@Override
public void onError(Preference preference, int error) {
if (DBG) dumpState();
- if (!preference.isEnabled()) {
- Log.i(LOG_TAG, "onError, skipped duplicated error popup");
- return;
- }
-
Log.i(LOG_TAG, "onError, preference=" + preference.getKey() + ", error=" + error);
if (mIsForeground) {
diff --git a/src/com/android/services/telephony/CdmaConnection.java b/src/com/android/services/telephony/CdmaConnection.java
index 90e7663..c7b324d 100644
--- a/src/com/android/services/telephony/CdmaConnection.java
+++ b/src/com/android/services/telephony/CdmaConnection.java
@@ -16,11 +16,12 @@
package com.android.services.telephony;
+import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.telephony.DisconnectCause;
-import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
@@ -284,8 +285,14 @@
private boolean isEmergency() {
Phone phone = getPhone();
- return phone != null && getAddress() != null && PhoneNumberUtils.isLocalEmergencyNumber(
- phone.getContext(), getAddress().getSchemeSpecificPart());
+ if (phone != null && getAddress() != null) {
+ TelephonyManager tm = (TelephonyManager) phone.getContext()
+ .getSystemService(Context.TELEPHONY_SERVICE);
+ if (tm != null) {
+ return tm.isEmergencyNumber(getAddress().getSchemeSpecificPart());
+ }
+ }
+ return false;
}
/**
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 4826ecb..c9f762b 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -16,6 +16,7 @@
package com.android.services.telephony;
+import android.annotation.NonNull;
import android.content.Context;
import android.graphics.drawable.Icon;
import android.net.Uri;
@@ -28,6 +29,7 @@
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.telephony.PhoneNumberUtils;
+import android.text.TextUtils;
import android.util.Pair;
import com.android.ims.internal.ConferenceParticipant;
@@ -1269,58 +1271,79 @@
}
/**
+ * Extracts a phone number from a {@link Uri}.
+ * <p>
+ * Phone numbers can be represented either as a TEL URI or a SIP URI.
+ * For conference event packages, RFC3261 specifies how participants can be identified using a
+ * SIP URI.
+ * A valid SIP uri has the format: sip:user:password@host:port;uri-parameters?headers
+ * Per RFC3261, the "user" can be a telephone number.
+ * For example: sip:1650555121;phone-context=blah.com@host.com
+ * In this case, the phone number is in the user field of the URI, and the parameters can be
+ * ignored.
+ *
+ * A SIP URI can also specify a phone number in a format similar to:
+ * sip:+1-212-555-1212@something.com;user=phone
+ * In this case, the phone number is again in user field and the parameters can be ignored.
+ * We can get the user field in these instances by splitting the string on the @, ;, or :
+ * and looking at the first found item.
+ * @param handle The URI containing a SIP or TEL formatted phone number.
+ * @return extracted phone number.
+ */
+ private static @NonNull String extractPhoneNumber(@NonNull Uri handle) {
+ // Number is always in the scheme specific part, regardless of whether this is a TEL or SIP
+ // URI.
+ String number = handle.getSchemeSpecificPart();
+ // Get anything before the @ for the SIP case.
+ String[] numberParts = number.split("[@;:]");
+
+ if (numberParts.length == 0) {
+ Log.v(LOG_TAG, "extractPhoneNumber(N) : no number in handle");
+ return "";
+ }
+ return numberParts[0];
+ }
+
+ /**
* Determines if the passed in participant handle is the same as the conference host's handle.
* Starts with a simple equality check. However, the handles from a conference event package
* will be a SIP uri, so we need to pull that apart to look for the participant's phone number.
*
- * @param hostHandles The handle(s) of the connection hosting the conference.
+ * @param hostHandles The handle(s) of the connection hosting the conference, typically obtained
+ * from P-Associated-Uri entries.
* @param handle The handle of the conference participant.
* @return {@code true} if the host's handle matches the participant's handle, {@code false}
* otherwise.
*/
- private boolean isParticipantHost(Uri[] hostHandles, Uri handle) {
+ @VisibleForTesting
+ public static boolean isParticipantHost(Uri[] hostHandles, Uri handle) {
// If there is no host handle or no participant handle, bail early.
if (hostHandles == null || hostHandles.length == 0 || handle == null) {
- Log.v(this, "isParticipantHost(N) : host or participant uri null");
+ Log.v(LOG_TAG, "isParticipantHost(N) : host or participant uri null");
return false;
}
- // Conference event package participants are identified using SIP URIs (see RFC3261).
- // A valid SIP uri has the format: sip:user:password@host:port;uri-parameters?headers
- // Per RFC3261, the "user" can be a telephone number.
- // For example: sip:1650555121;phone-context=blah.com@host.com
- // In this case, the phone number is in the user field of the URI, and the parameters can be
- // ignored.
- //
- // A SIP URI can also specify a phone number in a format similar to:
- // sip:+1-212-555-1212@something.com;user=phone
- // In this case, the phone number is again in user field and the parameters can be ignored.
- // We can get the user field in these instances by splitting the string on the @, ;, or :
- // and looking at the first found item.
-
- String number = handle.getSchemeSpecificPart();
- String numberParts[] = number.split("[@;:]");
-
- if (numberParts.length == 0) {
- Log.v(this, "isParticipantHost(N) : no number in participant handle");
+ String number = extractPhoneNumber(handle);
+ // If we couldn't extract the participant's number, then we can't determine if it is the
+ // host or not.
+ if (TextUtils.isEmpty(number)) {
return false;
}
- number = numberParts[0];
for (Uri hostHandle : hostHandles) {
if (hostHandle == null) {
continue;
}
- // The host number will be a tel: uri. Per RFC3966, the part after tel: is the phone
- // number.
- String hostNumber = hostHandle.getSchemeSpecificPart();
+ // Similar to the CEP participant data, the host identity in the P-Associated-Uri could
+ // be a SIP URI or a TEL URI.
+ String hostNumber = extractPhoneNumber(hostHandle);
// Use a loose comparison of the phone numbers. This ensures that numbers that differ
// by special characters are counted as equal.
// E.g. +16505551212 would be the same as 16505551212
boolean isHost = PhoneNumberUtils.compare(hostNumber, number);
- Log.v(this, "isParticipantHost(%s) : host: %s, participant %s", (isHost ? "Y" : "N"),
+ Log.v(LOG_TAG, "isParticipantHost(%s) : host: %s, participant %s", (isHost ? "Y" : "N"),
Rlog.pii(LOG_TAG, hostNumber), Rlog.pii(LOG_TAG, number));
if (isHost) {
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 18a9574..4fe5fb9 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -428,8 +428,7 @@
.getBoolean(R.bool.config_support_video_calling_fallback));
if (slotId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
- extras.putString(PhoneAccount.EXTRA_SORT_ORDER,
- String.valueOf(slotId));
+ extras.putInt(PhoneAccount.EXTRA_SORT_ORDER, slotId);
}
mIsMergeCallSupported = isCarrierMergeCallSupported();
@@ -854,7 +853,8 @@
// Next check whether we're in or near a country that supports it
String country =
mPhone.getServiceStateTracker().getLocaleTracker()
- .getCurrentCountry().toLowerCase();
+ .getLastKnownCountryIso().toLowerCase();
+
String[] supportedCountries = mContext.getResources().getStringArray(
R.array.config_simless_emergency_rtt_supported_countries);
if (supportedCountries == null || Arrays.stream(supportedCountries).noneMatch(
@@ -863,7 +863,7 @@
+ " not supported in this country: " + country);
return false;
}
-
+
return true;
}
@@ -1134,7 +1134,7 @@
this.mTelephonyConnectionService = telephonyConnectionService;
}
- TelephonyConnectionService getTelephonyConnectionService() {
+ public TelephonyConnectionService getTelephonyConnectionService() {
return mTelephonyConnectionService;
}
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 5a2b384..09c83c0 100755
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -96,6 +96,9 @@
private static final int MSG_CONFERENCE_MERGE_FAILED = 6;
private static final int MSG_SUPP_SERVICE_NOTIFY = 7;
+ // the threshold used to compare mAudioCodecBitrateKbps and mAudioCodecBandwidth.
+ private static final float THRESHOLD = 0.01f;
+
/**
* Mappings from {@link com.android.internal.telephony.Connection} extras keys to their
* equivalents defined in {@link android.telecom.Connection}.
@@ -1325,7 +1328,9 @@
setCallerDisplayName(name, namePresentation);
}
- if (PhoneNumberUtils.isEmergencyNumber(mOriginalConnection.getAddress())) {
+ TelephonyManager tm = (TelephonyManager) getPhone().getContext()
+ .getSystemService(Context.TELEPHONY_SERVICE);
+ if (tm.isEmergencyNumber(mOriginalConnection.getAddress())) {
mTreatAsEmergencyCall = true;
}
@@ -1388,7 +1393,9 @@
mHandler.obtainMessage(MSG_CONNECTION_EXTRAS_CHANGED, connExtras == null ? null :
new Bundle(connExtras)).sendToTarget();
- if (PhoneNumberUtils.isEmergencyNumber(mOriginalConnection.getAddress())) {
+ TelephonyManager tm = (TelephonyManager) getPhone().getContext()
+ .getSystemService(Context.TELEPHONY_SERVICE);
+ if (tm.isEmergencyNumber(mOriginalConnection.getAddress())) {
mTreatAsEmergencyCall = true;
}
// Propagate VERSTAT for IMS calls.
@@ -1492,7 +1499,8 @@
}
}
- private void refreshCodecType() {
+ private void refreshCodec() {
+ boolean changed = false;
Bundle newExtras = getExtras();
if (newExtras == null) {
newExtras = new Bundle();
@@ -1508,6 +1516,31 @@
Connection.AUDIO_CODEC_NONE);
if (newCodecType != oldCodecType) {
newExtras.putInt(Connection.EXTRA_AUDIO_CODEC, newCodecType);
+ changed = true;
+ }
+ if (isImsConnection()) {
+ float newBitrate = getOriginalConnection().getAudioCodecBitrateKbps();
+ float oldBitrate = newExtras.getFloat(Connection.EXTRA_AUDIO_CODEC_BITRATE_KBPS, 0.0f);
+ if (Math.abs(newBitrate - oldBitrate) > THRESHOLD) {
+ newExtras.putFloat(Connection.EXTRA_AUDIO_CODEC_BITRATE_KBPS, newBitrate);
+ changed = true;
+ }
+
+ float newBandwidth = getOriginalConnection().getAudioCodecBandwidthKhz();
+ float oldBandwidth = newExtras.getFloat(Connection.EXTRA_AUDIO_CODEC_BANDWIDTH_KHZ,
+ 0.0f);
+ if (Math.abs(newBandwidth - oldBandwidth) > THRESHOLD) {
+ newExtras.putFloat(Connection.EXTRA_AUDIO_CODEC_BANDWIDTH_KHZ, newBandwidth);
+ changed = true;
+ }
+ } else {
+ ArrayList<String> toRemove = new ArrayList<>();
+ toRemove.add(Connection.EXTRA_AUDIO_CODEC_BITRATE_KBPS);
+ toRemove.add(Connection.EXTRA_AUDIO_CODEC_BANDWIDTH_KHZ);
+ removeTelephonyExtras(toRemove);
+ }
+
+ if (changed) {
putTelephonyExtras(newExtras);
}
}
@@ -1586,7 +1619,7 @@
}
}
- isVowifiEnabled = ImsUtil.isWfcEnabled(phone.getContext(), phone.getPhoneId());
+ isVowifiEnabled = isWfcEnabled(phone);
}
if (isCurrentVideoCall) {
@@ -2191,7 +2224,7 @@
updateAddress();
updateMultiparty();
refreshDisableAddCall();
- refreshCodecType();
+ refreshCodec();
}
/**
@@ -2722,7 +2755,7 @@
boolean isIms = phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS;
boolean isVoWifiEnabled = false;
if (isIms) {
- isVoWifiEnabled = ImsUtil.isWfcEnabled(phone.getContext(), phone.getPhoneId());
+ isVoWifiEnabled = isWfcEnabled(phone);
}
boolean isRttMergeSupported = getCarrierConfig()
.getBoolean(CarrierConfigManager.KEY_ALLOW_MERGING_RTT_CALLS_BOOL);
@@ -2772,6 +2805,12 @@
notifyConferenceSupportedChanged(isConferenceSupported);
}
}
+
+ @VisibleForTesting
+ boolean isWfcEnabled(Phone phone) {
+ return ImsUtil.isWfcEnabled(phone.getContext(), phone.getPhoneId());
+ }
+
/**
* Provides a mapping from extras keys which may be found in the
* {@link com.android.internal.telephony.Connection} to their equivalents defined in
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index a2e9565..56012c8 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -160,6 +160,9 @@
private EmergencyTonePlayer mEmergencyTonePlayer;
private HoldTracker mHoldTracker;
private boolean mIsTtyEnabled;
+ /** Set to true when there is an emergency call pending which will potential trigger a dial.
+ * This must be set to false when the call is dialed. */
+ private volatile boolean mIsEmergencyCallPending;
// Contains one TelephonyConnection that has placed a call and a memory of which Phones it has
// already tried to connect with. There should be only one TelephonyConnection trying to place a
@@ -800,6 +803,10 @@
if (mRadioOnHelper == null) {
mRadioOnHelper = new RadioOnHelper(this);
}
+
+ if (isEmergencyNumber) {
+ mIsEmergencyCallPending = true;
+ }
mRadioOnHelper.triggerRadioOnAndListen(new RadioOnStateListener.Callback() {
@Override
public void onComplete(RadioOnStateListener listener, boolean isRadioReady) {
@@ -912,6 +919,14 @@
}
/**
+ * @return whether radio has recently been turned on for emergency call but hasn't actually
+ * dialed the call yet.
+ */
+ public boolean isEmergencyCallPending() {
+ return mIsEmergencyCallPending;
+ }
+
+ /**
* Whether the cellular radio is power off because the device is on Bluetooth.
*/
private boolean isRadioPowerDownOnBluetooth() {
@@ -936,6 +951,7 @@
for (Phone curPhone : mPhoneFactoryProxy.getPhones()) {
curPhone.setRadioPower(true, false, false, true);
}
+ mIsEmergencyCallPending = false;
}
return;
}
@@ -951,6 +967,7 @@
Log.i(this, "handleOnComplete - delayDialForDdsSwitch result = " + result);
adjustAndPlaceOutgoingConnection(phone, originalConnection, request,
numberToDial, handle, originalPhoneType, true);
+ mIsEmergencyCallPending = false;
}
});
}
@@ -961,6 +978,7 @@
mDisconnectCauseFactory.toTelecomDisconnectCause(
android.telephony.DisconnectCause.POWER_OFF,
"Failed to turn on radio."));
+ mIsEmergencyCallPending = false;
}
}
@@ -1687,7 +1705,6 @@
EmergencyNumber emergencyNumber =
phone.getEmergencyNumberTracker().getEmergencyNumber(number);
if (emergencyNumber != null) {
- phone.notifyOutgoingEmergencyCall(emergencyNumber);
if (!getAllConnections().isEmpty()) {
if (!shouldHoldForEmergencyCall(phone)) {
// If we do not support holding ongoing calls for an outgoing
diff --git a/src/com/android/services/telephony/rcs/DelegateBinderStateManager.java b/src/com/android/services/telephony/rcs/DelegateBinderStateManager.java
new file mode 100644
index 0000000..39e9965
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/DelegateBinderStateManager.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2020 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.services.telephony.rcs;
+
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.aidl.ISipTransport;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+/**
+ * Defines the interface to be used to manage the state of a SipDelegate on the ImsService side.
+ */
+public interface DelegateBinderStateManager {
+
+ /**
+ * Callback interface that allows listeners to listen to changes in registration or
+ * configuration state.
+ */
+ interface StateCallback {
+ /**
+ * The SipDelegate has notified telephony that the registration state has changed.
+ */
+ void onRegistrationStateChanged(DelegateRegistrationState registrationState);
+
+ /**
+ * The SipDelegate has notified telephony that the IMS configuration has changed.
+ */
+ void onImsConfigurationChanged(SipDelegateImsConfiguration config);
+ }
+
+ /** Allow for mocks to be created for testing. */
+ @VisibleForTesting
+ interface Factory {
+ /**
+ * Create a new instance of this interface, which may change depending on the tags being
+ * denied. See {@link SipDelegateBinderConnectionStub} and
+ * {@link SipDelegateBinderConnection}
+ */
+ DelegateBinderStateManager create(int subId, ISipTransport sipTransport,
+ DelegateRequest requestedConfig, Set<FeatureTagState> transportDeniedTags,
+ Executor executor, List<StateCallback> stateCallbacks);
+ }
+
+ /**
+ * Start the process to create a SipDelegate on the ImsService.
+ * @param cb The Binder interface that the SipDelegate should use to notify new incoming SIP
+ * messages as well as acknowledge whether or not an outgoing SIP message was
+ * successfully sent.
+ * @param createdConsumer The consumer that will be notified when the creation process has
+ * completed. Contains the ISipDelegate interface to communicate with the SipDelegate
+ * and the feature tags the SipDelegate itself denied.
+ * @return true if the creation process started, false if the remote process died. If false, the
+ * consumers will not be notified.
+ */
+ boolean create(ISipDelegateMessageCallback cb,
+ BiConsumer<ISipDelegate, Set<FeatureTagState>> createdConsumer);
+
+ /**
+ * Destroy the existing SipDelegate managed by this object.
+ * <p>
+ * This instance should be cleaned up after this call.
+ * @param reason The reason for why this delegate is being destroyed.
+ * @param destroyedConsumer The consumer that will be notified when this operation completes.
+ * Contains the reason the SipDelegate reported it was destroyed.
+ */
+ void destroy(int reason, Consumer<Integer> destroyedConsumer);
+}
diff --git a/src/com/android/services/telephony/rcs/DelegateStateTracker.java b/src/com/android/services/telephony/rcs/DelegateStateTracker.java
new file mode 100644
index 0000000..1d8fa3b
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/DelegateStateTracker.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2020 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.services.telephony.rcs;
+
+import android.os.RemoteException;
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
+import android.telephony.ims.stub.DelegateConnectionStateCallback;
+import android.util.LocalLog;
+import android.util.Log;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Manages the events sent back to the remote IMS application using the AIDL backing for the
+ * {@link DelegateConnectionStateCallback} interface.
+ */
+public class DelegateStateTracker implements DelegateBinderStateManager.StateCallback {
+ private static final String LOG_TAG = "DelegateST";
+
+ private final int mSubId;
+ private final ISipDelegateConnectionStateCallback mAppStateCallback;
+ private final ISipDelegate mLocalDelegateImpl;
+
+ private final LocalLog mLocalLog = new LocalLog(SipTransportController.LOG_SIZE);
+
+ private List<FeatureTagState> mDelegateDeniedTags;
+ private DelegateRegistrationState mLastRegState;
+ private boolean mCreatedCalled = false;
+ private int mRegistrationStateOverride = -1;
+
+ public DelegateStateTracker(int subId, ISipDelegateConnectionStateCallback appStateCallback,
+ ISipDelegate localDelegateImpl) {
+ mSubId = subId;
+ mAppStateCallback = appStateCallback;
+ mLocalDelegateImpl = localDelegateImpl;
+ }
+
+ /**
+ * Notify this state tracker that a new internal SipDelegate has been connected.
+ *
+ * Registration and state updates will be send via the
+ * {@link SipDelegateBinderConnection.StateCallback} callback implemented by this class as they
+ * arrive.
+ * @param deniedTags The tags denied by the SipTransportController and ImsService creating the
+ * SipDelegate. These tags will need to be notified back to the IMS application.
+ */
+ public void sipDelegateConnected(Set<FeatureTagState> deniedTags) {
+ logi("SipDelegate connected with denied tags:" + deniedTags);
+ // From the IMS application perspective, we only call onCreated/onDestroyed once and
+ // provide the local implementation of ISipDelegate, which doesn't change, even though
+ // SipDelegates may be changing underneath.
+ if (!mCreatedCalled) {
+ mCreatedCalled = true;
+ notifySipDelegateCreated();
+ }
+ mRegistrationStateOverride = -1;
+ mDelegateDeniedTags = new ArrayList<>(deniedTags);
+ }
+
+ /**
+ * The underlying SipDelegate is changing due to a state change in the SipDelegateController.
+ *
+ * This will trigger an override of the IMS application's registration state. All feature tags
+ * in the REGISTERED state will be overridden to move to the deregistering state specified until
+ * a new SipDelegate was successfully created and {@link #sipDelegateConnected(Set)} was called
+ * or it was destroyed and {@link #sipDelegateDestroyed(int)} was called.
+ * @param deregisteringReason The new deregistering reason that all feature tags in the
+ * registered state should now report.
+ */
+ public void sipDelegateChanging(int deregisteringReason) {
+ logi("SipDelegate Changing");
+ mRegistrationStateOverride = deregisteringReason;
+ if (mLastRegState == null) {
+ logw("sipDelegateChanging: invalid state, onRegistrationStateChanged never called.");
+ mLastRegState = new DelegateRegistrationState.Builder().build();
+ }
+ onRegistrationStateChanged(mLastRegState);
+ }
+
+ /**
+ * The underlying SipDelegate has been destroyed.
+ *
+ * This should only be called when the entire {@link SipDelegateController} is going down
+ * because the application has requested that the SipDelegate be destroyed.
+ *
+ * This can also be called in error conditions where the IMS application or ImsService has
+ * crashed.
+ * @param reason The reason that will be sent to the IMS application for why the SipDelegate
+ * is being destroyed.
+ */
+ public void sipDelegateDestroyed(int reason) {
+ logi("SipDelegate destroyed:" + reason);
+ mRegistrationStateOverride = -1;
+ try {
+ mAppStateCallback.onDestroyed(reason);
+ } catch (RemoteException e) {
+ logw("sipDelegateDestroyed: IMS application is dead: " + e);
+ }
+ }
+
+ /**
+ * The underlying SipDelegate has reported that its registration state has changed.
+ * @param registrationState The RegistrationState reported by the SipDelegate to be sent to the
+ * IMS application.
+ */
+ @Override
+ public void onRegistrationStateChanged(DelegateRegistrationState registrationState) {
+ if (mRegistrationStateOverride > DelegateRegistrationState.DEREGISTERED_REASON_UNKNOWN) {
+ logi("onRegistrationStateChanged: overriding registered state to "
+ + mRegistrationStateOverride);
+ registrationState = overrideRegistrationForDelegateChange(mRegistrationStateOverride,
+ registrationState);
+ }
+ if (registrationState.equals(mLastRegState)) {
+ logi("onRegistrationStateChanged: skipping notification, state is the same.");
+ return;
+ }
+ mLastRegState = registrationState;
+ logi("onRegistrationStateChanged: sending reg state " + registrationState);
+ try {
+ mAppStateCallback.onFeatureTagStatusChanged(registrationState, mDelegateDeniedTags);
+ } catch (RemoteException e) {
+ logw("onRegistrationStateChanged: IMS application is dead: " + e);
+ }
+ }
+
+ /**
+ * THe underlying SipDelegate has reported that the IMS configuration has changed.
+ * @param config The config to be sent to the IMS application.
+ */
+ @Override
+ public void onImsConfigurationChanged(SipDelegateImsConfiguration config) {
+ logi("onImsConfigurationChanged: Sending new IMS configuration.");
+ try {
+ mAppStateCallback.onImsConfigurationChanged(config);
+ } catch (RemoteException e) {
+ logw("onImsConfigurationChanged: IMS application is dead: " + e);
+ }
+ }
+
+ /** Write state about this tracker into the PrintWriter to be included in the dumpsys */
+ public void dump(PrintWriter printWriter) {
+ printWriter.println("Last reg state: " + mLastRegState);
+ printWriter.println("Denied tags: " + mDelegateDeniedTags);
+ printWriter.println("Most recent logs: ");
+ printWriter.println();
+ mLocalLog.dump(printWriter);
+ }
+
+ private DelegateRegistrationState overrideRegistrationForDelegateChange(
+ int registerOverrideReason, DelegateRegistrationState state) {
+ Set<String> registeredFeatures = state.getRegisteredFeatureTags();
+ DelegateRegistrationState.Builder overriddenState = new DelegateRegistrationState.Builder();
+ // keep other deregistering/deregistered tags the same.
+ for (FeatureTagState dereging : state.getDeregisteringFeatureTags()) {
+ overriddenState.addDeregisteringFeatureTag(dereging.getFeatureTag(),
+ dereging.getState());
+ }
+ for (FeatureTagState dereged : state.getDeregisteredFeatureTags()) {
+ overriddenState.addDeregisteredFeatureTag(dereged.getFeatureTag(),
+ dereged.getState());
+ }
+ // Override REGISTERED only
+ for (String ft : registeredFeatures) {
+ overriddenState.addDeregisteringFeatureTag(ft, registerOverrideReason);
+ }
+ return overriddenState.build();
+ }
+
+ private void notifySipDelegateCreated() {
+ try {
+ mAppStateCallback.onCreated(mLocalDelegateImpl);
+ } catch (RemoteException e) {
+ logw("notifySipDelegateCreated: IMS application is dead: " + e);
+ }
+ }
+
+ private void logi(String log) {
+ Log.i(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
+ mLocalLog.log("[I] " + log);
+ }
+ private void logw(String log) {
+ Log.w(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
+ mLocalLog.log("[W] " + log);
+ }
+}
diff --git a/src/com/android/services/telephony/rcs/MessageTransportStateTracker.java b/src/com/android/services/telephony/rcs/MessageTransportStateTracker.java
new file mode 100644
index 0000000..0691ae5
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/MessageTransportStateTracker.java
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2020 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.services.telephony.rcs;
+
+import android.os.Binder;
+import android.os.RemoteException;
+import android.telephony.ims.DelegateMessageCallback;
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.SipMessage;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.stub.SipDelegate;
+import android.util.LocalLog;
+import android.util.Log;
+
+import java.io.PrintWriter;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+/**
+ * Tracks the SIP message path both from the IMS application to the SipDelegate and from the
+ * SipDelegate back to the IMS Application.
+ * <p>
+ * Responsibilities include:
+ * 1) Queue incoming and outgoing SIP messages and deliver to IMS application and SipDelegate in
+ * order. If there is an error delivering the message, notify the caller.
+ * 2) TODO Perform basic validation of outgoing messages.
+ * 3) TODO Record the status of ongoing SIP Dialogs and trigger the completion of pending
+ * consumers when they are finished or call closeDialog to clean up the SIP
+ * dialogs that did not complete within the allotted timeout time.
+ * <p>
+ * Note: This handles incoming binder calls, so all calls from other processes should be handled on
+ * the provided Executor.
+ */
+public class MessageTransportStateTracker implements DelegateBinderStateManager.StateCallback {
+ private static final String TAG = "MessageST";
+
+ /**
+ * Communicates the result of verifying whether a SIP message should be sent based on the
+ * contents of the SIP message as well as if the transport is in an available state for the
+ * intended recipient of the message.
+ */
+ private static class VerificationResult {
+ public static final VerificationResult SUCCESS = new VerificationResult();
+
+ /**
+ * If {@code true}, the requested SIP message has been verified to be sent to the remote. If
+ * {@code false}, the SIP message has failed verification and should not be sent to the
+ * result. The {@link #restrictedReason} field will contain the reason for the verification
+ * failure.
+ */
+ public final boolean isVerified;
+
+ /**
+ * The reason associated with why the SIP message was not verified and generated a
+ * {@code false} result for {@link #isVerified}.
+ */
+ public final int restrictedReason;
+
+ /**
+ * Communicates a verified result of success. Use {@link #SUCCESS} instead.
+ */
+ private VerificationResult() {
+ isVerified = true;
+ restrictedReason = SipDelegateManager.MESSAGE_FAILURE_REASON_UNKNOWN;
+ }
+
+ /**
+ * The result of verifying that the SIP Message should be sent.
+ * @param reason The reason associated with why the SIP message was not verified and
+ * generated a {@code false} result for {@link #isVerified}.
+ */
+ VerificationResult(@SipDelegateManager.MessageFailureReason int reason) {
+ isVerified = false;
+ restrictedReason = reason;
+ }
+ }
+
+ // SipDelegateConnection(IMS Application) -> SipDelegate(ImsService)
+ private final ISipDelegate.Stub mSipDelegateConnection = new ISipDelegate.Stub() {
+ /**
+ * The IMS application is acknowledging that it has successfully received and processed an
+ * incoming SIP message sent by the SipDelegate in
+ * {@link ISipDelegateMessageCallback#onMessageReceived(SipMessage)}.
+ */
+ @Override
+ public void notifyMessageReceived(String viaTransactionId) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> {
+ if (mSipDelegate == null) {
+ logw("notifyMessageReceived called when SipDelegate is not associated for "
+ + "transaction id: " + viaTransactionId);
+ return;
+ }
+ try {
+ // TODO track the SIP Dialogs created/destroyed on the associated
+ // SipDelegate.
+ mSipDelegate.notifyMessageReceived(viaTransactionId);
+ } catch (RemoteException e) {
+ logw("SipDelegate not available when notifyMessageReceived was called "
+ + "for transaction id: " + viaTransactionId);
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * The IMS application is acknowledging that it received an incoming SIP message sent by the
+ * SipDelegate in {@link ISipDelegateMessageCallback#onMessageReceived(SipMessage)} but it
+ * was unable to process it.
+ */
+ @Override
+ public void notifyMessageReceiveError(String viaTransactionId, int reason) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> {
+ if (mSipDelegate == null) {
+ logw("notifyMessageReceiveError called when SipDelegate is not associated "
+ + "for transaction id: " + viaTransactionId);
+ return;
+ }
+ try {
+ // TODO track the SIP Dialogs created/destroyed on the associated
+ // SipDelegate.
+ mSipDelegate.notifyMessageReceiveError(viaTransactionId, reason);
+ } catch (RemoteException e) {
+ logw("SipDelegate not available when notifyMessageReceiveError was called "
+ + "for transaction id: " + viaTransactionId);
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * The IMS application is sending an outgoing SIP message to the SipDelegate to be processed
+ * and sent over the network.
+ */
+ @Override
+ public void sendMessage(SipMessage sipMessage, long configVersion) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> {
+ VerificationResult result = verifyOutgoingMessage(sipMessage);
+ if (!result.isVerified) {
+ notifyDelegateSendError("Outgoing messages restricted", sipMessage,
+ result.restrictedReason);
+ return;
+ }
+ try {
+ // TODO track the SIP Dialogs created/destroyed on the associated
+ // SipDelegate.
+ mSipDelegate.sendMessage(sipMessage, configVersion);
+ logi("sendMessage: message sent - " + sipMessage + ", configVersion: "
+ + configVersion);
+ } catch (RemoteException e) {
+ notifyDelegateSendError("RemoteException: " + e, sipMessage,
+ SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD);
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * The SipDelegateConnection is requesting that the resources associated with an ongoing SIP
+ * dialog be released as the SIP dialog is now closed.
+ */
+ @Override
+ public void closeDialog(String callId) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> {
+ if (mSipDelegate == null) {
+ logw("closeDialog called when SipDelegate is not associated, callId: "
+ + callId);
+ return;
+ }
+ try {
+ // TODO track the SIP Dialogs created/destroyed on the associated
+ // SipDelegate.
+ mSipDelegate.closeDialog(callId);
+ } catch (RemoteException e) {
+ logw("SipDelegate not available when closeDialog was called "
+ + "for call id: " + callId);
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ };
+
+ // SipDelegate(ImsService) -> SipDelegateConnection(IMS Application)
+ private final ISipDelegateMessageCallback.Stub mDelegateConnectionMessageCallback =
+ new ISipDelegateMessageCallback.Stub() {
+ /**
+ * An Incoming SIP Message has been received by the SipDelegate and is being routed
+ * to the IMS application for processing.
+ * <p>
+ * IMS application will call {@link ISipDelegate#notifyMessageReceived(String)} to
+ * acknowledge receipt of this incoming message.
+ */
+ @Override
+ public void onMessageReceived(SipMessage message) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> {
+ VerificationResult result = verifyIncomingMessage(message);
+ if (!result.isVerified) {
+ notifyAppReceiveError("Incoming messages restricted", message,
+ result.restrictedReason);
+ return;
+ }
+ try {
+ // TODO track the SIP Dialogs created/destroyed on the associated
+ // SipDelegate.
+ mAppCallback.onMessageReceived(message);
+ logi("onMessageReceived: received " + message);
+ } catch (RemoteException e) {
+ notifyAppReceiveError("RemoteException: " + e, message,
+ SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD);
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * An outgoing SIP message sent previously by the SipDelegateConnection to the SipDelegate
+ * using {@link ISipDelegate#sendMessage(SipMessage, int)} as been successfully sent.
+ */
+ @Override
+ public void onMessageSent(String viaTransactionId) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> {
+ if (mSipDelegate == null) {
+ logw("Unexpected state, onMessageSent called when SipDelegate is not "
+ + "associated");
+ }
+ try {
+ mAppCallback.onMessageSent(viaTransactionId);
+ } catch (RemoteException e) {
+ logw("Error sending onMessageSent to SipDelegateConnection, remote not"
+ + "available for transaction ID: " + viaTransactionId);
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * An outgoing SIP message sent previously by the SipDelegateConnection to the SipDelegate
+ * using {@link ISipDelegate#sendMessage(SipMessage, int)} failed to be sent.
+ */
+ @Override
+ public void onMessageSendFailure(String viaTransactionId, int reason) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> {
+ if (mSipDelegate == null) {
+ logw("Unexpected state, onMessageSendFailure called when SipDelegate is not"
+ + "associated");
+ }
+ try {
+ mAppCallback.onMessageSendFailure(viaTransactionId, reason);
+ } catch (RemoteException e) {
+ logw("Error sending onMessageSendFailure to SipDelegateConnection, remote"
+ + " not available for transaction ID: " + viaTransactionId);
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ };
+
+ private final ISipDelegateMessageCallback mAppCallback;
+ private final Executor mExecutor;
+ private final int mSubId;
+ private final LocalLog mLocalLog = new LocalLog(SipTransportController.LOG_SIZE);
+
+ private ISipDelegate mSipDelegate;
+ private Consumer<Boolean> mPendingClosedConsumer;
+ private int mDelegateClosingReason = -1;
+ private int mDelegateClosedReason = -1;
+
+ public MessageTransportStateTracker(int subId, Executor executor,
+ ISipDelegateMessageCallback appMessageCallback) {
+ mSubId = subId;
+ mAppCallback = appMessageCallback;
+ mExecutor = executor;
+ }
+
+ @Override
+ public void onRegistrationStateChanged(DelegateRegistrationState registrationState) {
+ // TODO: integrate registration changes to SipMessage verification checks.
+ }
+
+ @Override
+ public void onImsConfigurationChanged(SipDelegateImsConfiguration config) {
+ // Not needed for this Tracker
+ }
+
+ /**
+ * Open the transport and allow SIP messages to be sent/received on the delegate specified.
+ * @param delegate The delegate connection to send SIP messages to on the ImsService.
+ * @param deniedFeatureTags Feature tags that have been denied. Outgoing SIP messages relating
+ * to these tags will be denied.
+ */
+ public void openTransport(ISipDelegate delegate, Set<FeatureTagState> deniedFeatureTags) {
+ mSipDelegate = delegate;
+ mDelegateClosingReason = -1;
+ mDelegateClosedReason = -1;
+ // TODO: integrate denied tags to SipMessage verification checks.
+ }
+
+ /** Dump state about this tracker that should be included in the dumpsys */
+ public void dump(PrintWriter printWriter) {
+ mLocalLog.dump(printWriter);
+ }
+
+ /**
+ * @return SipDelegate implementation to be sent to IMS application.
+ */
+ public ISipDelegate getDelegateConnection() {
+ return mSipDelegateConnection;
+ }
+
+ /**
+ * @return MessageCallback implementation to be sent to the ImsService.
+ */
+ public ISipDelegateMessageCallback getMessageCallback() {
+ return mDelegateConnectionMessageCallback;
+ }
+
+ /**
+ * Gradually close all SIP Dialogs by:
+ * 1) denying all new outgoing SIP Dialog requests with the reason specified and
+ * 2) only allowing existing SIP Dialogs to continue.
+ * <p>
+ * This will allow traffic to continue on existing SIP Dialogs until a BYE is sent and the
+ * SIP Dialogs are closed or a timeout is hit and {@link SipDelegate#closeDialog(String)} is
+ * forcefully called on all open SIP Dialogs.
+ * <p>
+ * Any outgoing out-of-dialog traffic on this transport will be denied with the provided reason.
+ * <p>
+ * Incoming out-of-dialog traffic will continue to be set up until the SipDelegate is fully
+ * closed.
+ * @param delegateClosingReason The reason code to return to
+ * {@link DelegateMessageCallback#onMessageSendFailure(String, int)} if a new out-of-dialog SIP
+ * message is received while waiting for existing Dialogs.
+ * @param closedReason reason to return to new outgoing SIP messages via
+ * {@link SipDelegate#notifyMessageReceiveError(String, int)} once the transport
+ * transitions to the fully closed state.
+ * @param resultConsumer The consumer called when the message transport has been closed. It will
+ * return {@code true} if the procedure completed successfully or {@link false} if the
+ * transport needed to be closed forcefully due to the application not responding before
+ * a timeout occurred.
+ */
+ public void closeGracefully(int delegateClosingReason, int closedReason,
+ Consumer<Boolean> resultConsumer) {
+ mDelegateClosingReason = delegateClosingReason;
+ mPendingClosedConsumer = resultConsumer;
+ mExecutor.execute(() -> {
+ // TODO: Track SIP Dialogs and complete when there are no SIP dialogs open anymore or
+ // the timeout occurs.
+ mPendingClosedConsumer.accept(true);
+ mPendingClosedConsumer = null;
+ closeTransport(closedReason);
+ });
+ }
+
+ /**
+ * Close all ongoing SIP Dialogs immediately and respond to any incoming/outgoing messages with
+ * the provided reason.
+ * @param closedReason The failure reason to provide to incoming/outgoing SIP messages
+ * if an attempt is made to send/receive a message after this method is called.
+ */
+ public void close(int closedReason) {
+ closeTransport(closedReason);
+ }
+
+ // Clean up all state related to the existing SipDelegate immediately.
+ private void closeTransport(int closedReason) {
+ // TODO: add logic to forcefully close open SIP dialogs once they are being tracked.
+ mSipDelegate = null;
+ if (mPendingClosedConsumer != null) {
+ mExecutor.execute(() -> {
+ logw("closeTransport: transport close forced with pending consumer.");
+ mPendingClosedConsumer.accept(false /*closedGracefully*/);
+ mPendingClosedConsumer = null;
+ });
+ }
+ mDelegateClosingReason = -1;
+ mDelegateClosedReason = closedReason;
+ }
+
+ private VerificationResult verifyOutgoingMessage(SipMessage message) {
+ if (mDelegateClosingReason > -1) {
+ return new VerificationResult(mDelegateClosingReason);
+ }
+ if (mDelegateClosedReason > -1) {
+ return new VerificationResult(mDelegateClosedReason);
+ }
+ if (mSipDelegate == null) {
+ logw("sendMessage called when SipDelegate is not associated." + message);
+ return new VerificationResult(SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD);
+ }
+ return VerificationResult.SUCCESS;
+ }
+
+ private VerificationResult verifyIncomingMessage(SipMessage message) {
+ // Do not restrict incoming based on closing reason.
+ if (mDelegateClosedReason > -1) {
+ return new VerificationResult(mDelegateClosedReason);
+ }
+ return VerificationResult.SUCCESS;
+ }
+
+ private void notifyDelegateSendError(String logReason, SipMessage message, int reasonCode) {
+ // TODO parse SipMessage header for viaTransactionId.
+ logw("Error sending SipMessage[id: " + null + ", code: " + reasonCode + "] -> SipDelegate "
+ + "for reason: " + logReason);
+ try {
+ mAppCallback.onMessageSendFailure(null, reasonCode);
+ } catch (RemoteException e) {
+ logw("notifyDelegateSendError, SipDelegate is not available: " + e);
+ }
+ }
+
+ private void notifyAppReceiveError(String logReason, SipMessage message, int reasonCode) {
+ // TODO parse SipMessage header for viaTransactionId.
+ logw("Error sending SipMessage[id: " + null + ", code: " + reasonCode + "] -> "
+ + "SipDelegateConnection for reason: " + logReason);
+ try {
+ mSipDelegate.notifyMessageReceiveError(null, reasonCode);
+ } catch (RemoteException e) {
+ logw("notifyAppReceiveError, SipDelegate is not available: " + e);
+ }
+ }
+
+ private void logi(String log) {
+ Log.w(SipTransportController.LOG_TAG, TAG + "[" + mSubId + "] " + log);
+ mLocalLog.log("[I] " + log);
+ }
+
+ private void logw(String log) {
+ Log.w(SipTransportController.LOG_TAG, TAG + "[" + mSubId + "] " + log);
+ mLocalLog.log("[W] " + log);
+ }
+}
diff --git a/src/com/android/services/telephony/rcs/RcsFeatureController.java b/src/com/android/services/telephony/rcs/RcsFeatureController.java
index fcfe312..304a74d 100644
--- a/src/com/android/services/telephony/rcs/RcsFeatureController.java
+++ b/src/com/android/services/telephony/rcs/RcsFeatureController.java
@@ -20,7 +20,9 @@
import android.content.Context;
import android.net.Uri;
import android.telephony.ims.ImsException;
+import android.telephony.ims.ImsRcsManager;
import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.RegistrationManager;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -28,7 +30,7 @@
import android.util.Log;
import com.android.ims.FeatureConnector;
-import com.android.ims.IFeatureConnector;
+import com.android.ims.FeatureUpdates;
import com.android.ims.RcsFeatureManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.imsphone.ImsRegistrationCallbackHelper;
@@ -72,19 +74,25 @@
* Called when the feature should be destroyed.
*/
void onDestroy();
+
+ /**
+ * Called when a dumpsys is being generated for this RcsFeatureController for all Features
+ * to report their status.
+ */
+ void dump(PrintWriter pw);
}
/**
* Used to inject FeatureConnector instances for testing.
*/
@VisibleForTesting
- public interface FeatureConnectorFactory<T extends IFeatureConnector> {
+ public interface FeatureConnectorFactory<U extends FeatureUpdates> {
/**
- * @return a {@link FeatureConnector} associated for the given {@link IFeatureConnector}
- * and slot id.
+ * @return a {@link FeatureConnector} associated for the given {@link FeatureUpdates}
+ * and slot index.
*/
- FeatureConnector<T> create(Context context, int slotId,
- FeatureConnector.Listener<T> listener, Executor executor, String tag);
+ FeatureConnector<U> create(Context context, int slotIndex,
+ FeatureConnector.Listener<U> listener, Executor executor, String logPrefix);
}
/**
@@ -100,7 +108,8 @@
ImsRegistrationCallbackHelper.ImsRegistrationUpdate cb, Executor executor);
}
- private FeatureConnectorFactory<RcsFeatureManager> mFeatureFactory = FeatureConnector::new;
+ private FeatureConnectorFactory<RcsFeatureManager> mFeatureFactory =
+ RcsFeatureManager::getConnector;
private RegistrationHelperFactory mRegistrationHelperFactory =
ImsRegistrationCallbackHelper::new;
@@ -115,11 +124,6 @@
private FeatureConnector.Listener<RcsFeatureManager> mFeatureConnectorListener =
new FeatureConnector.Listener<RcsFeatureManager>() {
@Override
- public RcsFeatureManager getFeatureManager() {
- return new RcsFeatureManager(mContext, mSlotId);
- }
-
- @Override
public void connectionReady(RcsFeatureManager manager)
throws com.android.ims.ImsException {
if (manager == null) {
@@ -140,7 +144,10 @@
}
@Override
- public void connectionUnavailable() {
+ public void connectionUnavailable(int reason) {
+ if (reason == FeatureConnector.UNAVAILABLE_REASON_SERVER_UNAVAILABLE) {
+ loge("unexpected - connectionUnavailable due to server unavailable");
+ }
// Call before disabling connection to manager.
removeConnectionToService();
updateConnectionStatus(null /*manager*/);
@@ -279,7 +286,7 @@
}
@VisibleForTesting
- public void setFeatureConnectorFactory(FeatureConnectorFactory factory) {
+ public void setFeatureConnectorFactory(FeatureConnectorFactory<RcsFeatureManager> factory) {
mFeatureFactory = factory;
}
@@ -426,6 +433,14 @@
pw.print("connected=");
synchronized (mLock) {
pw.println(mFeatureManager != null);
+ pw.println();
+ pw.println("RcsFeatureControllers:");
+ pw.increaseIndent();
+ for (Feature f : mFeatures.values()) {
+ f.dump(pw);
+ pw.println();
+ }
+ pw.decreaseIndent();
}
}
@@ -433,6 +448,10 @@
Log.w(LOG_TAG, getLogPrefix().append(log).toString());
}
+ private void loge(String log) {
+ Log.e(LOG_TAG, getLogPrefix().append(log).toString());
+ }
+
private StringBuilder getLogPrefix() {
StringBuilder sb = new StringBuilder("[");
sb.append(mSlotId);
diff --git a/src/com/android/services/telephony/rcs/SipDelegateBinderConnection.java b/src/com/android/services/telephony/rcs/SipDelegateBinderConnection.java
new file mode 100644
index 0000000..1a77f2b
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/SipDelegateBinderConnection.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2020 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.services.telephony.rcs;
+
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.aidl.ISipDelegateStateCallback;
+import android.telephony.ims.aidl.ISipTransport;
+import android.telephony.ims.stub.SipDelegate;
+import android.util.LocalLog;
+import android.util.Log;
+
+import java.io.PrintWriter;
+import java.util.Collections;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+/**
+ * Container for the active connection to the {@link SipDelegate} active on the ImsService.
+ * <p>
+ * New instances of this class will be created and destroyed new {@link SipDelegate}s are created
+ * and destroyed by the {@link SipDelegateController}.
+ */
+public class SipDelegateBinderConnection implements DelegateBinderStateManager,
+ IBinder.DeathRecipient {
+ private static final String LOG_TAG = "BinderConn";
+
+ protected final int mSubId;
+ protected final Set<FeatureTagState> mDeniedTags;
+ protected final Executor mExecutor;
+ protected final List<StateCallback> mStateCallbacks;
+
+ private final LocalLog mLocalLog = new LocalLog(SipTransportController.LOG_SIZE);
+
+ // Callback interface from ImsService to this Connection. State Events will be forwarded to IMS
+ // application through DelegateStateTracker.
+ private final ISipDelegateStateCallback mSipDelegateStateCallback =
+ new ISipDelegateStateCallback.Stub() {
+ @Override
+ public void onCreated(ISipDelegate delegate,
+ List<FeatureTagState> deniedFeatureTags) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() ->
+ notifySipDelegateCreated(delegate, deniedFeatureTags));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void onFeatureTagRegistrationChanged(
+ DelegateRegistrationState registrationState) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> {
+ logi("onFeatureTagRegistrationChanged:" + registrationState);
+ for (StateCallback c : mStateCallbacks) {
+ c.onRegistrationStateChanged(registrationState);
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void onImsConfigurationChanged(
+ SipDelegateImsConfiguration registeredSipConfig) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> {
+ logi("onImsConfigurationChanged");
+ for (StateCallback c : mStateCallbacks) {
+ c.onImsConfigurationChanged(registeredSipConfig);
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void onDestroyed(int reason) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> notifySipDelegateDestroyed(reason));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ };
+
+ private final ISipTransport mSipTransport;
+ private final DelegateRequest mRequestedConfig;
+
+ private ISipDelegate mDelegateBinder;
+ private BiConsumer<ISipDelegate, Set<FeatureTagState>> mPendingCreatedConsumer;
+ private Consumer<Integer> mPendingDestroyedConsumer;
+
+ /**
+ * Create a new Connection object to manage the creation and destruction of a
+ * {@link SipDelegate}.
+ * @param subId The subid that this SipDelegate is being created for.
+ * @param sipTransport The SipTransport implementation that will be used to manage SipDelegates.
+ * @param requestedConfig The DelegateRequest to be sent to the ImsService.
+ * @param transportDeniedTags The feature tags that have already been denied by the
+ * SipTransportController and should not be requested.
+ * @param executor The Executor that all binder calls from the remote process will be executed
+ * on.
+ * @param stateCallbacks A list of callbacks that will each be called when the state of the
+ * SipDelegate changes. This will be called on the supplied executor.
+ */
+ public SipDelegateBinderConnection(int subId, ISipTransport sipTransport,
+ DelegateRequest requestedConfig, Set<FeatureTagState> transportDeniedTags,
+ Executor executor, List<StateCallback> stateCallbacks) {
+ mSubId = subId;
+ mSipTransport = sipTransport;
+ mRequestedConfig = requestedConfig;
+ mDeniedTags = transportDeniedTags;
+ mExecutor = executor;
+ mStateCallbacks = stateCallbacks;
+ }
+
+ @Override
+ public boolean create(ISipDelegateMessageCallback cb,
+ BiConsumer<ISipDelegate, Set<FeatureTagState>> createdConsumer) {
+ try {
+ mSipTransport.createSipDelegate(mSubId, mRequestedConfig, mSipDelegateStateCallback,
+ cb);
+ mSipTransport.asBinder().linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ logw("create called on unreachable SipTransport:" + e);
+ return false;
+ }
+ mPendingCreatedConsumer = createdConsumer;
+ return true;
+ }
+
+ @Override
+ public void destroy(int reason, Consumer<Integer> destroyedConsumer) {
+ mPendingDestroyedConsumer = destroyedConsumer;
+ try {
+ if (mDelegateBinder != null) {
+ mSipTransport.destroySipDelegate(mDelegateBinder, reason);
+ } else {
+ mExecutor.execute(() -> notifySipDelegateDestroyed(reason));
+ }
+ mStateCallbacks.clear();
+ } catch (RemoteException e) {
+ logw("destroy called on unreachable SipTransport:" + e);
+ mExecutor.execute(() -> notifySipDelegateDestroyed(reason));
+ }
+ try {
+ mSipTransport.asBinder().unlinkToDeath(this, 0);
+ } catch (NoSuchElementException e) {
+ logw("unlinkToDeath called on already unlinked binder" + e);
+ }
+ }
+
+ private void notifySipDelegateCreated(ISipDelegate delegate,
+ List<FeatureTagState> deniedFeatureTags) {
+ logi("Delegate Created: " + delegate + ", deniedTags:" + deniedFeatureTags);
+ if (delegate == null) {
+ logw("Invalid null delegate returned!");
+ }
+ mDelegateBinder = delegate;
+ // Add denied feature tags from SipDelegate to the ones denied by the transport
+ if (deniedFeatureTags != null) {
+ mDeniedTags.addAll(deniedFeatureTags);
+ }
+ if (mPendingCreatedConsumer == null) return;
+ mPendingCreatedConsumer.accept(delegate, mDeniedTags);
+ mPendingCreatedConsumer = null;
+ }
+
+ private void notifySipDelegateDestroyed(int reason) {
+ logi("Delegate Destroyed, reason: " + reason);
+ mDelegateBinder = null;
+ if (mPendingDestroyedConsumer == null) return;
+ mPendingDestroyedConsumer.accept(reason);
+ mPendingDestroyedConsumer = null;
+ }
+
+ /** Dump state about this binder connection that should be included in the dumpsys. */
+ public void dump(PrintWriter printWriter) {
+ mLocalLog.dump(printWriter);
+ }
+
+ protected final void logi(String log) {
+ Log.i(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
+ mLocalLog.log("[I] " + log);
+ }
+
+ protected final void logw(String log) {
+ Log.w(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
+ mLocalLog.log("[W] " + log);
+ }
+
+ @Override
+ public void binderDied() {
+ mExecutor.execute(() -> {
+ logw("binderDied!");
+ // Unblock any pending create/destroy operations.
+ // SipTransportController will handle the overall destruction/teardown.
+ notifySipDelegateCreated(null, Collections.emptyList());
+ notifySipDelegateDestroyed(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD);
+ });
+ }
+}
diff --git a/src/com/android/services/telephony/rcs/SipDelegateBinderConnectionStub.java b/src/com/android/services/telephony/rcs/SipDelegateBinderConnectionStub.java
new file mode 100644
index 0000000..888af94
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/SipDelegateBinderConnectionStub.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 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.services.telephony.rcs;
+
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.stub.SipDelegate;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+/**
+ * Stub implementation used when a SipDelegate needs to be set up in specific cases, but there
+ * is no underlying implementation in the ImsService.
+ *
+ * This is used in cases where all of the requested feature tags were denied for various reasons
+ * from the SipTransportController. In this case, we will "connect", send a update to include the
+ * denied feature tags, and then do nothing until this stub is torn down.
+ */
+public class SipDelegateBinderConnectionStub implements DelegateBinderStateManager {
+ protected final Set<FeatureTagState> mDeniedTags;
+ protected final Executor mExecutor;
+ protected final List<StateCallback> mStateCallbacks;
+
+ /**
+ * Create a new Connection object to manage the creation and destruction of a
+ * {@link SipDelegate}.
+ * @param transportDeniedTags The feature tags that have already been denied by the
+ * SipTransportController and should not be requested.
+ * @param executor The Executor that all binder calls from the remote process will be executed
+ * on.
+ * @param stateCallbacks A list of callbacks that will each be called when the state of the
+ * SipDelegate changes. This will be called on the supplied executor.
+ */
+ public SipDelegateBinderConnectionStub(Set<FeatureTagState> transportDeniedTags,
+ Executor executor, List<StateCallback> stateCallbacks) {
+ mDeniedTags = transportDeniedTags;
+ mExecutor = executor;
+ mStateCallbacks = stateCallbacks;
+ }
+
+ @Override
+ public boolean create(ISipDelegateMessageCallback cb,
+ BiConsumer<ISipDelegate, Set<FeatureTagState>> createdConsumer) {
+ mExecutor.execute(() -> {
+ createdConsumer.accept(null, (mDeniedTags));
+ for (SipDelegateBinderConnection.StateCallback c: mStateCallbacks) {
+ c.onRegistrationStateChanged(new DelegateRegistrationState.Builder().build());
+ }
+ });
+ return true;
+ }
+
+ @Override
+ public void destroy(int reason, Consumer<Integer> destroyedConsumer) {
+ mExecutor.execute(() -> {
+ mStateCallbacks.clear();
+ destroyedConsumer.accept(reason);
+ });
+ }
+}
diff --git a/src/com/android/services/telephony/rcs/SipDelegateController.java b/src/com/android/services/telephony/rcs/SipDelegateController.java
new file mode 100644
index 0000000..ed50778
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/SipDelegateController.java
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2020 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.services.telephony.rcs;
+
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateConnection;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.aidl.ISipTransport;
+import android.telephony.ims.stub.DelegateConnectionStateCallback;
+import android.telephony.ims.stub.SipDelegate;
+import android.util.LocalLog;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ScheduledExecutorService;
+
+/**
+ * Created when an IMS application wishes to open up a {@link SipDelegateConnection} and manages the
+ * resulting {@link SipDelegate} that may be created on the ImsService side.
+ */
+public class SipDelegateController {
+ static final String LOG_TAG = "SipDelegateC";
+
+ private DelegateBinderStateManager.Factory mBinderConnectionFactory =
+ new DelegateBinderStateManager.Factory() {
+ @Override
+ public DelegateBinderStateManager create(int subId, ISipTransport sipTransport,
+ DelegateRequest requestedConfig, Set<FeatureTagState> transportDeniedTags,
+ Executor executor, List<DelegateBinderStateManager.StateCallback> stateCallbacks) {
+ // We should not actually create a SipDelegate in this case.
+ if (requestedConfig.getFeatureTags().isEmpty()) {
+ return new SipDelegateBinderConnectionStub(transportDeniedTags, executor,
+ stateCallbacks);
+ }
+ return new SipDelegateBinderConnection(mSubId, mSipTransportImpl, requestedConfig,
+ transportDeniedTags, mExecutorService, stateCallbacks);
+ }
+ };
+
+ private final int mSubId;
+ private final String mPackageName;
+ private final DelegateRequest mInitialRequest;
+ private final ISipTransport mSipTransportImpl;
+ private final ScheduledExecutorService mExecutorService;
+ private final MessageTransportStateTracker mMessageTransportStateTracker;
+ private final DelegateStateTracker mDelegateStateTracker;
+ private final LocalLog mLocalLog = new LocalLog(SipTransportController.LOG_SIZE);
+
+ private DelegateBinderStateManager mBinderConnection;
+ private Set<String> mTrackedFeatureTags;
+
+ public SipDelegateController(int subId, DelegateRequest initialRequest, String packageName,
+ ISipTransport sipTransportImpl, ScheduledExecutorService executorService,
+ ISipDelegateConnectionStateCallback stateCallback,
+ ISipDelegateMessageCallback messageCallback) {
+ mSubId = subId;
+ mPackageName = packageName;
+ mInitialRequest = initialRequest;
+ mSipTransportImpl = sipTransportImpl;
+ mExecutorService = executorService;
+
+ mMessageTransportStateTracker = new MessageTransportStateTracker(mSubId, executorService,
+ messageCallback);
+ mDelegateStateTracker = new DelegateStateTracker(mSubId, stateCallback,
+ mMessageTransportStateTracker.getDelegateConnection());
+ }
+
+ /**
+ * Inject dependencies for testing only.
+ */
+ @VisibleForTesting
+ public SipDelegateController(int subId, DelegateRequest initialRequest, String packageName,
+ ISipTransport sipTransportImpl, ScheduledExecutorService executorService,
+ MessageTransportStateTracker messageTransportStateTracker,
+ DelegateStateTracker delegateStateTracker,
+ DelegateBinderStateManager.Factory connectionFactory) {
+ mSubId = subId;
+ mInitialRequest = initialRequest;
+ mPackageName = packageName;
+ mSipTransportImpl = sipTransportImpl;
+ mExecutorService = executorService;
+ mMessageTransportStateTracker = messageTransportStateTracker;
+ mDelegateStateTracker = delegateStateTracker;
+ mBinderConnectionFactory = connectionFactory;
+ }
+
+ /**
+ * @return The InitialRequest from the IMS application. The feature tags that are actually set
+ * up may differ from this request based on the state of this controller.
+ */
+ public DelegateRequest getInitialRequest() {
+ return mInitialRequest;
+ }
+
+ /**
+ * @return The package name of the IMS application associated with this SipDelegateController.
+ */
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ public ISipDelegate getSipDelegateInterface() {
+ return mMessageTransportStateTracker.getDelegateConnection();
+ }
+
+ /**
+ * Create the underlying SipDelegate.
+ * <p>
+ * This may not happen instantly, The CompletableFuture returned will not complete until
+ * {@link DelegateConnectionStateCallback#onCreated(SipDelegateConnection)} is called by the
+ * SipDelegate or DelegateStateTracker state is updated in the case that all requested features
+ * were denied.
+ * @return A CompletableFuture that will complete once the SipDelegate has been created. If true
+ * is returned, the SipDelegate has been created successfully. If false, the ImsService is not
+ * reachable and the process should be aborted.
+ */
+ public CompletableFuture<Boolean> create(Set<String> supportedSet,
+ Set<FeatureTagState> deniedSet) {
+ logi("create, supported: " + supportedSet + ", denied: " + deniedSet);
+ mTrackedFeatureTags = supportedSet;
+ DelegateBinderStateManager connection =
+ createBinderConnection(supportedSet, deniedSet);
+ CompletableFuture<Pair<ISipDelegate, Set<FeatureTagState>>> pendingCreate =
+ createSipDelegate(connection);
+ // May need to implement special case handling where SipDelegate denies all in supportedSet,
+ // however that should be a very rare case. For now, if that happens, just keep the
+ // SipDelegate bound.
+ // use thenApply here because we need this to happen on the same thread that it was called
+ // on in order to ensure ordering of onCreated being called, followed by registration
+ // state changed. If not, this is subject to race conditions where registered is queued
+ // before the async processing of this future.
+ return pendingCreate.thenApply((resultPair) -> {
+ if (resultPair == null) {
+ logw("create: resultPair returned null");
+ return false;
+ }
+ mBinderConnection = connection;
+ logi("create: created, delegate denied: " + resultPair.second);
+ mMessageTransportStateTracker.openTransport(resultPair.first, resultPair.second);
+ mDelegateStateTracker.sipDelegateConnected(resultPair.second);
+ return true;
+ });
+ }
+
+ /**
+ * Modify the SipTransport to reflect the new Feature Tag set that the IMS application has
+ * access to.
+ * <p>
+ * This involves the following operations if the new supported tag set does not match the
+ * the existing set:
+ * 1) destroy the existing underlying SipDelegate. If there are SIP Dialogs that are active
+ * on the SipDelegate that is pending to be destroyed, we must move the feature tags into a
+ * deregistering state via
+ * {@link DelegateRegistrationState#DEREGISTERING_REASON_FEATURE_TAGS_CHANGING} to signal to the
+ * IMS application to close all dialogs before the operation can proceed. If any outgoing
+ * out-of-dialog messages are sent at this time, they will also fail with reason
+ * {@link SipDelegateManager#MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION}.
+ * 2) create a new underlying SipDelegate and notify trackers, allowing the transport to
+ * re-open.
+ * @param newSupportedSet The new supported set of feature tags that the SipDelegate should
+ * be opened for.
+ * @param deniedSet The new set of tags that have been denied as well as the reason for the
+ * denial to be reported back to the IMS Application.
+ * @return A CompletableFuture containing the pending operation that will change the supported
+ * feature tags. Any operations to change the supported feature tags of the associated
+ * SipDelegate after this should not happen until this pending operation completes. Will
+ * complete with {@code true} if the operation was successful or {@code false} if the
+ * IMS service was unreachable.
+ */
+ public CompletableFuture<Boolean> changeSupportedFeatureTags(Set<String> newSupportedSet,
+ Set<FeatureTagState> deniedSet) {
+ logi("Received feature tag set change, old: [" + mTrackedFeatureTags + "], new: "
+ + newSupportedSet + ",denied: [" + deniedSet + "]");
+ if (mTrackedFeatureTags != null && mTrackedFeatureTags.equals(newSupportedSet)) {
+ logi("changeSupportedFeatureTags: no change, returning");
+ return CompletableFuture.completedFuture(true);
+ }
+
+ mTrackedFeatureTags = newSupportedSet;
+ // Next perform the destroy operation.
+ CompletableFuture<Integer> pendingDestroy = destroySipDelegate(false/*force*/,
+ SipDelegateManager.MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION,
+ SipDelegateManager.MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION,
+ DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+
+ // Next perform the create operation with the new set of supported feature tags.
+ return pendingDestroy.thenComposeAsync((reasonFromService) -> {
+ logi("changeSupportedFeatureTags: destroy stage complete, reason reported: "
+ + reasonFromService);
+ return create(newSupportedSet, deniedSet);
+ }, mExecutorService);
+ }
+
+ /**
+ * Destroy this SipDelegate. This controller should be disposed of after this method is
+ * called.
+ * <p>
+ * This may not happen instantly if there are SIP Dialogs that are active on this SipDelegate.
+ * In this case, the CompletableFuture will not complete until
+ * {@link DelegateConnectionStateCallback#onDestroyed(int)} is called by the SipDelegate.
+ * @param force If set true, we will close the transport immediately and call
+ * {@link SipDelegate#closeDialog(String)} on any open dialogs. If false, we will wait for the
+ * SIP Dialogs to close or the close timer to timeout before destroying the underlying
+ * SipDelegate.
+ * @param destroyReason The reason for why this SipDelegate is being destroyed.
+ * @return A CompletableFuture that will complete once the SipDelegate has been destroyed.
+ */
+ public CompletableFuture<Integer> destroy(boolean force, int destroyReason) {
+ logi("destroy, forced " + force + ", destroyReason: " + destroyReason);
+
+ CompletableFuture<Integer> pendingOperationComplete =
+ destroySipDelegate(force, SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED,
+ getMessageFailReasonFromDestroyReason(destroyReason),
+ DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING,
+ destroyReason);
+ return pendingOperationComplete.thenApplyAsync((reasonFromDelegate) -> {
+ logi("destroy, operation complete, notifying trackers, reason" + reasonFromDelegate);
+ mDelegateStateTracker.sipDelegateDestroyed(reasonFromDelegate);
+ return reasonFromDelegate;
+ }, mExecutorService);
+ };
+
+ private static int getMessageFailReasonFromDestroyReason(int destroyReason) {
+ switch (destroyReason) {
+ case SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD:
+ return SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD;
+ case SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP:
+ case SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_USER_DISABLED_RCS:
+ return SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED;
+ default:
+ return SipDelegateManager.MESSAGE_FAILURE_REASON_UNKNOWN;
+ }
+ }
+
+ /**
+ * @param force If set true, we will close the transport immediately and call
+ * {@link SipDelegate#closeDialog(String)} on any open dialogs. If false, we will wait for the
+ * SIP Dialogs to close or the close timer to timeout before destroying the underlying
+ * SipDelegate.
+ * @param messageDestroyingReason The reason to send back to the IMS application in the case
+ * that a new outgoing SIP message is sent that is out-of-dialog while the message
+ * transport is closing.
+ * @param messageDestroyedReason The reason to send back to the IMS application in the case
+ * that a new outgoing SIP message is sent once the underlying transport is closed.
+ * @param deregisteringReason The deregistering state reported to the IMS application for all
+ * registered feature tags.
+ * @param delegateDestroyedReason The reason to send to the underlying SipDelegate that is being
+ * destroyed.
+ * @return A CompletableFuture containing the reason from the SipDelegate for why it was
+ * destroyed.
+ */
+ private CompletableFuture<Integer> destroySipDelegate(boolean force,
+ int messageDestroyingReason, int messageDestroyedReason, int deregisteringReason,
+ int delegateDestroyedReason) {
+ if (mBinderConnection == null) {
+ logi("destroySipDelegate, called when binder connection is already null");
+ return CompletableFuture.completedFuture(delegateDestroyedReason);
+ }
+ // First, bring down the message transport.
+ CompletableFuture<Boolean> pendingTransportClosed = new CompletableFuture<>();
+ if (force) {
+ logi("destroySipDelegate, forced");
+ mMessageTransportStateTracker.close(messageDestroyedReason);
+ pendingTransportClosed.complete(true);
+ } else {
+ mMessageTransportStateTracker.closeGracefully(messageDestroyingReason,
+ messageDestroyedReason, pendingTransportClosed::complete);
+ }
+
+ // Do not send an intermediate pending state to app if there are no open SIP dialogs to
+ // worry about.
+ if (!pendingTransportClosed.isDone()) {
+ mDelegateStateTracker.sipDelegateChanging(deregisteringReason);
+ } else {
+ logi("destroySipDelegate, skip DEREGISTERING_REASON_DESTROY_PENDING");
+ }
+
+ // Next, destroy the SipDelegate.
+ return pendingTransportClosed.thenComposeAsync((wasGraceful) -> {
+ logi("destroySipDelegate, transport gracefully closed = " + wasGraceful);
+ CompletableFuture<Integer> pendingDestroy = new CompletableFuture<>();
+ mBinderConnection.destroy(delegateDestroyedReason, pendingDestroy::complete);
+ return pendingDestroy;
+ }, mExecutorService);
+ }
+
+ /**
+ * @return a CompletableFuture that returns a Pair containing SipDelegate Binder interface as
+ * well as rejected feature tags or a {@code null} Pair instance if the ImsService is not
+ * available.
+ */
+ private CompletableFuture<Pair<ISipDelegate, Set<FeatureTagState>>> createSipDelegate(
+ DelegateBinderStateManager connection) {
+ CompletableFuture<Pair<ISipDelegate, Set<FeatureTagState>>> createdFuture =
+ new CompletableFuture<>();
+ boolean isStarted = connection.create(mMessageTransportStateTracker.getMessageCallback(),
+ (delegate, delegateDeniedTags) ->
+ createdFuture.complete(new Pair<>(delegate, delegateDeniedTags)));
+ if (!isStarted) {
+ logw("Couldn't create binder connection, ImsService is not available.");
+ connection.destroy(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD, null);
+ return CompletableFuture.completedFuture(null);
+ }
+ return createdFuture;
+ }
+
+ private DelegateBinderStateManager createBinderConnection(Set<String> supportedSet,
+ Set<FeatureTagState> deniedSet) {
+
+ List<DelegateBinderStateManager.StateCallback> stateCallbacks = new ArrayList<>(2);
+ stateCallbacks.add(mDelegateStateTracker);
+ stateCallbacks.add(mMessageTransportStateTracker);
+
+ return mBinderConnectionFactory.create(mSubId, mSipTransportImpl,
+ new DelegateRequest(supportedSet), deniedSet, mExecutorService, stateCallbacks);
+ }
+
+ /**
+ * Write the current state of this controller in String format using the PrintWriter provided
+ * for dumpsys.
+ */
+ public void dump(PrintWriter printWriter) {
+ IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " ");
+ pw.println("SipDelegateController" + "[" + mSubId + "]:");
+ pw.increaseIndent();
+ pw.println("DelegateStateTracker:");
+ pw.increaseIndent();
+ mDelegateStateTracker.dump(printWriter);
+ pw.decreaseIndent();
+ pw.println("MessageStateTracker:");
+ pw.increaseIndent();
+ mMessageTransportStateTracker.dump(printWriter);
+ pw.decreaseIndent();
+ pw.decreaseIndent();
+ }
+
+ private void logi(String log) {
+ Log.w(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
+ mLocalLog.log("[I] " + log);
+ }
+
+ private void logw(String log) {
+ Log.w(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
+ mLocalLog.log("[W] " + log);
+ }
+}
diff --git a/src/com/android/services/telephony/rcs/SipTransportController.java b/src/com/android/services/telephony/rcs/SipTransportController.java
new file mode 100644
index 0000000..5d817ba
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/SipTransportController.java
@@ -0,0 +1,889 @@
+/*
+ * Copyright (C) 2020 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.services.telephony.rcs;
+
+import android.app.role.OnRoleHoldersChangedListener;
+import android.app.role.RoleManager;
+import android.content.Context;
+import android.os.UserHandle;
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.ImsService;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.aidl.ISipTransport;
+import android.telephony.ims.stub.DelegateConnectionMessageCallback;
+import android.telephony.ims.stub.DelegateConnectionStateCallback;
+import android.telephony.ims.stub.SipDelegate;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.util.LocalLog;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.android.ims.RcsFeatureManager;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+
+import com.google.common.base.Objects;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+/**
+ * Manages the creation and destruction of SipDelegates in response to an IMS application requesting
+ * a SipDelegateConnection registered to one or more IMS feature tags.
+ * <p>
+ * This allows an IMS application to forward traffic related to those feature tags over the existing
+ * IMS registration managed by the {@link ImsService} associated with this cellular subscription
+ * instead of requiring that the IMS application manage its own IMS registration over-the-top. This
+ * is required for some cellular carriers, which mandate that all IMS SIP traffic must be sent
+ * through a single IMS registration managed by the system IMS service.
+ *
+ * //TODO: Support other roles besides SMS
+ * //TODO: Bring in carrier provisioning to influence features that can be created.
+ * //TODO: Generate registration change events.
+ */
+public class SipTransportController implements RcsFeatureController.Feature,
+ OnRoleHoldersChangedListener {
+ static final int LOG_SIZE = 50;
+ static final String LOG_TAG = "SipTransportC";
+
+ /**See {@link TimerAdapter#getReevaluateThrottleTimerMilliseconds()}.*/
+ private static final int REEVALUATE_THROTTLE_DEFAULT_MS = 1000;
+ /**See {@link TimerAdapter#getUpdateRegistrationDelayMilliseconds()}.*/
+ private static final int TRIGGER_UPDATE_REGISTRATION_DELAY_DEFAULT_MS = 1000;
+
+ /**
+ * {@link RoleManager} is final so we have to wrap the implementation for testing.
+ */
+ @VisibleForTesting
+ public interface RoleManagerAdapter {
+ /** See {@link RoleManager#getRoleHolders(String)} */
+ List<String> getRoleHolders(String roleName);
+ /** See {@link RoleManager#addOnRoleHoldersChangedListenerAsUser} */
+ void addOnRoleHoldersChangedListenerAsUser(Executor executor,
+ OnRoleHoldersChangedListener listener, UserHandle user);
+ /** See {@link RoleManager#removeOnRoleHoldersChangedListenerAsUser} */
+ void removeOnRoleHoldersChangedListenerAsUser(OnRoleHoldersChangedListener listener,
+ UserHandle user);
+ }
+
+ /**
+ * Adapter for timers related to this class so they can be modified during testing.
+ */
+ @VisibleForTesting
+ public interface TimerAdapter {
+ /**
+ * Time we will delay after a {@link #createSipDelegate} or {@link #destroySipDelegate}
+ * command to re-evaluate and apply any changes to the list of tracked
+ * SipDelegateControllers.
+ * <p>
+ * Another create/destroy request sent during this time will not postpone re-evaluation
+ * again.
+ */
+ int getReevaluateThrottleTimerMilliseconds();
+
+ /**
+ * Time after re-evaluate we will wait to trigger the update of IMS registration.
+ * <p>
+ * Another re-evaluate while waiting to trigger a registration update will cause this
+ * controller to cancel and reschedule the event again, further delaying the trigger to send
+ * a registration update.
+ */
+ int getUpdateRegistrationDelayMilliseconds();
+ }
+
+ private static class TimerAdapterImpl implements TimerAdapter {
+
+ @Override
+ public int getReevaluateThrottleTimerMilliseconds() {
+ return REEVALUATE_THROTTLE_DEFAULT_MS;
+ }
+
+ @Override
+ public int getUpdateRegistrationDelayMilliseconds() {
+ return TRIGGER_UPDATE_REGISTRATION_DELAY_DEFAULT_MS;
+ }
+ }
+
+ private static class RoleManagerAdapterImpl implements RoleManagerAdapter {
+
+ private final RoleManager mRoleManager;
+
+ private RoleManagerAdapterImpl(Context context) {
+ mRoleManager = context.getSystemService(RoleManager.class);
+ }
+
+ @Override
+ public List<String> getRoleHolders(String roleName) {
+ return mRoleManager.getRoleHolders(roleName);
+ }
+
+ @Override
+ public void addOnRoleHoldersChangedListenerAsUser(Executor executor,
+ OnRoleHoldersChangedListener listener, UserHandle user) {
+ mRoleManager.addOnRoleHoldersChangedListenerAsUser(executor, listener, user);
+ }
+
+ @Override
+ public void removeOnRoleHoldersChangedListenerAsUser(OnRoleHoldersChangedListener listener,
+ UserHandle user) {
+ mRoleManager.removeOnRoleHoldersChangedListenerAsUser(listener, user);
+ }
+ }
+
+ /**
+ * Used in {@link #destroySipDelegate(int, ISipDelegate, int)} to store pending destroy
+ * requests.
+ */
+ private static final class DestroyRequest {
+ public final SipDelegateController controller;
+ public final int reason;
+
+ DestroyRequest(SipDelegateController c, int r) {
+ controller = c;
+ reason = r;
+ }
+
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ DestroyRequest that = (DestroyRequest) o;
+ return reason == that.reason
+ && controller.equals(that.controller);
+ }
+
+ @Override
+ public int hashCode() {
+ return java.util.Objects.hash(controller, reason);
+ }
+
+ @Override
+ public String toString() {
+ return "DestroyRequest{" + "controller=" + controller + ", reason=" + reason + '}';
+ }
+ }
+
+ /**
+ * Allow the ability for tests to easily mock out the SipDelegateController for testing.
+ */
+ @VisibleForTesting
+ public interface SipDelegateControllerFactory {
+ /** See {@link SipDelegateController} */
+ SipDelegateController create(int subId, DelegateRequest initialRequest, String packageName,
+ ISipTransport sipTransportImpl, ScheduledExecutorService executorService,
+ ISipDelegateConnectionStateCallback stateCallback,
+ ISipDelegateMessageCallback messageCallback);
+ }
+
+ private SipDelegateControllerFactory mDelegateControllerFactory = SipDelegateController::new;
+ private final int mSlotId;
+ private final ScheduledExecutorService mExecutorService;
+ private final RoleManagerAdapter mRoleManagerAdapter;
+ private final TimerAdapter mTimerAdapter;
+ private final LocalLog mLocalLog = new LocalLog(LOG_SIZE);
+
+ // A priority queue of active SipDelegateControllers, where the oldest SipDelegate gets
+ // access to the feature tag if multiple apps are allowed to request the same feature tag.
+ private final List<SipDelegateController> mDelegatePriorityQueue = new ArrayList<>();
+ // SipDelegateControllers who have been created and are pending to be added to the priority
+ // queue. Will be added into the queue in the same order as they were added here.
+ private final List<SipDelegateController> mDelegatePendingCreate = new ArrayList<>();
+ // SipDelegateControllers that are pending to be destroyed.
+ private final List<DestroyRequest> mDelegatePendingDestroy = new ArrayList<>();
+
+ // Future scheduled for operations that require the list of SipDelegateControllers to
+ // be evaluated. When the timer expires and triggers the reevaluate method, this controller
+ // will iterate through mDelegatePriorityQueue and assign Feature Tags based on role+priority.
+ private ScheduledFuture<?> mScheduledEvaluateFuture;
+ // mPendingEvaluateFTFuture creates this CompletableFuture, exposed in order to stop other
+ // evaluates from occurring while another is waiting for a result on other threads.
+ private CompletableFuture<Void> mEvaluateCompleteFuture;
+ // Future scheduled that will trigger the ImsService to update the IMS registration for the
+ // SipDelegate configuration. Will be scheduled TRIGGER_UPDATE_REGISTRATION_DELAY_MS
+ // milliseconds after a pending evaluate completes.
+ private ScheduledFuture<?> mPendingUpdateRegistrationFuture;
+ // Subscription id will change as new subscriptions are loaded on the slot.
+ private int mSubId;
+ // Will go up/down as the ImsService associated with this slotId goes up/down.
+ private RcsFeatureManager mRcsManager;
+ // Cached package name of the app that is considered the default SMS app.
+ private String mCachedSmsRolePackageName = "";
+
+ /**
+ * Create an instance of SipTransportController.
+ * @param context The Context associated with this controller.
+ * @param slotId The slot index associated with this controller.
+ * @param subId The subscription ID associated with this controller when it was first created.
+ */
+ public SipTransportController(Context context, int slotId, int subId) {
+ mSlotId = slotId;
+ mSubId = subId;
+
+ mRoleManagerAdapter = new RoleManagerAdapterImpl(context);
+ mTimerAdapter = new TimerAdapterImpl();
+ mExecutorService = Executors.newSingleThreadScheduledExecutor();
+ }
+
+ /**
+ * Constructor to inject dependencies for testing.
+ */
+ @VisibleForTesting
+ public SipTransportController(Context context, int slotId, int subId,
+ SipDelegateControllerFactory delegateFactory, RoleManagerAdapter roleManagerAdapter,
+ TimerAdapter timerAdapter, ScheduledExecutorService executor) {
+ mSlotId = slotId;
+ mSubId = subId;
+
+ mRoleManagerAdapter = roleManagerAdapter;
+ mTimerAdapter = timerAdapter;
+ mDelegateControllerFactory = delegateFactory;
+ mExecutorService = executor;
+ logi("created");
+ }
+
+ @Override
+ public void onRcsConnected(RcsFeatureManager manager) {
+ mExecutorService.submit(() -> onRcsManagerChanged(manager));
+ }
+
+ @Override
+ public void onRcsDisconnected() {
+ mExecutorService.submit(() -> onRcsManagerChanged(null));
+ }
+
+ @Override
+ public void onAssociatedSubscriptionUpdated(int subId) {
+ mExecutorService.submit(()-> onSubIdChanged(subId));
+ }
+
+ @Override
+ public void onDestroy() {
+ mExecutorService.submit(()-> {
+ // Ensure new create/destroy requests are denied.
+ mSubId = -1;
+ triggerDeregistrationEvent();
+ scheduleDestroyDelegates(
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN)
+ .thenRun(mExecutorService::shutdown);
+ });
+ }
+
+ /**
+ * Optionally create a new {@link SipDelegate} based off of the {@link DelegateRequest} given
+ * based on the state of this controller and associate it with the given callbacks.
+ * <p>
+ * Once the {@link SipDelegate} has been created,
+ * {@link ISipDelegateConnectionStateCallback#onCreated(ISipDelegate)} must be called with
+ * the AIDL instance corresponding to the remote {@link SipDelegate}.
+ * @param subId the subId associated with the request.
+ * @param request The request parameters used to create the {@link SipDelegate}.
+ * @param delegateState The {@link DelegateConnectionStateCallback} Binder connection.
+ * @param delegateMessage The {@link DelegateConnectionMessageCallback} Binder Connection
+ * @throws ImsException if the request to create the {@link SipDelegate} did not complete.
+ */
+ public void createSipDelegate(int subId, DelegateRequest request, String packageName,
+ ISipDelegateConnectionStateCallback delegateState,
+ ISipDelegateMessageCallback delegateMessage) throws ImsException {
+ logi("createSipDelegate: request= " + request + ", packageName= " + packageName);
+ CompletableFuture<ImsException> result = new CompletableFuture<>();
+ mExecutorService.submit(() -> createSipDelegateInternal(subId, request, packageName,
+ delegateState,
+ // Capture any ImsExceptions generated during the process.
+ delegateMessage, result::complete));
+ try {
+ ImsException e = result.get();
+ logi("createSipDelegate: request finished");
+ if (e != null) {
+ throw e;
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ logw("createSipDelegate: exception completing future: " + e);
+ }
+ }
+
+ /**
+ * The remote IMS application has requested the destruction of an existing {@link SipDelegate}.
+ * @param subId The subId associated with the request.
+ * @param connection The internal Binder connection associated with the {@link SipDelegate}.
+ * @param reason The reason for why the {@link SipDelegate} was destroyed.
+ */
+ public void destroySipDelegate(int subId, ISipDelegate connection, int reason) {
+ mExecutorService.execute(() -> destroySipDelegateInternal(subId, connection, reason));
+ }
+
+ /**
+ * @return Whether or not SipTransports are supported on the connected ImsService. This can
+ * change based on the capabilities of the ImsService.
+ * @throws ImsException if the ImsService connected to this controller is currently down.
+ */
+ public boolean isSupported(int subId) throws ImsException {
+ Boolean result = waitForMethodToComplete(() -> isSupportedInternal(subId));
+ if (result == null) {
+ logw("isSupported, unexpected null result, returning false");
+ return false;
+ }
+ return result;
+ }
+
+ private void createSipDelegateInternal(int subId, DelegateRequest request, String packageName,
+ ISipDelegateConnectionStateCallback delegateState,
+ ISipDelegateMessageCallback delegateMessage,
+ Consumer<ImsException> startedErrorConsumer) {
+ ISipTransport transport;
+ // Send back any errors via Consumer early in creation process if it is clear that the
+ // SipDelegate will never be created.
+ try {
+ checkStateOfController(subId);
+ transport = mRcsManager.getSipTransport();
+ if (transport == null) {
+ logw("createSipDelegateInternal, transport null during request.");
+ startedErrorConsumer.accept(new ImsException("SipTransport not supported",
+ ImsException.CODE_ERROR_UNSUPPORTED_OPERATION));
+ return;
+ } else {
+ // Release the binder thread as there were no issues processing the initial request.
+ startedErrorConsumer.accept(null);
+ }
+ } catch (ImsException e) {
+ logw("createSipDelegateInternal, ImsException during create: " + e);
+ startedErrorConsumer.accept(e);
+ return;
+ }
+
+ SipDelegateController c = mDelegateControllerFactory.create(subId, request, packageName,
+ transport, mExecutorService, delegateState, delegateMessage);
+ logi("createSipDelegateInternal: request= " + request + ", packageName= " + packageName
+ + ", controller created: " + c);
+ addPendingCreateAndEvaluate(c);
+ }
+
+ private void destroySipDelegateInternal(int subId, ISipDelegate connection, int reason) {
+ if (subId != mSubId) {
+ logw("destroySipDelegateInternal: ignoring destroy, as this is about to be destroyed "
+ + "anyway due to subId change, delegate=" + connection);
+ return;
+ }
+ if (connection == null) {
+ logw("destroySipDelegateInternal: ignoring destroy, null connection binder.");
+ return;
+ }
+ SipDelegateController match = null;
+ for (SipDelegateController controller : mDelegatePriorityQueue) {
+ if (Objects.equal(connection.asBinder(),
+ controller.getSipDelegateInterface().asBinder())) {
+ match = controller;
+ break;
+ }
+ }
+ if (match == null) {
+ logw("destroySipDelegateInternal: could not find matching connection=" + connection);
+ return;
+ }
+
+ logi("destroySipDelegateInternal: destroy queued for connection= " + connection);
+ addPendingDestroyAndEvaluate(match, reason);
+ }
+
+ /**
+ * Cancel pending update IMS registration events if they exist and instead send a deregister
+ * event.
+ */
+ private void triggerDeregistrationEvent() {
+ if (mPendingUpdateRegistrationFuture != null
+ && !mPendingUpdateRegistrationFuture.isDone()) {
+ // Cancel pending update and replace with a call to deregister now.
+ mPendingUpdateRegistrationFuture.cancel(false);
+ logi("triggerDeregistrationEvent: cancelling existing reg update event: "
+ + mPendingUpdateRegistrationFuture);
+ }
+ logi("triggerDeregistrationEvent: Sending deregister event to ImsService");
+ //TODO hook up registration apis
+ }
+
+ /**
+ * Schedule an update to the IMS registration. If there is an existing update scheduled, cancel
+ * it and reschedule.
+ */
+ private void scheduleUpdateRegistration() {
+ if (mPendingUpdateRegistrationFuture != null
+ && !mPendingUpdateRegistrationFuture.isDone()) {
+ // Cancel the old pending operation and reschedule again.
+ mPendingUpdateRegistrationFuture.cancel(false);
+ logi("scheduleUpdateRegistration: cancelling existing reg update event: "
+ + mPendingUpdateRegistrationFuture);
+ }
+ ScheduledFuture<?> f = mExecutorService.schedule(this::triggerUpdateRegistrationEvent,
+ mTimerAdapter.getUpdateRegistrationDelayMilliseconds(), TimeUnit.MILLISECONDS);
+ logi("scheduleUpdateRegistration: scheduling new event: " + f);
+ mPendingUpdateRegistrationFuture = f;
+ }
+
+ private void triggerUpdateRegistrationEvent() {
+ logi("triggerUpdateRegistrationEvent: Sending update registration event to ImsService");
+ //TODO hook up registration apis
+ }
+
+ /**
+ * Returns whether or not the ImsService implementation associated with the supplied subId
+ * supports the SipTransport APIs.
+ * <p>
+ * This should only be called on the ExecutorService.
+ * @return true if SipTransport is supported on this subscription, false otherwise.
+ * @throws ImsException thrown if there was an error determining the state of the ImsService.
+ */
+ private boolean isSupportedInternal(int subId) throws ImsException {
+ checkStateOfController(subId);
+ return (mRcsManager.getSipTransport() != null);
+ }
+
+ private boolean addPendingDestroy(SipDelegateController c, int reason) {
+ DestroyRequest request = new DestroyRequest(c, reason);
+ if (!mDelegatePendingDestroy.contains(request)) {
+ return mDelegatePendingDestroy.add(request);
+ }
+ return false;
+ }
+
+ /**
+ * The supplied SipDelegateController has been destroyed and associated feature tags have been
+ * released. Trigger the re-evaluation of the priority queue with the new configuration.
+ */
+ private void addPendingDestroyAndEvaluate(SipDelegateController c, int reason) {
+ if (addPendingDestroy(c, reason)) {
+ scheduleThrottledReevaluate();
+ }
+ }
+
+ /**
+ * A new SipDelegateController has been created, add to the back of the priority queue and
+ * trigger the re-evaluation of the priority queue with the new configuration.
+ */
+ private void addPendingCreateAndEvaluate(SipDelegateController c) {
+ mDelegatePendingCreate.add(c);
+ scheduleThrottledReevaluate();
+ }
+
+ /**
+ * The priority queue has changed, which will cause a re-evaluation of the feature tags granted
+ * to each SipDelegate.
+ * <p>
+ * Note: re-evaluations are throttled to happen at a minimum to occur every
+ * REEVALUATE_THROTTLE_MS seconds. We also do not reevaluate while another reevaluate operation
+ * is in progress, so in this case, defer schedule itself.
+ */
+ private void scheduleThrottledReevaluate() {
+ if (isEvaluatePendingAndNotInProgress()) {
+ logi("scheduleThrottledReevaluate: throttling reevaluate, eval already pending: "
+ + mScheduledEvaluateFuture);
+ } else {
+ mScheduledEvaluateFuture = mExecutorService.schedule(this::reevaluateDelegates,
+ mTimerAdapter.getReevaluateThrottleTimerMilliseconds(), TimeUnit.MILLISECONDS);
+ logi("scheduleThrottledReevaluate: new reevaluate scheduled: "
+ + mScheduledEvaluateFuture);
+ }
+ }
+
+ /**
+ * @return true if there is a evaluate pending, false if there is not. If evaluate has already
+ * begun, but we are waiting for it to complete, this will also return false.
+ */
+ private boolean isEvaluatePendingAndNotInProgress() {
+ boolean isEvalScheduled = mScheduledEvaluateFuture != null
+ && !mScheduledEvaluateFuture.isDone();
+ boolean isEvalInProgress = mEvaluateCompleteFuture != null
+ && !mEvaluateCompleteFuture.isDone();
+ return isEvalScheduled && !isEvalInProgress;
+ }
+
+ /**
+ * Cancel any pending re-evaluates and perform it as soon as possible. This is done in the case
+ * where we need to do something like tear down this controller or change subId.
+ */
+ private void scheduleReevaluateNow(CompletableFuture<Void> onDoneFuture) {
+ if (isEvaluatePendingAndNotInProgress()) {
+ mScheduledEvaluateFuture.cancel(false /*interrupt*/);
+ logi("scheduleReevaluateNow: cancelling pending reevaluate: "
+ + mScheduledEvaluateFuture);
+ }
+ // we have tasks that depend on this potentially, so once the last reevaluate is done,
+ // schedule a new one right away.
+ if (mEvaluateCompleteFuture != null && !mEvaluateCompleteFuture.isDone()) {
+ mEvaluateCompleteFuture.thenRunAsync(
+ () -> scheduleReevaluateNow(onDoneFuture), mExecutorService);
+ return;
+ }
+
+ reevaluateDelegates();
+ mEvaluateCompleteFuture.thenAccept(onDoneFuture::complete);
+ }
+
+ /**
+ * Apply all operations that have been pending by collecting pending create/destroy operations
+ * and batch applying them to the mDelegatePriorityQueue.
+ *
+ * First perform the operation of destroying all SipDelegateConnections that have been pending
+ * destroy. Next, add all pending new SipDelegateControllers to the end of
+ * mDelegatePriorityQueue and loop through all in the queue, applying feature tags to the
+ * appropriate SipDelegateController if they pass role checks and have not already been claimed
+ * by another delegate higher in the priority queue.
+ */
+ private void reevaluateDelegates() {
+ if (mEvaluateCompleteFuture != null && !mEvaluateCompleteFuture.isDone()) {
+ logw("reevaluateDelegates: last evaluate not done, deferring new request");
+ // Defer re-evaluate until after the pending re-evaluate is complete.
+ mEvaluateCompleteFuture.thenRunAsync(this::scheduleThrottledReevaluate,
+ mExecutorService);
+ return;
+ }
+
+ // Destroy all pending destroy delegates first. Order doesn't matter.
+ List<CompletableFuture<Void>> pendingDestroyList = mDelegatePendingDestroy.stream()
+ .map(d -> triggerDestroy(d.controller, d.reason)).collect(
+ Collectors.toList());
+ CompletableFuture<Void> pendingDestroy = CompletableFuture.allOf(
+ pendingDestroyList.toArray(new CompletableFuture[mDelegatePendingDestroy.size()]));
+ mDelegatePriorityQueue.removeAll(mDelegatePendingDestroy.stream().map(d -> d.controller)
+ .collect(Collectors.toList()));
+ mDelegatePendingDestroy.clear();
+
+ // Add newly created SipDelegates to end of queue before evaluating associated features.
+ mDelegatePriorityQueue.addAll(mDelegatePendingCreate);
+ for (SipDelegateController c : mDelegatePendingCreate) {
+ logi("reevaluateDelegates: pending create: " + c);
+ }
+ mDelegatePendingCreate.clear();
+
+ // Wait for destroy stages to complete, then loop from oldest to most recent and associate
+ // feature tags that the app has requested to the SipDelegate.
+ // Each feature tag can only be associated with one SipDelegate, so as feature tags are
+ // taken, do not allow other SipDelegates to be associated with those tags as well. Each
+ // stage of the CompletableFuture chain passes the previously claimed feature tags into the
+ // next stage so that those feature tags can be denied if already claimed.
+ // Executor doesn't matter here, just composing here to transform to the next stage.
+ CompletableFuture<Set<String>> pendingChange = pendingDestroy.thenCompose((ignore) -> {
+ logi("reevaluateDelegates: destroy phase complete");
+ return CompletableFuture.completedFuture(new ArraySet<>());
+ });
+ final String cachedSmsRolePackage = mCachedSmsRolePackageName;
+ for (SipDelegateController c : mDelegatePriorityQueue) {
+ logi("reevaluateDelegates: pending reeval: " + c);
+ pendingChange = pendingChange.thenComposeAsync((takenTags) -> {
+ logi("reevaluateDelegates: last stage completed with result:" + takenTags);
+ if (takenTags == null) {
+ // return early, the ImsService is no longer available. This will eventually be
+ // destroyed.
+ return CompletableFuture.completedFuture(null /*failed*/);
+ }
+ return changeSupportedFeatureTags(c, cachedSmsRolePackage, takenTags);
+ }, mExecutorService);
+ }
+
+ // Executor doesn't matter here, just adding an extra stage to print result.
+ mEvaluateCompleteFuture = pendingChange
+ .thenAccept((associatedFeatures) -> logi("reevaluateDelegates: reevaluate complete,"
+ + " feature tags associated: " + associatedFeatures));
+ logi("reevaluateDelegates: future created.");
+ }
+
+ private CompletableFuture<Void> triggerDestroy(SipDelegateController c, int reason) {
+ return c.destroy(isForcedFromReason(reason), reason)
+ // Executor doesn't matter here, just for logging.
+ .thenAccept((delegateReason) -> logi("destroy triggered with " + reason
+ + " and finished with reason= " + delegateReason));
+ }
+
+ private boolean isForcedFromReason(int reason) {
+ switch (reason) {
+ case SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_UNKNOWN:
+ logw("isForcedFromReason, unknown reason");
+ /*intentional fallthrough*/
+ case SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP:
+ /*intentional fallthrough*/
+ case SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_USER_DISABLED_RCS:
+ return false;
+ case SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD:
+ /*intentional fallthrough*/
+ case SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN:
+ return true;
+ }
+ logw("isForcedFromReason, unexpected reason: " + reason);
+ return false;
+ }
+
+ /**
+ * Called by RoleManager when a role has changed so that we can query the new role holder.
+ * @param roleName the name of the role whose holders are changed
+ * @param user the user for this role holder change
+ */
+ // Called on mExecutorThread
+ @Override
+ public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
+ logi("onRoleHoldersChanged, roleName= " + roleName + ", user= " + user);
+ // Only monitor changes on the system
+ if (!UserHandle.SYSTEM.equals(user)) {
+ return;
+ }
+
+ if (!RoleManager.ROLE_SMS.equals(roleName)) {
+ logi("onRoleHoldersChanged, ignoring non SMS role change");
+ // TODO: only target default sms app for now and add new roles later using
+ // CarrierConfigManager
+ return;
+ }
+ updateRoleCache();
+ // new denied tags will be picked up when reevaluate completes.
+ scheduleThrottledReevaluate();
+ }
+
+
+ private void updateRoleCache() {
+ String newSmsRolePackageName = "";
+ try {
+ // Only one app can fulfill the SMS role.
+ newSmsRolePackageName = mRoleManagerAdapter.getRoleHolders(RoleManager.ROLE_SMS)
+ .stream().findFirst().orElse("");
+ } catch (Exception e) {
+ logi("updateRoleCache: exception=" + e);
+ }
+
+ logi("updateRoleCache: new packageName=" + newSmsRolePackageName);
+ if (TextUtils.equals(mCachedSmsRolePackageName, newSmsRolePackageName)) {
+ logi("updateRoleCache, skipping, role did not change");
+ return;
+ }
+ mCachedSmsRolePackageName = newSmsRolePackageName;
+ }
+
+ /**
+ * Check the requested roles for the specified package name and return the tags that were
+ * applied to that SipDelegateController.
+ * @param controller Controller to attribute feature tags to.
+ * @param alreadyRequestedTags The feature tags that were already granted to other SipDelegates.
+ * @return Once complete, contains the set of feature tags that the SipDelegate now has
+ * associated with it along with the feature tags that previous SipDelegates had.
+ *
+ * // TODO: we currently only track SMS role, extend to support other roles as well.
+ */
+ private CompletableFuture<Set<String>> changeSupportedFeatureTags(
+ SipDelegateController controller, String smsRolePackageName,
+ Set<String> alreadyRequestedTags) {
+ Set<String> requestedFeatureTags = controller.getInitialRequest().getFeatureTags();
+ String packageName = controller.getPackageName();
+ if (!smsRolePackageName.equals(packageName)) {
+ // Deny all tags.
+ Set<FeatureTagState> deniedTags = new ArraySet<>();
+ for (String s : requestedFeatureTags) {
+ deniedTags.add(new FeatureTagState(s,
+ SipDelegateManager.DENIED_REASON_NOT_ALLOWED));
+ }
+ CompletableFuture<Boolean> pendingDeny = controller.changeSupportedFeatureTags(
+ Collections.emptySet(), deniedTags);
+ logi("changeSupportedFeatureTags pendingDeny=" + pendingDeny);
+ // do not worry about executor used here, this stage used to interpret result + add log.
+ return pendingDeny.thenApply((completedSuccessfully) -> {
+ logi("changeSupportedFeatureTags: deny completed: " + completedSuccessfully);
+ if (!completedSuccessfully) return null;
+ // Return back the previous list of requested tags, as we did not add any more.
+ return alreadyRequestedTags;
+ });
+ }
+
+ ArraySet<String> previouslyGrantedTags = new ArraySet<>(alreadyRequestedTags);
+ // deny tags already used by other delegates
+ Set<FeatureTagState> deniedTags = new ArraySet<>();
+ for (String s : requestedFeatureTags) {
+ if (previouslyGrantedTags.contains(s)) {
+ deniedTags.add(new FeatureTagState(s,
+ SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE));
+ }
+ }
+ Set<String> nonDeniedTags = requestedFeatureTags.stream()
+ .filter(r -> !previouslyGrantedTags.contains(r))
+ .collect(Collectors.toSet());
+ // Add newly granted tags to the already requested tags list.
+ previouslyGrantedTags.addAll(nonDeniedTags);
+ CompletableFuture<Boolean> pendingChange = controller.changeSupportedFeatureTags(
+ nonDeniedTags, deniedTags);
+ logi("changeSupportedFeatureTags pendingChange=" + pendingChange);
+ // do not worry about executor used here, this stage used to interpret result + add log.
+ return pendingChange.thenApply((completedSuccessfully) -> {
+ logi("changeSupportedFeatureTags: change completed: " + completedSuccessfully);
+ if (!completedSuccessfully) return null;
+ return previouslyGrantedTags;
+ });
+ }
+
+ /**
+ * Run a Callable on the ExecutorService Thread and wait for the result.
+ * If an ImsException is thrown, catch it and rethrow it to caller.
+ */
+ private <T> T waitForMethodToComplete(Callable<T> callable) throws ImsException {
+ Future<T> r = mExecutorService.submit(callable);
+ T result;
+ try {
+ result = r.get();
+ } catch (InterruptedException e) {
+ result = null;
+ } catch (ExecutionException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof ImsException) {
+ // Rethrow the exception
+ throw (ImsException) cause;
+ }
+ logw("Unexpected Exception, returning null: " + cause);
+ result = null;
+ }
+ return result;
+ }
+
+ /**
+ * Throw an ImsException for common scenarios where the state of the controller is not ready
+ * for communication.
+ * <p>
+ * This should only be called while running on the on the ExecutorService.
+ */
+ private void checkStateOfController(int subId) throws ImsException {
+ if (mSubId != subId) {
+ // sub ID has changed while this was in the queue.
+ throw new ImsException("subId is no longer valid for this request.",
+ ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
+ }
+ if (mRcsManager == null) {
+ throw new ImsException("Connection to ImsService is not available",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+ }
+
+ private void onRcsManagerChanged(RcsFeatureManager m) {
+ logi("manager changed, " + mRcsManager + "->" + m);
+ if (mRcsManager == m) return;
+ mRcsManager = m;
+ if (mRcsManager == null) {
+ logi("onRcsManagerChanged: lost connection to ImsService, tearing down...");
+ unregisterListeners();
+ scheduleDestroyDelegates(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD);
+ } else {
+ logi("onRcsManagerChanged: registering listeners/updating role cache...");
+ registerListeners();
+ updateRoleCache();
+ }
+ }
+
+ private void registerListeners() {
+ try {
+ mRoleManagerAdapter.addOnRoleHoldersChangedListenerAsUser(mExecutorService, this,
+ UserHandle.SYSTEM);
+ } catch (Exception e) {
+ logi("registerListeners: exception=" + e);
+ }
+ }
+
+ private void unregisterListeners() {
+ mCachedSmsRolePackageName = "";
+ mRoleManagerAdapter.removeOnRoleHoldersChangedListenerAsUser(this, UserHandle.SYSTEM);
+ }
+
+ /**
+ * Called when either the sub ID associated with the slot has changed or the carrier
+ * configuration associated with the same subId has changed.
+ */
+ private void onSubIdChanged(int newSubId) {
+ logi("subId changed, " + mSubId + "->" + newSubId);
+ if (mSubId != newSubId) {
+ // Swap subId, any pending create/destroy on old subId will be denied.
+ mSubId = newSubId;
+ scheduleDestroyDelegates(
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
+ return;
+ }
+ // TODO: if subId hasn't changed this means that we should load in any new carrier configs
+ // that we care about and apply.
+ }
+
+ /**
+ * Destroy all tracked SipDelegateConnections due to the subscription being torn down.
+ * @return A CompletableFuture that will complete when all SipDelegates have been torn down.
+ */
+ private CompletableFuture<Void> scheduleDestroyDelegates(int reason) {
+ boolean addedDestroy = false;
+ for (SipDelegateController c : mDelegatePriorityQueue) {
+ logi("scheduleDestroyDelegates: Controller pending destroy: " + c);
+ addedDestroy |= addPendingDestroy(c, reason);
+ }
+ if (addedDestroy) {
+ CompletableFuture<Void> pendingDestroy = new CompletableFuture<>();
+ scheduleReevaluateNow(pendingDestroy);
+ return pendingDestroy;
+ } else {
+ return CompletableFuture.completedFuture(null);
+ }
+ }
+
+ @Override
+ public void dump(PrintWriter printWriter) {
+ IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " ");
+ pw.println("SipTransportController" + "[" + mSlotId + "->" + mSubId + "]:");
+ pw.increaseIndent();
+ pw.println("LocalLog:");
+ pw.increaseIndent();
+ mLocalLog.dump(pw);
+ pw.decreaseIndent();
+ pw.println("SipDelegateControllers (in priority order):");
+ pw.increaseIndent();
+ if (mDelegatePriorityQueue.isEmpty()) {
+ pw.println("[NONE]");
+ } else {
+ for (SipDelegateController c : mDelegatePriorityQueue) {
+ c.dump(pw);
+ }
+ }
+ pw.decreaseIndent();
+ pw.decreaseIndent();
+ }
+
+ private void logi(String log) {
+ Log.w(LOG_TAG, "[" + mSlotId + "->" + mSubId + "] " + log);
+ mLocalLog.log("[I] " + log);
+ }
+
+ private void logw(String log) {
+ Log.w(LOG_TAG, "[" + mSlotId + "->" + mSubId + "] " + log);
+ mLocalLog.log("[W] " + log);
+ }
+}
diff --git a/src/com/android/services/telephony/rcs/TelephonyRcsService.java b/src/com/android/services/telephony/rcs/TelephonyRcsService.java
index 69d8f82..941a6a8 100644
--- a/src/com/android/services/telephony/rcs/TelephonyRcsService.java
+++ b/src/com/android/services/telephony/rcs/TelephonyRcsService.java
@@ -47,21 +47,25 @@
private static final String LOG_TAG = "TelephonyRcsService";
/**
- * Used to inject RcsFeatureController and UserCapabilityExchangeImpl instances for testing.
+ * Used to inject RcsFeatureController and UceController instances for testing.
*/
@VisibleForTesting
public interface FeatureFactory {
/**
- * @return an {@link RcsFeatureController} assoicated with the slot specified.
+ * @return an {@link RcsFeatureController} associated with the slot specified.
*/
RcsFeatureController createController(Context context, int slotId);
/**
- * @return an instance of {@link UserCapabilityExchangeImpl} associated with the slot
+ * @return an instance of {@link UceControllerManager} associated with the slot specified.
+ */
+ UceControllerManager createUceControllerManager(Context context, int slotId, int subId);
+
+ /**
+ * @return an instance of {@link SipTransportController} for the slot and subscription
* specified.
*/
- UserCapabilityExchangeImpl createUserCapabilityExchange(Context context, int slotId,
- int subId);
+ SipTransportController createSipTransportController(Context context, int slotId, int subId);
}
private FeatureFactory mFeatureFactory = new FeatureFactory() {
@@ -71,9 +75,15 @@
}
@Override
- public UserCapabilityExchangeImpl createUserCapabilityExchange(Context context, int slotId,
+ public UceControllerManager createUceControllerManager(Context context, int slotId,
int subId) {
- return new UserCapabilityExchangeImpl(context, slotId, subId);
+ return new UceControllerManager(context, slotId, subId);
+ }
+
+ @Override
+ public SipTransportController createSipTransportController(Context context, int slotId,
+ int subId) {
+ return new SipTransportController(context, slotId, subId);
}
};
@@ -225,13 +235,24 @@
private void updateSupportedFeatures(RcsFeatureController c, int slotId, int subId) {
if (doesSubscriptionSupportPresence(subId)) {
- if (c.getFeature(UserCapabilityExchangeImpl.class) == null) {
- c.addFeature(mFeatureFactory.createUserCapabilityExchange(mContext, slotId, subId),
- UserCapabilityExchangeImpl.class);
+ if (c.getFeature(UceControllerManager.class) == null) {
+ c.addFeature(mFeatureFactory.createUceControllerManager(mContext, slotId, subId),
+ UceControllerManager.class);
}
} else {
- if (c.getFeature(UserCapabilityExchangeImpl.class) != null) {
- c.removeFeature(UserCapabilityExchangeImpl.class);
+ if (c.getFeature(UceControllerManager.class) != null) {
+ c.removeFeature(UceControllerManager.class);
+ }
+ }
+
+ if (doesSubscriptionSupportSingleRegistration(subId)) {
+ if (c.getFeature(SipTransportController.class) == null) {
+ c.addFeature(mFeatureFactory.createSipTransportController(mContext, slotId, subId),
+ SipTransportController.class);
+ }
+ } else {
+ if (c.getFeature(SipTransportController.class) != null) {
+ c.removeFeature(SipTransportController.class);
}
}
// Only start the connection procedure if we have active features.
@@ -250,6 +271,14 @@
return supportsUce;
}
+ private boolean doesSubscriptionSupportSingleRegistration(int subId) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) return false;
+ CarrierConfigManager carrierConfigManager =
+ mContext.getSystemService(CarrierConfigManager.class);
+ if (carrierConfigManager == null) return false;
+ return carrierConfigManager.getConfigForSubId(subId).getBoolean(
+ CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL);
+ }
private int getSubscriptionFromSlot(int slotId) {
SubscriptionManager manager = mContext.getSystemService(SubscriptionManager.class);
diff --git a/src/com/android/services/telephony/rcs/UceControllerManager.java b/src/com/android/services/telephony/rcs/UceControllerManager.java
new file mode 100644
index 0000000..d1f91d1
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/UceControllerManager.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2020 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.services.telephony.rcs;
+
+import android.content.Context;
+import android.net.Uri;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.RcsUceAdapter;
+import android.telephony.ims.RcsUceAdapter.PublishState;
+import android.telephony.ims.aidl.IRcsUceControllerCallback;
+import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
+import android.util.Log;
+
+import com.android.ims.RcsFeatureManager;
+import com.android.ims.rcs.uce.UceController;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+/**
+ * Responsible for managing the creation and destruction of UceController. It also received the
+ * requests from {@link com.android.phone.ImsRcsController} and pass these requests to
+ * {@link UceController}
+ */
+public class UceControllerManager implements RcsFeatureController.Feature {
+
+ private static final String LOG_TAG = "UceControllerManager";
+
+ private final int mSlotId;
+ private final Context mContext;
+ private final ExecutorService mExecutorService;
+
+ private volatile UceController mUceController;
+
+ public UceControllerManager(Context context, int slotId, int subId) {
+ Log.d(LOG_TAG, "create: slotId=" + slotId + ", subId=" + subId);
+
+ mSlotId = slotId;
+ mContext = context;
+ mExecutorService = Executors.newSingleThreadExecutor();
+ mUceController = new UceController(mContext, subId);
+ }
+
+ /**
+ * Constructor to inject dependencies for testing.
+ */
+ @VisibleForTesting
+ public UceControllerManager(Context context, int slotId, int subId, ExecutorService executor) {
+ mSlotId = slotId;
+ mContext = context;
+ mExecutorService = executor;
+ mUceController = new UceController(mContext, subId);
+ }
+
+ @Override
+ public void onRcsConnected(RcsFeatureManager manager) {
+ mExecutorService.submit(() -> mUceController.onRcsConnected(manager));
+ }
+
+ @Override
+ public void onRcsDisconnected() {
+ mExecutorService.submit(() -> mUceController.onRcsDisconnected());
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.d(LOG_TAG, "onDestroy");
+ mExecutorService.submit(() -> mUceController.onDestroy());
+ // When the shutdown is called, it will refuse any new tasks and let existing tasks finish.
+ mExecutorService.shutdown();
+ }
+
+ /**
+ * This method will be called when either the subscription ID associated with the slot has
+ * changed or the carrier configuration associated with the same subId has changed.
+ */
+ @Override
+ public void onAssociatedSubscriptionUpdated(int subId) {
+ mExecutorService.submit(() -> {
+ Log.i(LOG_TAG, "onAssociatedSubscriptionUpdated: slotId=" + mSlotId
+ + ", subId=" + subId);
+
+ // Destroy existing UceController and create a new one.
+ mUceController.onDestroy();
+ mUceController = new UceController(mContext, subId);
+ });
+ }
+
+ @VisibleForTesting
+ public void setUceController(UceController uceController) {
+ mUceController = uceController;
+ }
+
+ /**
+ * Request the capabilities for contacts.
+ *
+ * @param contactNumbers A list of numbers that the capabilities are being requested for.
+ * @param c A callback for when the request for capabilities completes.
+ * @throws ImsException if the ImsService connected to this controller is currently down.
+ */
+ public void requestCapabilities(List<Uri> contactNumbers, IRcsUceControllerCallback c)
+ throws ImsException {
+ Future future = mExecutorService.submit(() -> {
+ checkUceControllerState();
+ mUceController.requestCapabilities(contactNumbers, c);
+ return true;
+ });
+
+ try {
+ future.get();
+ } catch (ExecutionException | InterruptedException e) {
+ Log.w(LOG_TAG, "requestCapabilities: " + e);
+ Throwable cause = e.getCause();
+ if (cause instanceof ImsException) {
+ throw (ImsException) cause;
+ }
+ }
+ }
+
+ /**
+ * Request the capabilities for the given contact.
+ * @param contactNumber The contact of the capabilities are being requested for.
+ * @param c A callback for when the request for capabilities completes.
+ * @throws ImsException if the ImsService connected to this controller is currently down.
+ */
+ public void requestNetworkAvailability(Uri contactNumber, IRcsUceControllerCallback c)
+ throws ImsException {
+ Future future = mExecutorService.submit(() -> {
+ checkUceControllerState();
+ mUceController.requestAvailability(contactNumber, c);
+ return true;
+ });
+
+ try {
+ future.get();
+ } catch (ExecutionException | InterruptedException e) {
+ Log.w(LOG_TAG, "requestNetworkAvailability exception: " + e);
+ Throwable cause = e.getCause();
+ if (cause instanceof ImsException) {
+ throw (ImsException) cause;
+ }
+ }
+ }
+
+ /**
+ * Get the UCE publish state.
+ *
+ * @throws ImsException if the ImsService connected to this controller is currently down.
+ */
+ public @PublishState int getUcePublishState() throws ImsException {
+ Future future = mExecutorService.submit(() -> {
+ checkUceControllerState();
+ return mUceController.getUcePublishState();
+ });
+
+ try {
+ return (Integer) future.get();
+ } catch (ExecutionException | InterruptedException e) {
+ Log.w(LOG_TAG, "requestNetworkAvailability exception: " + e);
+ Throwable cause = e.getCause();
+ if (cause instanceof ImsException) {
+ throw (ImsException) cause;
+ }
+ return RcsUceAdapter.PUBLISH_STATE_OTHER_ERROR;
+ }
+ }
+
+ /**
+ * Register the Publish state changed callback.
+ *
+ * @throws ImsException if the ImsService connected to this controller is currently down.
+ */
+ public void registerPublishStateCallback(IRcsUcePublishStateCallback c) throws ImsException {
+ Future future = mExecutorService.submit(() -> {
+ checkUceControllerState();
+ mUceController.registerPublishStateCallback(c);
+ return true;
+ });
+
+ try {
+ future.get();
+ } catch (ExecutionException | InterruptedException e) {
+ Log.w(LOG_TAG, "registerPublishStateCallback exception: " + e);
+ Throwable cause = e.getCause();
+ if (cause instanceof ImsException) {
+ throw (ImsException) cause;
+ }
+ }
+ }
+
+ /**
+ * Unregister the existing publish state changed callback.
+ */
+ public void unregisterPublishStateCallback(IRcsUcePublishStateCallback c) {
+ Future future = mExecutorService.submit(() -> {
+ if (checkUceControllerState()) {
+ mUceController.unregisterPublishStateCallback(c);
+ }
+ return true;
+ });
+
+ try {
+ future.get();
+ } catch (ExecutionException | InterruptedException e) {
+ Log.w(LOG_TAG, "unregisterPublishStateCallback exception: " + e);
+ }
+ }
+
+ private boolean checkUceControllerState() throws ImsException {
+ if (mUceController == null || mUceController.isUnavailable()) {
+ throw new ImsException("UCE controller is unavailable",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+ return true;
+ }
+
+
+ @Override
+ public void dump(PrintWriter printWriter) {
+ IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " ");
+ pw.println("UceControllerManager" + "[" + mSlotId + "]:");
+ pw.increaseIndent();
+ pw.println("UceController available = " + mUceController != null);
+ //TODO: Add dump for UceController
+ pw.decreaseIndent();
+ }
+}
diff --git a/src/com/android/services/telephony/rcs/UserCapabilityExchangeImpl.java b/src/com/android/services/telephony/rcs/UserCapabilityExchangeImpl.java
deleted file mode 100644
index ee0c5be..0000000
--- a/src/com/android/services/telephony/rcs/UserCapabilityExchangeImpl.java
+++ /dev/null
@@ -1,1065 +0,0 @@
-/*
- * Copyright (C) 2020 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.services.telephony.rcs;
-
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PersistableBundle;
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
-import android.provider.Settings;
-import android.provider.Telephony;
-import android.telecom.TelecomManager;
-import android.telephony.AccessNetworkConstants;
-import android.telephony.CarrierConfigManager;
-import android.telephony.SubscriptionManager;
-import android.telephony.ims.ImsException;
-import android.telephony.ims.ImsManager;
-import android.telephony.ims.ImsMmTelManager;
-import android.telephony.ims.ImsReasonInfo;
-import android.telephony.ims.ProvisioningManager;
-import android.telephony.ims.RcsContactUceCapability;
-import android.telephony.ims.RcsUceAdapter;
-import android.telephony.ims.RegistrationManager;
-import android.telephony.ims.aidl.IRcsUceControllerCallback;
-import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
-import android.telephony.ims.feature.MmTelFeature;
-import android.telephony.ims.stub.RcsCapabilityExchange;
-import android.telephony.ims.stub.RcsPresenceExchangeImplBase;
-import android.util.Log;
-
-import com.android.ims.RcsFeatureManager;
-import com.android.ims.RcsFeatureManager.RcsFeatureCallbacks;
-import com.android.ims.ResultCode;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.phone.R;
-import com.android.service.ims.presence.ContactCapabilityResponse;
-import com.android.service.ims.presence.PresenceBase;
-import com.android.service.ims.presence.PresencePublication;
-import com.android.service.ims.presence.PresencePublisher;
-import com.android.service.ims.presence.PresenceSubscriber;
-import com.android.service.ims.presence.SubscribePublisher;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
-
-/**
- * Implements User Capability Exchange using Presence.
- */
-public class UserCapabilityExchangeImpl implements RcsFeatureController.Feature, SubscribePublisher,
- PresencePublisher {
-
- private static final String LOG_TAG = "RcsUceImpl";
-
- private final int mSlotId;
- private volatile int mSubId;
- private volatile boolean mImsContentChangedCallbackRegistered = false;
- // The result of requesting publish
- private volatile int mPublishState = PresenceBase.PUBLISH_STATE_NOT_PUBLISHED;
- // The network type which IMS registers on
- private volatile int mNetworkRegistrationType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
- // The MMTel capabilities of this subscription Id
- private MmTelFeature.MmTelCapabilities mMmTelCapabilities;
- private final Object mCapabilitiesLock = new Object();
-
- private final Context mContext;
- private final UceImplHandler mUceImplHandler;
- private RcsFeatureManager mRcsFeatureManager;
- private final PresencePublication mPresencePublication;
- private final PresenceSubscriber mPresenceSubscriber;
-
- // The task Ids of updating capabilities
- private final Set<Integer> mRequestingPublishTaskIds = new HashSet<>();
-
- // The callbacks to notify publish state changed.
- private final RemoteCallbackList<IRcsUcePublishStateCallback> mPublishStateCallbacks;
-
- // The task Ids of pending availability request.
- private final Set<Integer> mPendingAvailabilityRequests = new HashSet<>();
-
- private final ConcurrentHashMap<Integer, IRcsUceControllerCallback> mPendingCapabilityRequests =
- new ConcurrentHashMap<>();
-
- UserCapabilityExchangeImpl(Context context, int slotId, int subId) {
- mSlotId = slotId;
- mSubId = subId;
- logi("created");
-
- mContext = context;
- mPublishStateCallbacks = new RemoteCallbackList<>();
-
- HandlerThread handlerThread = new HandlerThread("UceImplHandlerThread");
- handlerThread.start();
- mUceImplHandler = new UceImplHandler(this, handlerThread.getLooper());
-
- String[] volteError = context.getResources().getStringArray(
- R.array.config_volte_provision_error_on_publish_response);
- String[] rcsError = context.getResources().getStringArray(
- R.array.config_rcs_provision_error_on_publish_response);
-
- // Initialize PresencePublication
- mPresencePublication = new PresencePublication(null /*PresencePublisher*/, context,
- volteError, rcsError);
- // Initialize PresenceSubscriber
- mPresenceSubscriber = new PresenceSubscriber(null /*SubscribePublisher*/, context,
- volteError, rcsError);
-
- onAssociatedSubscriptionUpdated(mSubId);
- registerReceivers();
- }
-
- @VisibleForTesting
- UserCapabilityExchangeImpl(Context context, int slotId, int subId, Looper looper,
- PresencePublication presencePublication, PresenceSubscriber presenceSubscriber,
- RemoteCallbackList<IRcsUcePublishStateCallback> publishStateCallbacks) {
- mSlotId = slotId;
- mSubId = subId;
- mContext = context;
- mPublishStateCallbacks = publishStateCallbacks;
- mUceImplHandler = new UceImplHandler(this, looper);
- mPresencePublication = presencePublication;
- mPresenceSubscriber = presenceSubscriber;
- onAssociatedSubscriptionUpdated(mSubId);
- registerReceivers();
- }
-
- // Runs on main thread.
- @Override
- public void onRcsConnected(RcsFeatureManager rcsFeatureManager) {
- logi("onRcsConnected");
- mRcsFeatureManager = rcsFeatureManager;
- mRcsFeatureManager.addFeatureListenerCallback(mRcsFeatureCallback);
-
- mPresencePublication.updatePresencePublisher(this);
- mPresenceSubscriber.updatePresenceSubscriber(this);
- }
-
- // Runs on main thread.
- @Override
- public void onRcsDisconnected() {
- logi("onRcsDisconnected");
- mPresencePublication.removePresencePublisher();
- mPresenceSubscriber.removePresenceSubscriber();
-
- if (mRcsFeatureManager != null) {
- mRcsFeatureManager.releaseConnection();
- mRcsFeatureManager = null;
- }
- }
-
- // Runs on main thread.
- @Override
- public void onAssociatedSubscriptionUpdated(int subId) {
- logi("onAssociatedSubscriptionUpdated: new subId=" + subId);
-
- // Listen to the IMS content changed with new subId.
- mUceImplHandler.registerImsContentChangedReceiver(subId);
-
- mSubId = subId;
- mPresencePublication.handleAssociatedSubscriptionChanged(subId);
- mPresenceSubscriber.handleAssociatedSubscriptionChanged(subId);
- }
-
- /**
- * Should be called before destroying this instance.
- * This instance is not usable after this method is called.
- */
- // Called on main thread.
- public void onDestroy() {
- logi("onDestroy");
- mUceImplHandler.getLooper().quit();
- unregisterReceivers();
- unregisterImsProvisionCallback(mSubId);
- onRcsDisconnected();
- }
-
- /**
- * @return the UCE Publish state.
- */
- // May happen on a Binder thread, PresencePublication locks to get result.
- public int getUcePublishState() {
- int publishState = mPresencePublication.getPublishState();
- return toUcePublishState(publishState);
- }
-
- @VisibleForTesting
- public UceImplHandler getHandler() {
- return mUceImplHandler;
- }
-
- /**
- * Register receiver to receive UCE publish state changed.
- */
- public void registerPublishStateCallback(IRcsUcePublishStateCallback c) {
- synchronized (mPublishStateCallbacks) {
- mPublishStateCallbacks.register(c);
- }
- }
-
- /**
- * Unregister UCE publish state callback.
- */
- public void unregisterUcePublishStateCallback(IRcsUcePublishStateCallback c) {
- synchronized (mPublishStateCallbacks) {
- mPublishStateCallbacks.unregister(c);
- }
- }
-
- private void clearPublishStateCallbacks() {
- synchronized (mPublishStateCallbacks) {
- logi("clearPublishStateCallbacks");
- final int lastIndex = mPublishStateCallbacks.getRegisteredCallbackCount() - 1;
- for (int index = lastIndex; index >= 0; index--) {
- IRcsUcePublishStateCallback callback =
- mPublishStateCallbacks.getRegisteredCallbackItem(index);
- mPublishStateCallbacks.unregister(callback);
- }
- }
- }
-
- private void notifyPublishStateChanged(@PresenceBase.PresencePublishState int state) {
- int result = toUcePublishState(state);
- synchronized (mPublishStateCallbacks) {
- mPublishStateCallbacks.broadcast(c -> {
- try {
- c.onPublishStateChanged(result);
- } catch (RemoteException e) {
- logw("notifyPublishStateChanged error: " + e);
- }
- });
- }
- }
-
- /**
- * Perform a capabilities request and call {@link IRcsUceControllerCallback} with the result.
- */
- // May happen on a Binder thread, PresenceSubscriber locks when requesting Capabilities.
- public void requestCapabilities(List<Uri> contactNumbers, IRcsUceControllerCallback c) {
- List<String> numbers = contactNumbers.stream()
- .map(UserCapabilityExchangeImpl::getNumberFromUri).collect(Collectors.toList());
- int taskId = mPresenceSubscriber.requestCapability(numbers,
- new ContactCapabilityResponse() {
- @Override
- public void onSuccess(int reqId) {
- logi("onSuccess called for reqId:" + reqId);
- }
-
- @Override
- public void onError(int reqId, int resultCode) {
- IRcsUceControllerCallback c = mPendingCapabilityRequests.remove(reqId);
- try {
- if (c != null) {
- c.onError(toUceError(resultCode));
- } else {
- logw("onError called for unknown reqId:" + reqId);
- }
- } catch (RemoteException e) {
- logi("Calling back to dead service");
- }
- }
-
- @Override
- public void onFinish(int reqId) {
- logi("onFinish called for reqId:" + reqId);
- }
-
- @Override
- public void onTimeout(int reqId) {
- IRcsUceControllerCallback c = mPendingCapabilityRequests.remove(reqId);
- try {
- if (c != null) {
- c.onError(RcsUceAdapter.ERROR_REQUEST_TIMEOUT);
- } else {
- logw("onTimeout called for unknown reqId:" + reqId);
- }
- } catch (RemoteException e) {
- logi("Calling back to dead service");
- }
- }
-
- @Override
- public void onCapabilitiesUpdated(int reqId,
- List<RcsContactUceCapability> contactCapabilities,
- boolean updateLastTimestamp) {
- IRcsUceControllerCallback c = mPendingCapabilityRequests.remove(reqId);
- try {
- if (c != null) {
- c.onCapabilitiesReceived(contactCapabilities);
- } else {
- logw("onCapabilitiesUpdated, unknown reqId:" + reqId);
- }
- } catch (RemoteException e) {
- logw("onCapabilitiesUpdated on dead service");
- }
- }
- });
- if (taskId < 0) {
- try {
- c.onError(toUceError(taskId));
- } catch (RemoteException e) {
- logi("Calling back to dead service");
- }
- return;
- }
- mPendingCapabilityRequests.put(taskId, c);
- }
-
- @Override
- public int requestCapability(String[] formattedContacts, int taskId) {
- if (formattedContacts == null || formattedContacts.length == 0) {
- logw("requestCapability error: contacts is null.");
- return ResultCode.SUBSCRIBE_INVALID_PARAM;
- }
- if (mRcsFeatureManager == null) {
- logw("requestCapability error: RcsFeatureManager is null.");
- return ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
- }
-
- logi("requestCapability: taskId=" + taskId);
-
- try {
- List<Uri> contactList = Arrays.stream(formattedContacts)
- .map(Uri::parse).collect(Collectors.toList());
- mRcsFeatureManager.requestCapabilities(contactList, taskId);
- } catch (Exception e) {
- logw("requestCapability error: " + e.getMessage());
- return ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
- }
- return ResultCode.SUCCESS;
- }
-
- @Override
- public int requestAvailability(String formattedContact, int taskId) {
- if (formattedContact == null || formattedContact.isEmpty()) {
- logw("requestAvailability error: contact is null.");
- return ResultCode.SUBSCRIBE_INVALID_PARAM;
- }
- if (mRcsFeatureManager == null) {
- logw("requestAvailability error: RcsFeatureManager is null.");
- return ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
- }
-
- logi("requestAvailability: taskId=" + taskId);
- addRequestingAvailabilityTaskId(taskId);
-
- try {
- Uri contactUri = Uri.parse(formattedContact);
- List<Uri> contactUris = new ArrayList<>(Arrays.asList(contactUri));
- mRcsFeatureManager.requestCapabilities(contactUris, taskId);
- } catch (Exception e) {
- logw("requestAvailability error: " + e.getMessage());
- removeRequestingAvailabilityTaskId(taskId);
- return ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
- }
- return ResultCode.SUCCESS;
- }
-
- @Override
- public int getStackStatusForCapabilityRequest() {
- if (mRcsFeatureManager == null) {
- logw("Check Stack status: Error! RcsFeatureManager is null.");
- return ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
- }
-
- if (!isCapabilityDiscoveryEnabled(mSubId)) {
- logw("Check Stack status: Error! capability discovery not enabled");
- return ResultCode.ERROR_SERVICE_NOT_ENABLED;
- }
-
- if (!isEabProvisioned(mContext, mSubId)) {
- logw("Check Stack status: Error! EAB provisioning disabled.");
- return ResultCode.ERROR_SERVICE_NOT_ENABLED;
- }
-
- if (getPublisherState() != PresenceBase.PUBLISH_STATE_200_OK) {
- logw("Check Stack status: Error! publish state " + getPublisherState());
- return ResultCode.ERROR_SERVICE_NOT_PUBLISHED;
- }
- return ResultCode.SUCCESS;
- }
-
- /**
- * The feature callback is to receive the request and update from RcsPresExchangeImplBase
- */
- @VisibleForTesting
- public RcsFeatureCallbacks mRcsFeatureCallback = new RcsFeatureCallbacks() {
- public void onCommandUpdate(int commandCode, int operationToken) {
- logi("onCommandUpdate: code=" + commandCode + ", token=" + operationToken);
- if (isPublishRequestExisted(operationToken)) {
- onCommandUpdateForPublishRequest(commandCode, operationToken);
- } else if (isCapabilityRequestExisted(operationToken)) {
- onCommandUpdateForCapabilityRequest(commandCode, operationToken);
- } else if (isAvailabilityRequestExisted(operationToken)) {
- onCommandUpdateForAvailabilityRequest(commandCode, operationToken);
- } else {
- logw("onCommandUpdate: invalid token " + operationToken);
- }
- }
-
- /** See {@link RcsPresenceExchangeImplBase#onNetworkResponse(int, String, int)} */
- public void onNetworkResponse(int responseCode, String reason, int operationToken) {
- logi("onNetworkResponse: code=" + responseCode + ", reason=" + reason
- + ", operationToken=" + operationToken);
- if (isPublishRequestExisted(operationToken)) {
- onNetworkResponseForPublishRequest(responseCode, reason, operationToken);
- } else if (isCapabilityRequestExisted(operationToken)) {
- onNetworkResponseForCapabilityRequest(responseCode, reason, operationToken);
- } else if (isAvailabilityRequestExisted(operationToken)) {
- onNetworkResponseForAvailabilityRequest(responseCode, reason, operationToken);
- } else {
- logw("onNetworkResponse: invalid token " + operationToken);
- }
- }
-
- /** See {@link RcsPresenceExchangeImplBase#onCapabilityRequestResponse(List, int)} */
- public void onCapabilityRequestResponsePresence(List<RcsContactUceCapability> infos,
- int operationToken) {
- if (isAvailabilityRequestExisted(operationToken)) {
- handleAvailabilityReqResponse(infos, operationToken);
- } else if (isCapabilityRequestExisted(operationToken)) {
- handleCapabilityReqResponse(infos, operationToken);
- } else {
- logw("capability request response: invalid token " + operationToken);
- }
- }
-
- /** See {@link RcsPresenceExchangeImplBase#onNotifyUpdateCapabilites(int)} */
- public void onNotifyUpdateCapabilities(int publishTriggerType) {
- logi("onNotifyUpdateCapabilities: type=" + publishTriggerType);
- mUceImplHandler.notifyUpdateCapabilities(publishTriggerType);
- }
-
- /** See {@link RcsPresenceExchangeImplBase#onUnpublish()} */
- public void onUnpublish() {
- logi("onUnpublish");
- mUceImplHandler.unpublish();
- }
- };
-
- private static class UceImplHandler extends Handler {
- private static final int EVENT_REGISTER_IMS_CHANGED_RECEIVER = 1;
- private static final int EVENT_NOTIFY_UPDATE_CAPABILITIES = 2;
- private static final int EVENT_UNPUBLISH = 3;
-
- private static final int REGISTER_IMS_CHANGED_DELAY = 10000; //10 seconds
-
- private final WeakReference<UserCapabilityExchangeImpl> mUceImplRef;
-
- UceImplHandler(UserCapabilityExchangeImpl uceImpl, Looper looper) {
- super(looper);
- mUceImplRef = new WeakReference(uceImpl);
- }
-
- @Override
- public void handleMessage(Message msg) {
- UserCapabilityExchangeImpl uceImpl = mUceImplRef.get();
- if (uceImpl == null) {
- return;
- }
- switch (msg.what) {
- case EVENT_REGISTER_IMS_CHANGED_RECEIVER:
- int subId = msg.arg1;
- uceImpl.registerImsContentChangedReceiverInternal(subId);
- break;
- case EVENT_NOTIFY_UPDATE_CAPABILITIES:
- int publishTriggerType = msg.arg1;
- uceImpl.onNotifyUpdateCapabilities(publishTriggerType);
- break;
- case EVENT_UNPUBLISH:
- uceImpl.onUnPublish();
- break;
- default:
- Log.w(LOG_TAG, "handleMessage: error=" + msg.what);
- break;
- }
- }
-
- private void retryRegisteringImsContentChangedReceiver(int subId) {
- sendRegisteringImsContentChangedMessage(subId, REGISTER_IMS_CHANGED_DELAY);
- }
-
- private void registerImsContentChangedReceiver(int subId) {
- sendRegisteringImsContentChangedMessage(subId, 0);
- }
-
- private void sendRegisteringImsContentChangedMessage(int subId, int delay) {
- if (subId <= SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- return;
- }
- removeRegisteringImsContentChangedReceiver();
- Message message = obtainMessage(EVENT_REGISTER_IMS_CHANGED_RECEIVER);
- message.arg1 = subId;
- sendMessageDelayed(message, delay);
- }
-
- private void removeRegisteringImsContentChangedReceiver() {
- removeMessages(EVENT_REGISTER_IMS_CHANGED_RECEIVER);
- }
-
- private void notifyUpdateCapabilities(int publishTriggerType) {
- Message message = obtainMessage(EVENT_NOTIFY_UPDATE_CAPABILITIES);
- message.arg1 = publishTriggerType;
- sendMessage(message);
- }
-
- private void unpublish() {
- sendEmptyMessage(EVENT_UNPUBLISH);
- }
- }
-
- private void onNotifyUpdateCapabilities(int publishTriggerType) {
- mPresencePublication.onStackPublishRequested(publishTriggerType);
- }
-
- private void onUnPublish() {
- mPresencePublication.setPublishState(PresenceBase.PUBLISH_STATE_NOT_PUBLISHED);
- }
-
- @Override
- public @PresenceBase.PresencePublishState int getPublisherState() {
- return mPublishState;
- }
-
- @Override
- public int requestPublication(RcsContactUceCapability capabilities, String contactUri,
- int taskId) {
- if (mRcsFeatureManager == null) {
- logw("requestPublication error: RcsFeatureManager is null.");
- return ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
- }
-
- logi("requestPublication: taskId=" + taskId);
- addPublishRequestTaskId(taskId);
-
- try {
- mRcsFeatureManager.requestPublication(capabilities, taskId);
- } catch (Exception ex) {
- logw("requestPublication error: " + ex.getMessage());
- removePublishRequestTaskId(taskId);
- return ResultCode.PUBLISH_GENERIC_FAILURE;
- }
- return ResultCode.SUCCESS;
- }
-
- /*
- * Handle the callback method RcsFeatureCallbacks#onCommandUpdate(int, int)
- */
- private void onCommandUpdateForPublishRequest(int commandCode, int operationToken) {
- if (!isPublishRequestExisted(operationToken)) {
- return;
- }
- int resultCode = ResultCode.SUCCESS;
- if (commandCode != RcsCapabilityExchange.COMMAND_CODE_SUCCESS) {
- logw("onCommandUpdateForPublishRequest failed! taskId=" + operationToken
- + ", code=" + commandCode);
- removePublishRequestTaskId(operationToken);
- resultCode = ResultCode.PUBLISH_GENERIC_FAILURE;
- }
- mPresencePublication.onCommandStatusUpdated(operationToken, operationToken, resultCode);
- }
-
- private void onCommandUpdateForCapabilityRequest(int commandCode, int operationToken) {
- if (!isCapabilityRequestExisted(operationToken)) {
- return;
- }
- int resultCode = ResultCode.SUCCESS;
- if (commandCode != RcsCapabilityExchange.COMMAND_CODE_SUCCESS) {
- logw("onCommandUpdateForCapabilityRequest failed! taskId=" + operationToken
- + ", code=" + commandCode);
- mPendingCapabilityRequests.remove(operationToken);
- resultCode = ResultCode.PUBLISH_GENERIC_FAILURE;
- }
- mPresenceSubscriber.onCommandStatusUpdated(operationToken, operationToken, resultCode);
- }
-
- private void onCommandUpdateForAvailabilityRequest(int commandCode, int operationToken) {
- if (!isAvailabilityRequestExisted(operationToken)) {
- return;
- }
- int resultCode = ResultCode.SUCCESS;
- if (commandCode != RcsCapabilityExchange.COMMAND_CODE_SUCCESS) {
- logw("onCommandUpdateForAvailabilityRequest failed! taskId=" + operationToken
- + ", code=" + commandCode);
- removeRequestingAvailabilityTaskId(operationToken);
- resultCode = ResultCode.PUBLISH_GENERIC_FAILURE;
- }
- mPresenceSubscriber.onCommandStatusUpdated(operationToken, operationToken, resultCode);
- }
-
- /*
- * Handle the callback method RcsFeatureCallbacks#onNetworkResponse(int, String, int)
- */
- private void onNetworkResponseForPublishRequest(int responseCode, String reason,
- int operationToken) {
- if (!isPublishRequestExisted(operationToken)) {
- return;
- }
- removePublishRequestTaskId(operationToken);
- mPresencePublication.onSipResponse(operationToken, responseCode, reason);
- }
-
- private void onNetworkResponseForCapabilityRequest(int responseCode, String reason,
- int operationToken) {
- if (!isCapabilityRequestExisted(operationToken)) {
- return;
- }
- mPresenceSubscriber.onSipResponse(operationToken, responseCode, reason);
- }
-
- private void onNetworkResponseForAvailabilityRequest(int responseCode, String reason,
- int operationToken) {
- if (!isAvailabilityRequestExisted(operationToken)) {
- return;
- }
- removeRequestingAvailabilityTaskId(operationToken);
- mPresenceSubscriber.onSipResponse(operationToken, responseCode, reason);
- }
-
- private void handleAvailabilityReqResponse(List<RcsContactUceCapability> infos, int token) {
- try {
- if (infos == null || infos.isEmpty()) {
- logw("handle availability request response: infos is null " + token);
- return;
- }
- logi("handleAvailabilityReqResponse: token=" + token);
- mPresenceSubscriber.updatePresence(infos.get(0));
- } finally {
- removeRequestingAvailabilityTaskId(token);
- }
- }
-
- private void handleCapabilityReqResponse(List<RcsContactUceCapability> infos, int token) {
- if (infos == null) {
- logw("handleCapabilityReqResponse: infos is null " + token);
- mPendingCapabilityRequests.remove(token);
- return;
- }
- logi("handleCapabilityReqResponse: token=" + token);
- mPresenceSubscriber.updatePresences(token, infos, true, null);
- }
-
- @Override
- public void updatePublisherState(@PresenceBase.PresencePublishState int publishState) {
- logi("updatePublisherState: from " + mPublishState + " to " + publishState);
- mPublishState = publishState;
- notifyPublishStateChanged(publishState);
- }
-
- private void addPublishRequestTaskId(int taskId) {
- synchronized (mRequestingPublishTaskIds) {
- mRequestingPublishTaskIds.add(taskId);
- }
- }
-
- private void removePublishRequestTaskId(int taskId) {
- synchronized (mRequestingPublishTaskIds) {
- mRequestingPublishTaskIds.remove(taskId);
- }
- }
-
- private boolean isPublishRequestExisted(Integer taskId) {
- synchronized (mRequestingPublishTaskIds) {
- return mRequestingPublishTaskIds.contains(taskId);
- }
- }
-
- private void addRequestingAvailabilityTaskId(int taskId) {
- synchronized (mPendingAvailabilityRequests) {
- mPendingAvailabilityRequests.contains(taskId);
- }
- }
-
- private void removeRequestingAvailabilityTaskId(int taskId) {
- synchronized (mPendingAvailabilityRequests) {
- mPendingAvailabilityRequests.remove(taskId);
- }
- }
-
- private boolean isAvailabilityRequestExisted(Integer taskId) {
- synchronized (mPendingAvailabilityRequests) {
- return mPendingAvailabilityRequests.contains(taskId);
- }
- }
-
- private boolean isCapabilityRequestExisted(Integer taskId) {
- return mPendingCapabilityRequests.containsKey(taskId);
- }
-
- private static String getNumberFromUri(Uri uri) {
- String number = uri.getSchemeSpecificPart();
- String[] numberParts = number.split("[@;:]");
-
- if (numberParts.length == 0) {
- return null;
- }
- return numberParts[0];
- }
-
- private static int toUcePublishState(int publishState) {
- switch (publishState) {
- case PresenceBase.PUBLISH_STATE_200_OK:
- return RcsUceAdapter.PUBLISH_STATE_OK;
- case PresenceBase.PUBLISH_STATE_NOT_PUBLISHED:
- return RcsUceAdapter.PUBLISH_STATE_NOT_PUBLISHED;
- case PresenceBase.PUBLISH_STATE_VOLTE_PROVISION_ERROR:
- return RcsUceAdapter.PUBLISH_STATE_VOLTE_PROVISION_ERROR;
- case PresenceBase.PUBLISH_STATE_RCS_PROVISION_ERROR:
- return RcsUceAdapter.PUBLISH_STATE_RCS_PROVISION_ERROR;
- case PresenceBase.PUBLISH_STATE_REQUEST_TIMEOUT:
- return RcsUceAdapter.PUBLISH_STATE_REQUEST_TIMEOUT;
- case PresenceBase.PUBLISH_STATE_OTHER_ERROR:
- return RcsUceAdapter.PUBLISH_STATE_OTHER_ERROR;
- default:
- return RcsUceAdapter.PUBLISH_STATE_OTHER_ERROR;
- }
- }
-
- private static int toUceError(int resultCode) {
- switch (resultCode) {
- case ResultCode.SUBSCRIBE_NOT_REGISTERED:
- return RcsUceAdapter.ERROR_NOT_REGISTERED;
- case ResultCode.SUBSCRIBE_REQUEST_TIMEOUT:
- return RcsUceAdapter.ERROR_REQUEST_TIMEOUT;
- case ResultCode.SUBSCRIBE_FORBIDDEN:
- return RcsUceAdapter.ERROR_FORBIDDEN;
- case ResultCode.SUBSCRIBE_NOT_FOUND:
- return RcsUceAdapter.ERROR_NOT_FOUND;
- case ResultCode.SUBSCRIBE_TOO_LARGE:
- return RcsUceAdapter.ERROR_REQUEST_TOO_LARGE;
- case ResultCode.SUBSCRIBE_INSUFFICIENT_MEMORY:
- return RcsUceAdapter.ERROR_INSUFFICIENT_MEMORY;
- case ResultCode.SUBSCRIBE_LOST_NETWORK:
- return RcsUceAdapter.ERROR_LOST_NETWORK;
- case ResultCode.SUBSCRIBE_ALREADY_IN_QUEUE:
- return RcsUceAdapter.ERROR_ALREADY_IN_QUEUE;
- default:
- return RcsUceAdapter.ERROR_GENERIC_FAILURE;
- }
- }
-
- /*
- * Register receivers for updating capabilities
- */
- private void registerReceivers() {
- IntentFilter filter = new IntentFilter(TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED);
- filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
- mContext.registerReceiver(mReceiver, filter);
-
- ContentResolver resolver = mContext.getContentResolver();
- if (resolver != null) {
- // Register mobile data content changed.
- resolver.registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.MOBILE_DATA), false,
- mMobileDataObserver);
-
- // Register SIM info content changed.
- resolver.registerContentObserver(Telephony.SimInfo.CONTENT_URI, false,
- mSimInfoContentObserver);
- }
- }
-
- private void unregisterReceivers() {
- mContext.unregisterReceiver(mReceiver);
- ContentResolver resolver = mContext.getContentResolver();
- if (resolver != null) {
- resolver.unregisterContentObserver(mMobileDataObserver);
- resolver.unregisterContentObserver(mSimInfoContentObserver);
- }
- }
-
- /**
- * Register IMS and provision content changed.
- *
- * Call the UceImplHandler#registerImsContentChangedReceiver instead of
- * calling this method directly.
- */
- private void registerImsContentChangedReceiverInternal(int subId) {
- mUceImplHandler.removeRegisteringImsContentChangedReceiver();
- try {
- final int originalSubId = mSubId;
- if ((originalSubId == subId) && (mImsContentChangedCallbackRegistered)) {
- logi("registerImsContentChangedReceiverInternal: already registered. skip");
- return;
- }
- // Unregister original IMS and Provision callback
- unregisterImsProvisionCallback(originalSubId);
- // Register new IMS and Provision callback
- registerImsProvisionCallback(subId);
- } catch (ImsException e) {
- logw("registerImsContentChangedReceiverInternal error: " + e);
- mUceImplHandler.retryRegisteringImsContentChangedReceiver(subId);
- }
- }
-
- private void unregisterImsProvisionCallback(int subId) {
- if (subId <= SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- return;
- }
- // Unregister IMS callback
- ImsMmTelManager imsMmtelManager = getImsMmTelManager(subId);
- if (imsMmtelManager != null) {
- try {
- imsMmtelManager.unregisterImsRegistrationCallback(mImsRegistrationCallback);
- imsMmtelManager.unregisterMmTelCapabilityCallback(mCapabilityCallback);
- } catch (RuntimeException e) {
- logw("unregister IMS callback error: " + e.getMessage());
- }
- }
-
- // Unregister provision changed callback
- ProvisioningManager provisioningManager =
- ProvisioningManager.createForSubscriptionId(subId);
- try {
- provisioningManager.unregisterProvisioningChangedCallback(mProvisioningChangedCallback);
- } catch (RuntimeException e) {
- logw("unregister provisioning callback error: " + e.getMessage());
- }
-
- // Remove all publish state callbacks
- clearPublishStateCallbacks();
-
- mImsContentChangedCallbackRegistered = false;
- }
-
- private void registerImsProvisionCallback(int subId) throws ImsException {
- if (subId <= SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- return;
- }
- // Register IMS callback
- ImsMmTelManager imsMmtelManager = getImsMmTelManager(subId);
- if (imsMmtelManager != null) {
- imsMmtelManager.registerImsRegistrationCallback(mContext.getMainExecutor(),
- mImsRegistrationCallback);
- imsMmtelManager.registerMmTelCapabilityCallback(mContext.getMainExecutor(),
- mCapabilityCallback);
- }
- // Register provision changed callback
- ProvisioningManager provisioningManager =
- ProvisioningManager.createForSubscriptionId(subId);
- provisioningManager.registerProvisioningChangedCallback(mContext.getMainExecutor(),
- mProvisioningChangedCallback);
-
- mImsContentChangedCallbackRegistered = true;
- logi("registerImsProvisionCallback");
- }
-
- private BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent == null) return;
- switch (intent.getAction()) {
- case TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED:
- int preferredMode = intent.getIntExtra(
- TelecomManager.EXTRA_TTY_PREFERRED_MODE, TelecomManager.TTY_MODE_OFF);
- logi("TTY preferred mode changed: " + preferredMode);
- mPresencePublication.onTtyPreferredModeChanged(preferredMode);
- break;
-
- case Intent.ACTION_AIRPLANE_MODE_CHANGED:
- boolean airplaneMode = intent.getBooleanExtra("state", false);
- logi("Airplane mode changed: " + airplaneMode);
- mPresencePublication.onAirplaneModeChanged(airplaneMode);
- break;
- }
- }
- };
-
- private ContentObserver mMobileDataObserver = new ContentObserver(
- new Handler(Looper.getMainLooper())) {
- @Override
- public void onChange(boolean selfChange) {
- boolean isEnabled = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.MOBILE_DATA, 1) == 1;
- logi("Mobile data changed: enabled=" + isEnabled);
- mPresencePublication.onMobileDataChanged(isEnabled);
- }
- };
-
- private ContentObserver mSimInfoContentObserver = new ContentObserver(
- new Handler(Looper.getMainLooper())) {
- @Override
- public void onChange(boolean selfChange) {
- if (mSubId <= SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- return;
- }
-
- ImsMmTelManager ims = getImsMmTelManager(mSubId);
- if (ims == null) return;
-
- try {
- boolean isEnabled = ims.isVtSettingEnabled();
- logi("SimInfo changed: VT setting=" + isEnabled);
- mPresencePublication.onVtEnabled(isEnabled);
- } catch (RuntimeException e) {
- logw("SimInfo changed error: " + e);
- }
- }
- };
-
- private RegistrationManager.RegistrationCallback mImsRegistrationCallback =
- new RegistrationManager.RegistrationCallback() {
- @Override
- public void onRegistered(int imsTransportType) {
- logi("onRegistered: type=" + imsTransportType);
- mNetworkRegistrationType = imsTransportType;
- mPresencePublication.onImsConnected();
-
- // Also trigger PresencePublication#onFeatureCapabilityChanged method
- MmTelFeature.MmTelCapabilities capabilities = null;
- synchronized (mCapabilitiesLock) {
- capabilities = mMmTelCapabilities;
- }
-
- if (capabilities != null) {
- mPresencePublication.onFeatureCapabilityChanged(mNetworkRegistrationType,
- capabilities);
- }
- }
-
- @Override
- public void onUnregistered(ImsReasonInfo info) {
- logi("onUnregistered");
- mNetworkRegistrationType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
-
- // Also trigger PresencePublication#onFeatureCapabilityChanged method
- MmTelFeature.MmTelCapabilities capabilities = null;
- synchronized (mCapabilitiesLock) {
- capabilities = mMmTelCapabilities;
- }
-
- if (capabilities != null) {
- mPresencePublication.onFeatureCapabilityChanged(mNetworkRegistrationType,
- capabilities);
- }
- mPresencePublication.onImsDisconnected();
- }
- };
-
- private ImsMmTelManager.CapabilityCallback mCapabilityCallback =
- new ImsMmTelManager.CapabilityCallback() {
- @Override
- public void onCapabilitiesStatusChanged(MmTelFeature.MmTelCapabilities capabilities) {
- if (capabilities == null) {
- logw("onCapabilitiesStatusChanged: parameter is null");
- return;
- }
- synchronized (mCapabilitiesLock) {
- mMmTelCapabilities = capabilities;
- }
- mPresencePublication.onFeatureCapabilityChanged(mNetworkRegistrationType, capabilities);
- }
- };
-
- private ProvisioningManager.Callback mProvisioningChangedCallback =
- new ProvisioningManager.Callback() {
- @Override
- public void onProvisioningIntChanged(int item, int value) {
- logi("onProvisioningIntChanged: item=" + item);
- switch (item) {
- case ProvisioningManager.KEY_EAB_PROVISIONING_STATUS:
- case ProvisioningManager.KEY_VOLTE_PROVISIONING_STATUS:
- case ProvisioningManager.KEY_VT_PROVISIONING_STATUS:
- mPresencePublication.handleProvisioningChanged();
- break;
- default:
- break;
- }
- }
- };
-
- private boolean isCapabilityDiscoveryEnabled(int subId) {
- try {
- ProvisioningManager manager = ProvisioningManager.createForSubscriptionId(subId);
- int discoveryEnabled = manager.getProvisioningIntValue(
- ProvisioningManager.KEY_RCS_CAPABILITY_DISCOVERY_ENABLED);
- return (discoveryEnabled == ProvisioningManager.PROVISIONING_VALUE_ENABLED);
- } catch (Exception e) {
- logw("isCapabilityDiscoveryEnabled error: " + e.getMessage());
- }
- return false;
- }
-
- private boolean isEabProvisioned(Context context, int subId) {
- if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- logw("isEabProvisioned error: invalid subscriptionId " + subId);
- return false;
- }
-
- CarrierConfigManager configManager = (CarrierConfigManager)
- context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
- if (configManager != null) {
- PersistableBundle config = configManager.getConfigForSubId(subId);
- if (config != null && !config.getBoolean(
- CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONED_BOOL)) {
- return true;
- }
- }
-
- try {
- ProvisioningManager manager = ProvisioningManager.createForSubscriptionId(subId);
- int provisioningStatus = manager.getProvisioningIntValue(
- ProvisioningManager.KEY_EAB_PROVISIONING_STATUS);
- return (provisioningStatus == ProvisioningManager.PROVISIONING_VALUE_ENABLED);
- } catch (Exception e) {
- logw("isEabProvisioned error: " + e.getMessage());
- }
- return false;
- }
-
- private ImsMmTelManager getImsMmTelManager(int subId) {
- try {
- ImsManager imsManager = (ImsManager) mContext.getSystemService(
- Context.TELEPHONY_IMS_SERVICE);
- return (imsManager == null) ? null : imsManager.getImsMmTelManager(subId);
- } catch (IllegalArgumentException e) {
- logw("getImsMmTelManager error: " + e.getMessage());
- return null;
- }
- }
-
- private void logi(String log) {
- Log.i(LOG_TAG, getLogPrefix().append(log).toString());
- }
-
- private void logw(String log) {
- Log.w(LOG_TAG, getLogPrefix().append(log).toString());
- }
-
- private StringBuilder getLogPrefix() {
- StringBuilder builder = new StringBuilder("[");
- builder.append(mSlotId);
- builder.append("->");
- builder.append(mSubId);
- builder.append("] ");
- return builder;
- }
-}
diff --git a/testapps/ImsTestService/AndroidManifest.xml b/testapps/ImsTestService/AndroidManifest.xml
index 46d0721..6177e73 100644
--- a/testapps/ImsTestService/AndroidManifest.xml
+++ b/testapps/ImsTestService/AndroidManifest.xml
@@ -21,7 +21,7 @@
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!--Beware, declaring the below permission will cause the device to not boot unless you add
this app and permission to frameworks/base/data/etc/privapp-permissions-platform.xml-->
- <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+ <!--uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/-->
<application android:label="ImsTestService"
android:directBootAware="true">
<activity android:name=".ImsTestServiceApp"
diff --git a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/SipTransportImpl.java b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/SipTransportImpl.java
new file mode 100644
index 0000000..1ae2594
--- /dev/null
+++ b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/SipTransportImpl.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 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.phone.testapps.imstestapp;
+
+import android.telephony.ims.stub.SipTransportImplBase;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Test stub implementation of SipTransport.
+ */
+public class SipTransportImpl extends SipTransportImplBase {
+
+ private static SipTransportImpl sSipTransportInstance;
+
+ public static SipTransportImpl getInstance(Executor e) {
+ if (sSipTransportInstance == null) {
+ sSipTransportInstance = new SipTransportImpl(e);
+ }
+ return sSipTransportInstance;
+ };
+
+ public SipTransportImpl(Executor e) {
+ super(e);
+ }
+}
diff --git a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/TestImsService.java b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/TestImsService.java
index 71323d8..477c638 100644
--- a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/TestImsService.java
+++ b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/TestImsService.java
@@ -39,6 +39,7 @@
public TestMmTelFeatureImpl mTestMmTelFeature;
public TestRcsFeatureImpl mTestRcsFeature;
public TestImsConfigImpl mTestImsConfig;
+ public SipTransportImpl mSipTransportImpl;
public static TestImsService getInstance() {
return mInstance;
@@ -51,7 +52,8 @@
mTestMmTelFeature = TestMmTelFeatureImpl.getInstance();
mTestRcsFeature = new TestRcsFeatureImpl();
mTestImsConfig = TestImsConfigImpl.getInstance();
-
+ mSipTransportImpl = SipTransportImpl.getInstance(
+ getApplicationContext().getMainExecutor());
mInstance = this;
}
@@ -60,10 +62,16 @@
return new ImsFeatureConfiguration.Builder()
.addFeature(0, ImsFeature.FEATURE_EMERGENCY_MMTEL)
.addFeature(0, ImsFeature.FEATURE_MMTEL)
+ .addFeature(0, ImsFeature.FEATURE_RCS)
.build();
}
@Override
+ public long getImsServiceCapabilities() {
+ return CAPABILITY_SIP_DELEGATE_CREATION;
+ }
+
+ @Override
public MmTelFeature createMmTelFeature(int slotId) {
Log.i(LOG_TAG, "TestImsService: onCreateMmTelImsFeature");
return mTestMmTelFeature;
@@ -84,4 +92,9 @@
public ImsConfigImplBase getConfig(int slotId) {
return mTestImsConfig;
}
+
+ @Override
+ public SipTransportImpl getSipTransport(int slotId) {
+ return mSipTransportImpl;
+ }
}
diff --git a/tests/src/com/android/TelephonyTestBase.java b/tests/src/com/android/TelephonyTestBase.java
index 132d893..502740d 100644
--- a/tests/src/com/android/TelephonyTestBase.java
+++ b/tests/src/com/android/TelephonyTestBase.java
@@ -27,6 +27,7 @@
import org.mockito.MockitoAnnotations;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
/**
@@ -58,6 +59,23 @@
PhoneConfigurationManager.unregisterAllMultiSimConfigChangeRegistrants();
}
+ protected final boolean waitForExecutorAction(Executor executor, long timeoutMillis) {
+ final CountDownLatch lock = new CountDownLatch(1);
+ Log.i("BRAD", "waitForExecutorAction");
+ executor.execute(() -> {
+ Log.i("BRAD", "countdown");
+ lock.countDown();
+ });
+ while (lock.getCount() > 0) {
+ try {
+ return lock.await(timeoutMillis, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ // do nothing
+ }
+ }
+ return true;
+ }
+
protected final void waitForHandlerAction(Handler h, long timeoutMillis) {
final CountDownLatch lock = new CountDownLatch(1);
h.post(lock::countDown);
diff --git a/tests/src/com/android/TestContext.java b/tests/src/com/android/TestContext.java
index 13bfe3b..9d712d3 100644
--- a/tests/src/com/android/TestContext.java
+++ b/tests/src/com/android/TestContext.java
@@ -17,7 +17,7 @@
package com.android;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doAnswer;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -32,9 +32,11 @@
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsManager;
import android.test.mock.MockContext;
+import android.util.SparseArray;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
import java.util.concurrent.Executor;
@@ -46,11 +48,19 @@
@Mock SubscriptionManager mMockSubscriptionManager;
@Mock ImsManager mMockImsManager;
- private PersistableBundle mCarrierConfig = new PersistableBundle();
+ private SparseArray<PersistableBundle> mCarrierConfigs = new SparseArray<>();
public TestContext() {
MockitoAnnotations.initMocks(this);
- doReturn(mCarrierConfig).when(mMockCarrierConfigManager).getConfigForSubId(anyInt());
+ doAnswer((Answer<PersistableBundle>) invocation -> {
+ int subId = (int) invocation.getArguments()[0];
+ if (subId < 0) {
+ return new PersistableBundle();
+ }
+ PersistableBundle b = mCarrierConfigs.get(subId);
+
+ return (b != null ? b : new PersistableBundle());
+ }).when(mMockCarrierConfigManager).getConfigForSubId(anyInt());
}
@Override
@@ -140,7 +150,15 @@
return null;
}
- public PersistableBundle getCarrierConfig() {
- return mCarrierConfig;
+ /**
+ * @return CarrierConfig PersistableBundle for the subscription specified.
+ */
+ public PersistableBundle getCarrierConfig(int subId) {
+ PersistableBundle b = mCarrierConfigs.get(subId);
+ if (b == null) {
+ b = new PersistableBundle();
+ mCarrierConfigs.put(subId, b);
+ }
+ return b;
}
}
diff --git a/tests/src/com/android/TestExecutorService.java b/tests/src/com/android/TestExecutorService.java
new file mode 100644
index 0000000..fec502a
--- /dev/null
+++ b/tests/src/com/android/TestExecutorService.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2020 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;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Delayed;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * An implementation of ExecutorService that just runs the requested task on the thread that it
+ * was called on for testing purposes.
+ */
+public class TestExecutorService implements ScheduledExecutorService {
+
+ private static class CompletedFuture<T> implements Future<T>, ScheduledFuture<T> {
+
+ private final Callable<T> mTask;
+ private final long mDelayMs;
+
+ CompletedFuture(Callable<T> task) {
+ mTask = task;
+ mDelayMs = 0;
+ }
+
+ CompletedFuture(Callable<T> task, long delayMs) {
+ mTask = task;
+ mDelayMs = delayMs;
+ }
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ return false;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return false;
+ }
+
+ @Override
+ public boolean isDone() {
+ return true;
+ }
+
+ @Override
+ public T get() throws InterruptedException, ExecutionException {
+ try {
+ return mTask.call();
+ } catch (Exception e) {
+ throw new ExecutionException(e);
+ }
+ }
+
+ @Override
+ public T get(long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ try {
+ return mTask.call();
+ } catch (Exception e) {
+ throw new ExecutionException(e);
+ }
+ }
+
+ @Override
+ public long getDelay(TimeUnit unit) {
+ if (unit == TimeUnit.MILLISECONDS) {
+ return mDelayMs;
+ } else {
+ // not implemented
+ return 0;
+ }
+ }
+
+ @Override
+ public int compareTo(Delayed o) {
+ if (o == null) return 1;
+ if (o.getDelay(TimeUnit.MILLISECONDS) > mDelayMs) return -1;
+ if (o.getDelay(TimeUnit.MILLISECONDS) < mDelayMs) return 1;
+ return 0;
+ }
+ }
+
+ @Override
+ public void shutdown() {
+ }
+
+ @Override
+ public List<Runnable> shutdownNow() {
+ return null;
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return false;
+ }
+
+ @Override
+ public boolean isTerminated() {
+ return false;
+ }
+
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit) {
+ return false;
+ }
+
+ @Override
+ public <T> Future<T> submit(Callable<T> task) {
+ return new CompletedFuture<>(task);
+ }
+
+ @Override
+ public <T> Future<T> submit(Runnable task, T result) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public Future<?> submit(Runnable task) {
+ task.run();
+ return new CompletedFuture<>(() -> null);
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout,
+ TimeUnit unit) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
+ // No need to worry about delays yet
+ command.run();
+ return new CompletedFuture<>(() -> null, delay);
+ }
+
+ @Override
+ public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
+ return new CompletedFuture<>(callable, delay);
+ }
+
+ @Override
+ public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period,
+ TimeUnit unit) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,
+ long delay, TimeUnit unit) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ command.run();
+ }
+}
diff --git a/tests/src/com/android/services/telephony/ImsConferenceTest.java b/tests/src/com/android/services/telephony/ImsConferenceTest.java
index f13d709..7e6488d 100644
--- a/tests/src/com/android/services/telephony/ImsConferenceTest.java
+++ b/tests/src/com/android/services/telephony/ImsConferenceTest.java
@@ -16,6 +16,8 @@
package com.android.services.telephony;
+import static junit.framework.Assert.assertTrue;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -573,4 +575,40 @@
assertEquals(0, imsConference.getNumberOfParticipants());
verify(mConferenceHost.mMockCall).hangup();
}
+
+ /**
+ * Verifies that an ImsConference can handle SIP and TEL URIs for both the P-Associated-Uri and
+ * conference event package identities.
+ */
+ @Test
+ public void testIsParticipantHost() {
+ // Simplest case, assume P-Associated-Uri is a tel URI and that the CEP participant is also
+ // a tel URI.
+ assertTrue(ImsConference.isParticipantHost(new Uri[] {
+ Uri.parse("tel:+8616505551234")},
+ Uri.parse("tel:+8616505551234")));
+
+ // Assume P-Associated-Uri is a tel URI and the CEP participant is a sip URI.
+ assertTrue(ImsConference.isParticipantHost(new Uri[] {
+ Uri.parse("tel:+8616505551234")},
+ Uri.parse("sip:+8616505551234@bj.ims.mnc011.mcc460.3gppnetwork.org")));
+
+ // Assume P-Associated-Uri is a sip URI and the CEP participant is a tel URI.
+ assertTrue(ImsConference.isParticipantHost(new Uri[] {
+ Uri.parse("sip:+8616505551234@bj.ims.mnc011.mcc460.3gppnetwork.org")},
+ Uri.parse("tel:+8616505551234")));
+
+ // Assume both P-Associated-Uri and the CEP participant are SIP URIs.
+ assertTrue(ImsConference.isParticipantHost(new Uri[] {
+ Uri.parse("sip:+8616505551234@bj.ims.mnc011.mcc460.3gppnetwork.org")},
+ Uri.parse("sip:+8616505551234@bj.ims.mnc011.mcc460.3gppnetwork.org")));
+
+ // Corner cases
+ assertFalse(ImsConference.isParticipantHost(new Uri[] {
+ Uri.parse("tel:+8616505551234")}, Uri.fromParts("", "", "")));
+ assertFalse(ImsConference.isParticipantHost(new Uri[] {
+ Uri.parse("tel:+8616505551234")}, null));
+ assertFalse(ImsConference.isParticipantHost(null, null));
+ assertFalse(ImsConference.isParticipantHost(new Uri[0], null));
+ }
}
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index 2060e6f..07fe6a8 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -936,14 +936,14 @@
// Setup test to not support SUPL on the non-DDS subscription
doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
- getTestContext().getCarrierConfig().putStringArray(
+ getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
null);
testPhone.getServiceState().setRoaming(false);
- getTestContext().getCarrierConfig().putInt(
+ getTestContext().getCarrierConfig(0 /*subId*/).putInt(
CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY);
- getTestContext().getCarrierConfig().putString(
+ getTestContext().getCarrierConfig(0 /*subId*/).putString(
CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "150");
delayDialRunnable.run();
@@ -1021,14 +1021,14 @@
// Setup test to not support SUPL on the non-DDS subscription
doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
- getTestContext().getCarrierConfig().putStringArray(
+ getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
null);
testPhone.getServiceState().setRoaming(false);
- getTestContext().getCarrierConfig().putInt(
+ getTestContext().getCarrierConfig(0 /*subId*/).putInt(
CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK);
- getTestContext().getCarrierConfig().putString(
+ getTestContext().getCarrierConfig(0 /*subId*/).putString(
CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
delayDialRunnable.run();
@@ -1047,14 +1047,14 @@
// If the non-DDS supports SUPL, dont switch data
doReturn(false).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
- getTestContext().getCarrierConfig().putStringArray(
+ getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
null);
testPhone.getServiceState().setRoaming(false);
- getTestContext().getCarrierConfig().putInt(
+ getTestContext().getCarrierConfig(0 /*subId*/).putInt(
CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY);
- getTestContext().getCarrierConfig().putString(
+ getTestContext().getCarrierConfig(0 /*subId*/).putString(
CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
delayDialRunnable.run();
@@ -1073,14 +1073,14 @@
// Setup test to not support SUPL on the non-DDS subscription
doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
- getTestContext().getCarrierConfig().putStringArray(
+ getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
null);
testPhone.getServiceState().setRoaming(true);
- getTestContext().getCarrierConfig().putInt(
+ getTestContext().getCarrierConfig(0 /*subId*/).putInt(
CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY);
- getTestContext().getCarrierConfig().putString(
+ getTestContext().getCarrierConfig(0 /*subId*/).putString(
CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
delayDialRunnable.run();
@@ -1107,13 +1107,13 @@
doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
String[] roamingPlmns = new String[1];
roamingPlmns[0] = testRoamingOperator;
- getTestContext().getCarrierConfig().putStringArray(
+ getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
roamingPlmns);
- getTestContext().getCarrierConfig().putInt(
+ getTestContext().getCarrierConfig(0 /*subId*/).putInt(
CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK);
- getTestContext().getCarrierConfig().putString(
+ getTestContext().getCarrierConfig(0 /*subId*/).putString(
CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
delayDialRunnable.run();
@@ -1140,13 +1140,13 @@
doReturn(true).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
String[] roamingPlmns = new String[1];
roamingPlmns[0] = testRoamingOperator;
- getTestContext().getCarrierConfig().putStringArray(
+ getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
roamingPlmns);
- getTestContext().getCarrierConfig().putInt(
+ getTestContext().getCarrierConfig(0 /*subId*/).putInt(
CarrierConfigManager.Gps.KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK);
- getTestContext().getCarrierConfig().putString(
+ getTestContext().getCarrierConfig(0 /*subId*/).putString(
CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, "0");
delayDialRunnable.run();
diff --git a/tests/src/com/android/services/telephony/TelephonyManagerTest.java b/tests/src/com/android/services/telephony/TelephonyManagerTest.java
new file mode 100644
index 0000000..e9cdc98
--- /dev/null
+++ b/tests/src/com/android/services/telephony/TelephonyManagerTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2020 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.services.telephony;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.emergency.EmergencyNumber;
+import android.test.mock.MockContext;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.telephony.ITelephony;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** Unit tests for {@link TelephonyManager}. */
+@RunWith(AndroidJUnit4.class)
+public class TelephonyManagerTest {
+ private static final String PKG_NAME = "Unittest.TelephonyManagerTest";
+ private static final String TAG = "TelephonyManagerTest";
+
+ private ITelephony mMockITelephony;
+ private SubscriptionManager mMockSubscriptionManager;
+ private Context mMockContext;
+
+ private TelephonyManager mTelephonyManager;
+
+ private final MockContext mContext =
+ new MockContext() {
+ @Override
+ public String getOpPackageName() {
+ return PKG_NAME;
+ }
+ @Override
+ public String getAttributionTag() {
+ return TAG;
+ }
+ @Override
+ public Context getApplicationContext() {
+ return null;
+ }
+ @Override
+ public Object getSystemService(String name) {
+ switch (name) {
+ case (Context.TELEPHONY_SUBSCRIPTION_SERVICE) : {
+ return mMockSubscriptionManager;
+ }
+ }
+ return null;
+ }
+ };
+
+ @Before
+ public void setUp() throws Exception {
+ mMockITelephony = mock(ITelephony.class);
+ mMockSubscriptionManager = mock(SubscriptionManager.class);
+ mMockContext = mock(Context.class);
+ when(mMockContext.getSystemService(eq(Context.TELEPHONY_SUBSCRIPTION_SERVICE)))
+ .thenReturn(mMockSubscriptionManager);
+
+ mTelephonyManager = new TelephonyManager(mContext);
+ TelephonyManager.setupITelephonyForTest(mMockITelephony);
+ TelephonyManager.enableServiceHandleCaching();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ TelephonyManager.setupITelephonyForTest(null);
+ TelephonyManager.disableServiceHandleCaching();
+ }
+
+ @Test
+ public void testGetEmergencyNumberListForCategories() throws Exception {
+ Map<Integer, List<EmergencyNumber>> emergencyNumberLists = new HashMap<>();
+ List<EmergencyNumber> emergencyNumberList = new ArrayList<>();
+ EmergencyNumber number_police = new EmergencyNumber(
+ "911",
+ "us",
+ "30",
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE,
+ new ArrayList<String>(),
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
+ EmergencyNumber number_fire = new EmergencyNumber(
+ "912",
+ "us",
+ "30",
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE,
+ new ArrayList<String>(),
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
+ emergencyNumberList.add(number_police);
+ emergencyNumberList.add(number_fire);
+ final int test_sub_id = 1;
+ emergencyNumberLists.put(test_sub_id, emergencyNumberList);
+ when(mMockITelephony.getEmergencyNumberList(eq(PKG_NAME), eq(TAG))).thenReturn(
+ emergencyNumberLists);
+
+ // Call TelephonyManager.getEmergencyNumberList(Category)
+ Map<Integer, List<EmergencyNumber>> returnedEmergencyNumberLists =
+ mTelephonyManager.getEmergencyNumberList(
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE);
+
+ // Verify the ITelephony service is called
+ verify(mMockITelephony, times(1)).getEmergencyNumberList(eq(PKG_NAME), eq(TAG));
+
+ // Verify the returned number list contains only the police number(s)
+ List<EmergencyNumber> returnedEmergencyNumberList = returnedEmergencyNumberLists.get(
+ test_sub_id);
+ for (EmergencyNumber num : returnedEmergencyNumberList) {
+ assertTrue(num.isInEmergencyServiceCategories(
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE));
+ }
+ }
+}
diff --git a/tests/src/com/android/services/telephony/TestTelephonyConnection.java b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
index 09cec17..67e0329 100644
--- a/tests/src/com/android/services/telephony/TestTelephonyConnection.java
+++ b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
@@ -21,6 +21,7 @@
import android.os.Bundle;
import android.os.PersistableBundle;
import android.telecom.PhoneAccountHandle;
+import android.telephony.TelephonyManager;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -61,6 +62,9 @@
Resources mMockResources;
@Mock
+ TelephonyManager mMockTelephonyManager;
+
+ @Mock
EmergencyNumberTracker mEmergencyNumberTracker;
private Phone mMockPhone;
@@ -84,6 +88,7 @@
mMockPhone = mock(Phone.class);
mMockContext = mock(Context.class);
+ mMockTelephonyManager = mock(TelephonyManager.class);
mOriginalConnection = mMockRadioConnection;
// Set up mMockRadioConnection and mMockPhone to contain an active call
when(mMockRadioConnection.getState()).thenReturn(Call.State.ACTIVE);
@@ -101,6 +106,8 @@
when(mMockPhone.getContext()).thenReturn(mMockContext);
when(mMockPhone.getCurrentSubscriberUris()).thenReturn(null);
when(mMockContext.getResources()).thenReturn(mMockResources);
+ when(mMockContext.getSystemService(Context.TELEPHONY_SERVICE))
+ .thenReturn(mMockTelephonyManager);
when(mMockResources.getBoolean(anyInt())).thenReturn(false);
when(mMockPhone.getDefaultPhone()).thenReturn(mMockPhone);
when(mMockPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_IMS);
@@ -169,6 +176,12 @@
// Requires ImsManager dependencies, do not implement during testing.
}
+ @Override
+ boolean isWfcEnabled(Phone phone) {
+ // Requires ImsManager dependencies, mock for test.
+ return true;
+ }
+
public int getNotifyPhoneAccountChangedCount() {
return mNotifyPhoneAccountChangedCount;
}
diff --git a/tests/src/com/android/services/telephony/rcs/DelegateStateTrackerTest.java b/tests/src/com/android/services/telephony/rcs/DelegateStateTrackerTest.java
new file mode 100644
index 0000000..4d40702
--- /dev/null
+++ b/tests/src/com/android/services/telephony/rcs/DelegateStateTrackerTest.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2020 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.services.telephony.rcs;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+public class DelegateStateTrackerTest extends TelephonyTestBase {
+ private static final int TEST_SUB_ID = 1;
+
+ @Mock private ISipDelegate mSipDelegate;
+ @Mock private ISipDelegateConnectionStateCallback mAppCallback;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * When an underlying SipDelegate is created, the app should only receive one onCreated callback
+ * independent of how many times sipDelegateConnected is called. Once created, registration
+ * and IMS configuration events should propagate up to the app as well.
+ */
+ @SmallTest
+ @Test
+ public void testDelegateCreated() throws Exception {
+ DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
+ mSipDelegate);
+ Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
+ stateTracker.sipDelegateConnected(deniedTags);
+ // Calling connected multiple times should not generate multiple onCreated events.
+ stateTracker.sipDelegateConnected(deniedTags);
+ verify(mAppCallback).onCreated(mSipDelegate);
+
+ // Ensure status updates are sent to app as expected.
+ DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
+ .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG)
+ .build();
+ SipDelegateImsConfiguration config = new SipDelegateImsConfiguration.Builder(1/*version*/)
+ .build();
+ stateTracker.onRegistrationStateChanged(regState);
+ stateTracker.onImsConfigurationChanged(config);
+ verify(mAppCallback).onFeatureTagStatusChanged(eq(regState),
+ eq(new ArrayList<>(deniedTags)));
+ verify(mAppCallback).onImsConfigurationChanged(config);
+
+ verify(mAppCallback, never()).onDestroyed(anyInt());
+ }
+
+ /**
+ * onDestroyed should be called when sipDelegateDestroyed is called.
+ */
+ @SmallTest
+ @Test
+ public void testDelegateDestroyed() throws Exception {
+ DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
+ mSipDelegate);
+ Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
+ stateTracker.sipDelegateConnected(deniedTags);
+
+ stateTracker.sipDelegateDestroyed(
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ verify(mAppCallback).onDestroyed(
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ }
+
+ /**
+ * When a SipDelegate is created and then an event occurs that will destroy->create a new
+ * SipDelegate underneath, we need to move the state of the features that are reporting
+ * registered to DEREGISTERING_REASON_FEATURE_TAGS_CHANGING so that the app can close dialogs on
+ * it. Once the new underlying SipDelegate is created, we must verify that the new registration
+ * is propagated up without any overrides.
+ */
+ @SmallTest
+ @Test
+ public void testDelegateChangingRegisteredTagsOverride() throws Exception {
+ DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
+ mSipDelegate);
+ Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
+ stateTracker.sipDelegateConnected(deniedTags);
+ // SipDelegate created
+ verify(mAppCallback).onCreated(mSipDelegate);
+ DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
+ .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG)
+ .addDeregisteringFeatureTag(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG,
+ DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE)
+ .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG,
+ DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED)
+ .build();
+ stateTracker.onRegistrationStateChanged(regState);
+ // Simulate underlying SipDelegate switch
+ stateTracker.sipDelegateChanging(
+ DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING);
+ // onFeatureTagStatusChanged should now be called with registered features overridden with
+ // DEREGISTERING_REASON_FEATURE_TAGS_CHANGING
+ DelegateRegistrationState overrideRegState = new DelegateRegistrationState.Builder()
+ .addDeregisteringFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG,
+ DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING)
+ // Already Deregistering/Deregistered tags should not be overridden.
+ .addDeregisteringFeatureTag(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG,
+ DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE)
+ .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG,
+ DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED)
+ .build();
+ // new underlying SipDelegate created
+ stateTracker.sipDelegateConnected(deniedTags);
+ stateTracker.onRegistrationStateChanged(regState);
+
+ // Verify registration state through the process:
+ ArgumentCaptor<DelegateRegistrationState> regCaptor =
+ ArgumentCaptor.forClass(DelegateRegistrationState.class);
+ verify(mAppCallback, times(3)).onFeatureTagStatusChanged(
+ regCaptor.capture(), eq(new ArrayList<>(deniedTags)));
+ List<DelegateRegistrationState> testStates = regCaptor.getAllValues();
+ // feature tags should first be registered
+ assertEquals(regState, testStates.get(0));
+ // registered feature tags should have moved to deregistering
+ assertEquals(overrideRegState, testStates.get(1));
+ // and then moved back to registered after underlying FT change done.
+ assertEquals(regState, testStates.get(2));
+
+ //onCreate should only have been called once and onDestroy should have never been called.
+ verify(mAppCallback).onCreated(mSipDelegate);
+ verify(mAppCallback, never()).onDestroyed(anyInt());
+ }
+
+ /**
+ * Test the case that when the underlying Denied tags change in the SipDelegate, the change is
+ * properly shown in the registration update event.
+ */
+ @SmallTest
+ @Test
+ public void testDelegateChangingDeniedTagsChanged() throws Exception {
+ DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
+ mSipDelegate);
+ Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
+ stateTracker.sipDelegateConnected(deniedTags);
+ // SipDelegate created
+ verify(mAppCallback).onCreated(mSipDelegate);
+ DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
+ .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG)
+ .build();
+ stateTracker.onRegistrationStateChanged(regState);
+ // Simulate underlying SipDelegate switch
+ stateTracker.sipDelegateChanging(
+ DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING);
+ // onFeatureTagStatusChanged should now be called with registered features overridden with
+ // DEREGISTERING_REASON_FEATURE_TAGS_CHANGING
+ DelegateRegistrationState overrideRegState = new DelegateRegistrationState.Builder()
+ .addDeregisteringFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG,
+ DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING)
+ .build();
+ // Verify registration state so far.
+ ArgumentCaptor<DelegateRegistrationState> regCaptor =
+ ArgumentCaptor.forClass(DelegateRegistrationState.class);
+ verify(mAppCallback, times(2)).onFeatureTagStatusChanged(
+ regCaptor.capture(), eq(new ArrayList<>(deniedTags)));
+ List<DelegateRegistrationState> testStates = regCaptor.getAllValues();
+ assertEquals(2, testStates.size());
+ // feature tags should first be registered
+ assertEquals(regState, testStates.get(0));
+ // registered feature tags should have moved to deregistering
+ assertEquals(overrideRegState, testStates.get(1));
+
+ // new underlying SipDelegate created, but SipDelegate denied one to one chat
+ deniedTags.add(new FeatureTagState(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG,
+ SipDelegateManager.DENIED_REASON_NOT_ALLOWED));
+ stateTracker.sipDelegateConnected(deniedTags);
+ DelegateRegistrationState fullyDeniedRegState = new DelegateRegistrationState.Builder()
+ .build();
+ // In this special case, it will be the SipDelegateConnectionBase that will trigger
+ // reg state change.
+ stateTracker.onRegistrationStateChanged(fullyDeniedRegState);
+ verify(mAppCallback).onFeatureTagStatusChanged(regCaptor.capture(),
+ eq(new ArrayList<>(deniedTags)));
+ // now all feature tags denied, so we should see only denied tags.
+ assertEquals(fullyDeniedRegState, regCaptor.getValue());
+
+ //onCreate should only have been called once and onDestroy should have never been called.
+ verify(mAppCallback).onCreated(mSipDelegate);
+ verify(mAppCallback, never()).onDestroyed(anyInt());
+ }
+
+ /**
+ * Test that when we move from changing tags state to the delegate being destroyed, we get the
+ * correct onDestroy event sent to the app.
+ */
+ @SmallTest
+ @Test
+ public void testDelegateChangingDeniedTagsChangingToDestroy() throws Exception {
+ DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
+ mSipDelegate);
+ Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
+ stateTracker.sipDelegateConnected(deniedTags);
+ // SipDelegate created
+ verify(mAppCallback).onCreated(mSipDelegate);
+ DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
+ .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG)
+ .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG,
+ DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED)
+ .build();
+ stateTracker.onRegistrationStateChanged(regState);
+ verify(mAppCallback).onFeatureTagStatusChanged(any(),
+ eq(new ArrayList<>(deniedTags)));
+ // Simulate underlying SipDelegate switch
+ stateTracker.sipDelegateChanging(
+ DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING);
+ // Destroy
+ stateTracker.sipDelegateDestroyed(
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+
+ // onFeatureTagStatusChanged should now be called with registered features overridden with
+ // DEREGISTERING_REASON_DESTROY_PENDING
+ DelegateRegistrationState overrideRegState = new DelegateRegistrationState.Builder()
+ .addDeregisteringFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG,
+ DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING)
+ // Deregistered should stay the same.
+ .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG,
+ DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED)
+ .build();
+ // Verify registration state through process:
+ ArgumentCaptor<DelegateRegistrationState> regCaptor =
+ ArgumentCaptor.forClass(DelegateRegistrationState.class);
+ verify(mAppCallback, times(2)).onFeatureTagStatusChanged(regCaptor.capture(),
+ eq(new ArrayList<>(deniedTags)));
+ List<DelegateRegistrationState> testStates = regCaptor.getAllValues();
+ assertEquals(2, testStates.size());
+ // feature tags should first be registered
+ assertEquals(regState, testStates.get(0));
+ // registered feature tags should have moved to deregistering
+ assertEquals(overrideRegState, testStates.get(1));
+ //onCreate/onDestroy should only be called once.
+ verify(mAppCallback).onCreated(mSipDelegate);
+ verify(mAppCallback).onDestroyed(
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ }
+
+ private Set<FeatureTagState> getMmTelDeniedTag() {
+ Set<FeatureTagState> deniedTags = new ArraySet<>();
+ deniedTags.add(new FeatureTagState(ImsSignallingUtils.MMTEL_TAG,
+ SipDelegateManager.DENIED_REASON_NOT_ALLOWED));
+ return deniedTags;
+ }
+}
diff --git a/tests/src/com/android/services/telephony/rcs/ImsSignallingUtils.java b/tests/src/com/android/services/telephony/rcs/ImsSignallingUtils.java
new file mode 100644
index 0000000..d607f6d
--- /dev/null
+++ b/tests/src/com/android/services/telephony/rcs/ImsSignallingUtils.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 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.services.telephony.rcs;
+
+/**
+ * Various definitions and utilities related to IMS Signalling.
+ */
+public class ImsSignallingUtils {
+ public static final String MMTEL_TAG =
+ "+g.3gpp.iari-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel\"";
+ public static final String ONE_TO_ONE_CHAT_TAG =
+ "+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gppservice.ims.icsi.oma.cpm.msg\"";
+ public static final String GROUP_CHAT_TAG =
+ "+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gppservice.ims.icsi.oma.cpm.session\"";
+ public static final String FILE_TRANSFER_HTTP_TAG =
+ "+g.3gpp.iari-ref=\"urn%3Aurn-7%3A3gppapplication.ims.iari.rcs.fthttp\"";
+}
diff --git a/tests/src/com/android/services/telephony/rcs/MessageTransportStateTrackerTest.java b/tests/src/com/android/services/telephony/rcs/MessageTransportStateTrackerTest.java
new file mode 100644
index 0000000..5e05085
--- /dev/null
+++ b/tests/src/com/android/services/telephony/rcs/MessageTransportStateTrackerTest.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2020 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.services.telephony.rcs;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.os.RemoteException;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.SipMessage;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+@RunWith(AndroidJUnit4.class)
+public class MessageTransportStateTrackerTest extends TelephonyTestBase {
+ private static final int TEST_SUB_ID = 1;
+
+ private static final SipMessage TEST_MESSAGE = new SipMessage(
+ "INVITE sip:callee@ex.domain.com SIP/2.0",
+ "Via: SIP/2.0/UDP ex.place.com;branch=z9hG4bK776asdhds",
+ new byte[0]);
+
+ // Use for finer-grained control of when the Executor executes.
+ private static class PendingExecutor implements Executor {
+ private final ArrayList<Runnable> mPendingRunnables = new ArrayList<>();
+
+ @Override
+ public void execute(Runnable command) {
+ mPendingRunnables.add(command);
+ }
+
+ public void executePending() {
+ for (Runnable r : mPendingRunnables) {
+ r.run();
+ }
+ mPendingRunnables.clear();
+ }
+ }
+
+ @Mock private ISipDelegateMessageCallback mDelegateMessageCallback;
+ @Mock private ISipDelegate mISipDelegate;
+ @Mock private Consumer<Boolean> mMockCloseConsumer;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @SmallTest
+ @Test
+ public void testDelegateConnectionSendOutgoingMessage() throws Exception {
+ MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+ Runnable::run, mDelegateMessageCallback);
+
+ tracker.openTransport(mISipDelegate, Collections.emptySet());
+ tracker.getDelegateConnection().sendMessage(TEST_MESSAGE, 1 /*version*/);
+ verify(mISipDelegate).sendMessage(TEST_MESSAGE, 1 /*version*/);
+
+ doThrow(new RemoteException()).when(mISipDelegate).sendMessage(any(), anyLong());
+ tracker.getDelegateConnection().sendMessage(TEST_MESSAGE, 1 /*version*/);
+ verify(mDelegateMessageCallback).onMessageSendFailure(any(),
+ eq(SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD));
+
+ tracker.close(SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED);
+ tracker.getDelegateConnection().sendMessage(TEST_MESSAGE, 1 /*version*/);
+ verify(mDelegateMessageCallback).onMessageSendFailure(any(),
+ eq(SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED));
+ }
+
+ @SmallTest
+ @Test
+ public void testDelegateConnectionCloseGracefully() throws Exception {
+ PendingExecutor executor = new PendingExecutor();
+ MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+ executor, mDelegateMessageCallback);
+
+ tracker.openTransport(mISipDelegate, Collections.emptySet());
+ tracker.getDelegateConnection().sendMessage(TEST_MESSAGE, 1 /*version*/);
+ executor.executePending();
+ verify(mISipDelegate).sendMessage(TEST_MESSAGE, 1 /*version*/);
+ verify(mDelegateMessageCallback, never()).onMessageSendFailure(any(), anyInt());
+
+ // Use PendingExecutor a little weird here, we need to queue sendMessage first, even though
+ // closeGracefully will complete partly synchronously to test that the pending message will
+ // return MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION before the scheduled
+ // graceful close operation completes.
+ tracker.getDelegateConnection().sendMessage(TEST_MESSAGE, 1 /*version*/);
+ tracker.closeGracefully(
+ SipDelegateManager.MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION,
+ SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED,
+ mMockCloseConsumer);
+ verify(mMockCloseConsumer, never()).accept(any());
+ // resolve pending close operation
+ executor.executePending();
+ verify(mDelegateMessageCallback).onMessageSendFailure(any(),
+ eq(SipDelegateManager.MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION));
+ // Still should only report one call of sendMessage from before
+ verify(mISipDelegate).sendMessage(TEST_MESSAGE, 1 /*version*/);
+ verify(mMockCloseConsumer).accept(true);
+
+ // ensure that after close operation completes, we get the correct
+ // MESSAGE_FAILURE_REASON_DELEGATE_CLOSED message.
+ tracker.getDelegateConnection().sendMessage(TEST_MESSAGE, 1 /*version*/);
+ executor.executePending();
+ verify(mDelegateMessageCallback).onMessageSendFailure(any(),
+ eq(SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED));
+ // Still should only report one call of sendMessage from before
+ verify(mISipDelegate).sendMessage(TEST_MESSAGE, 1 /*version*/);
+ }
+
+ @SmallTest
+ @Test
+ public void testDelegateConnectionNotifyMessageReceived() throws Exception {
+ MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+ Runnable::run, mDelegateMessageCallback);
+ tracker.openTransport(mISipDelegate, Collections.emptySet());
+ tracker.getDelegateConnection().notifyMessageReceived("z9hG4bK776asdhds");
+ verify(mISipDelegate).notifyMessageReceived("z9hG4bK776asdhds");
+ }
+
+ @SmallTest
+ @Test
+ public void testDelegateConnectionNotifyMessageReceiveError() throws Exception {
+ MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+ Runnable::run, mDelegateMessageCallback);
+ tracker.openTransport(mISipDelegate, Collections.emptySet());
+ tracker.getDelegateConnection().notifyMessageReceiveError("z9hG4bK776asdhds",
+ SipDelegateManager.MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE);
+ verify(mISipDelegate).notifyMessageReceiveError("z9hG4bK776asdhds",
+ SipDelegateManager.MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE);
+ }
+
+ @SmallTest
+ @Test
+ public void testDelegateConnectionCloseDialog() throws Exception {
+ MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+ Runnable::run, mDelegateMessageCallback);
+ tracker.openTransport(mISipDelegate, Collections.emptySet());
+ tracker.getDelegateConnection().closeDialog("testCallId");
+ verify(mISipDelegate).closeDialog("testCallId");
+ }
+
+ @SmallTest
+ @Test
+ public void testDelegateOnMessageReceived() throws Exception {
+ MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+ Runnable::run, mDelegateMessageCallback);
+ tracker.openTransport(mISipDelegate, Collections.emptySet());
+
+ tracker.getMessageCallback().onMessageReceived(TEST_MESSAGE);
+ verify(mDelegateMessageCallback).onMessageReceived(TEST_MESSAGE);
+
+ doThrow(new RemoteException()).when(mDelegateMessageCallback).onMessageReceived(any());
+ tracker.getMessageCallback().onMessageReceived(TEST_MESSAGE);
+ verify(mISipDelegate).notifyMessageReceiveError(any(),
+ eq(SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD));
+ }
+
+ @SmallTest
+ @Test
+ public void testDelegateOnMessageReceivedClosedGracefully() throws Exception {
+ PendingExecutor executor = new PendingExecutor();
+ MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+ executor, mDelegateMessageCallback);
+ tracker.openTransport(mISipDelegate, Collections.emptySet());
+
+ tracker.getMessageCallback().onMessageReceived(TEST_MESSAGE);
+ executor.executePending();
+ verify(mDelegateMessageCallback).onMessageReceived(TEST_MESSAGE);
+
+ tracker.getMessageCallback().onMessageReceived(TEST_MESSAGE);
+ tracker.closeGracefully(
+ SipDelegateManager.MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION,
+ SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED,
+ mMockCloseConsumer);
+ executor.executePending();
+ // Incoming SIP message should not be blocked by closeGracefully
+ verify(mDelegateMessageCallback, times(2)).onMessageReceived(TEST_MESSAGE);
+ }
+
+ @SmallTest
+ @Test
+ public void testDelegateOnMessageSent() throws Exception {
+ MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+ Runnable::run, mDelegateMessageCallback);
+ tracker.openTransport(mISipDelegate, Collections.emptySet());
+ tracker.getMessageCallback().onMessageSent("z9hG4bK776asdhds");
+ verify(mDelegateMessageCallback).onMessageSent("z9hG4bK776asdhds");
+ }
+
+ @SmallTest
+ @Test
+ public void testDelegateonMessageSendFailure() throws Exception {
+ MessageTransportStateTracker tracker = new MessageTransportStateTracker(TEST_SUB_ID,
+ Runnable::run, mDelegateMessageCallback);
+ tracker.openTransport(mISipDelegate, Collections.emptySet());
+ tracker.getMessageCallback().onMessageSendFailure("z9hG4bK776asdhds",
+ SipDelegateManager.MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE);
+ verify(mDelegateMessageCallback).onMessageSendFailure("z9hG4bK776asdhds",
+ SipDelegateManager.MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE);
+ }
+}
diff --git a/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java b/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
index fbb270d..7e87dc7 100644
--- a/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
@@ -100,7 +100,8 @@
verify(mMockFeature).onRcsConnected(mFeatureManager);
// Disconnect
- mConnectorListener.getValue().connectionUnavailable();
+ mConnectorListener.getValue().connectionUnavailable(
+ FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED);
verify(mFeatureManager).unregisterImsRegistrationCallback(any());
verify(mMockFeature, times(2)).onRcsDisconnected();
@@ -193,7 +194,8 @@
public void testFeatureManagerDisconnectedAddFeature() {
RcsFeatureController controller = createFeatureController();
// Disconnect the RcsFeatureManager
- mConnectorListener.getValue().connectionUnavailable();
+ mConnectorListener.getValue().connectionUnavailable(
+ FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED);
controller.addFeature(mMockFeature, RcsFeatureController.Feature.class);
verify(mMockFeature).onRcsDisconnected();
@@ -205,7 +207,8 @@
IImsRegistrationCallback regCb = mock(IImsRegistrationCallback.class);
IImsCapabilityCallback capCb = mock(IImsCapabilityCallback.class);
// Disconnect the RcsFeatureManager
- mConnectorListener.getValue().connectionUnavailable();
+ mConnectorListener.getValue().connectionUnavailable(
+ FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED);
try {
controller.registerImsRegistrationCallback(0 /*subId*/, null /*callback*/);
diff --git a/tests/src/com/android/services/telephony/rcs/SipDelegateBinderConnectionTest.java b/tests/src/com/android/services/telephony/rcs/SipDelegateBinderConnectionTest.java
new file mode 100644
index 0000000..fa439dc
--- /dev/null
+++ b/tests/src/com/android/services/telephony/rcs/SipDelegateBinderConnectionTest.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2020 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.services.telephony.rcs;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.aidl.ISipDelegateStateCallback;
+import android.telephony.ims.aidl.ISipTransport;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+@RunWith(AndroidJUnit4.class)
+public class SipDelegateBinderConnectionTest extends TelephonyTestBase {
+ private static final int TEST_SUB_ID = 1;
+
+ @Mock private ISipDelegate mMockDelegate;
+ @Mock private ISipTransport mMockTransport;
+ @Mock private IBinder mTransportBinder;
+ @Mock private ISipDelegateMessageCallback mMessageCallback;
+ @Mock private DelegateBinderStateManager.StateCallback mMockStateCallback;
+ @Mock private BiConsumer<ISipDelegate, Set<FeatureTagState>> mMockCreatedCallback;
+ @Mock private Consumer<Integer> mMockDestroyedCallback;
+
+ private ArrayList<SipDelegateBinderConnection.StateCallback> mStateCallbackList;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ doReturn(mTransportBinder).when(mMockTransport).asBinder();
+ mStateCallbackList = new ArrayList<>(1);
+ mStateCallbackList.add(mMockStateCallback);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @SmallTest
+ @Test
+ public void testBaseImpl() throws Exception {
+ DelegateBinderStateManager baseConnection = new SipDelegateBinderConnectionStub(
+ getMmTelDeniedTag(), Runnable::run, mStateCallbackList);
+
+ baseConnection.create(null /*message cb*/, mMockCreatedCallback);
+ // Verify the stub simulates onCreated + on registration state callback.
+ verify(mMockCreatedCallback).accept(any(), eq(getMmTelDeniedTag()));
+ verify(mMockStateCallback).onRegistrationStateChanged(
+ new DelegateRegistrationState.Builder().build());
+
+ // Verify onDestroyed is called correctly.
+ baseConnection.destroy(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP,
+ mMockDestroyedCallback);
+ verify(mMockDestroyedCallback).accept(
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ }
+
+ @SmallTest
+ @Test
+ public void testCreateConnection() throws Exception {
+ DelegateRequest request = getDelegateRequest();
+ ArraySet<FeatureTagState> deniedTags = getMmTelDeniedTag();
+ SipDelegateBinderConnection connection = new SipDelegateBinderConnection(TEST_SUB_ID,
+ mMockTransport, request, deniedTags, Runnable::run, mStateCallbackList);
+ ISipDelegateStateCallback cb = createDelegateCaptureStateCallback(request, connection);
+
+ // Send onCreated callback from SipDelegate
+ ArrayList<FeatureTagState> delegateDeniedTags = new ArrayList<>(1);
+ delegateDeniedTags.add(new FeatureTagState(ImsSignallingUtils.GROUP_CHAT_TAG,
+ SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE));
+ assertNotNull(cb);
+ cb.onCreated(mMockDelegate, delegateDeniedTags);
+
+ ArraySet<FeatureTagState> totalDeniedTags = new ArraySet<>(deniedTags);
+ // Add the tags denied by the controller as well.
+ totalDeniedTags.addAll(delegateDeniedTags);
+ // The callback should contain the controller and delegate denied tags in the callback.
+ verify(mMockCreatedCallback).accept(mMockDelegate, totalDeniedTags);
+ }
+
+ @SmallTest
+ @Test
+ public void testCreateConnectionServiceDead() throws Exception {
+ DelegateRequest request = getDelegateRequest();
+ ArraySet<FeatureTagState> deniedTags = getMmTelDeniedTag();
+ SipDelegateBinderConnection connection = new SipDelegateBinderConnection(TEST_SUB_ID,
+ mMockTransport, request, deniedTags, Runnable::run, mStateCallbackList);
+ doThrow(new RemoteException()).when(mMockTransport).createSipDelegate(eq(TEST_SUB_ID),
+ any(), any(), any());
+ ISipDelegateStateCallback cb = createDelegateCaptureStateCallback(request, connection);
+ assertNull(cb);
+ }
+
+ @SmallTest
+ @Test
+ public void testDestroyConnection() throws Exception {
+ DelegateRequest request = getDelegateRequest();
+ ArraySet<FeatureTagState> deniedTags = getMmTelDeniedTag();
+ SipDelegateBinderConnection connection = new SipDelegateBinderConnection(TEST_SUB_ID,
+ mMockTransport, request, deniedTags, Runnable::run, mStateCallbackList);
+ ISipDelegateStateCallback cb = createDelegateCaptureStateCallback(request, connection);
+ assertNotNull(cb);
+ cb.onCreated(mMockDelegate, null /*denied*/);
+ verify(mMockCreatedCallback).accept(mMockDelegate, deniedTags);
+
+ // call Destroy on the SipDelegate
+ destroy(connection, SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ cb.onDestroyed(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ verify(mMockDestroyedCallback).accept(
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ }
+
+ @SmallTest
+ @Test
+ public void testDestroyConnectionDead() throws Exception {
+ DelegateRequest request = getDelegateRequest();
+ ArraySet<FeatureTagState> deniedTags = getMmTelDeniedTag();
+ SipDelegateBinderConnection connection = new SipDelegateBinderConnection(TEST_SUB_ID,
+ mMockTransport, request, deniedTags, Runnable::run, mStateCallbackList);
+ ISipDelegateStateCallback cb = createDelegateCaptureStateCallback(request, connection);
+ assertNotNull(cb);
+ cb.onCreated(mMockDelegate, null /*denied*/);
+ verify(mMockCreatedCallback).accept(mMockDelegate, deniedTags);
+
+ // try to destroy when dead and ensure callback is still called.
+ doThrow(new RemoteException()).when(mMockTransport).destroySipDelegate(any(), anyInt());
+ destroy(connection, SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ verify(mMockDestroyedCallback).accept(
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ }
+
+ @SmallTest
+ @Test
+ public void testStateCallback() throws Exception {
+ DelegateRequest request = getDelegateRequest();
+ ArraySet<FeatureTagState> deniedTags = getMmTelDeniedTag();
+ SipDelegateBinderConnection connection = new SipDelegateBinderConnection(TEST_SUB_ID,
+ mMockTransport, request, deniedTags, Runnable::run, mStateCallbackList);
+ ISipDelegateStateCallback cb = createDelegateCaptureStateCallback(request, connection);
+ assertNotNull(cb);
+ cb.onCreated(mMockDelegate, new ArrayList<>(deniedTags));
+ verify(mMockCreatedCallback).accept(mMockDelegate, deniedTags);
+
+ SipDelegateImsConfiguration config = new SipDelegateImsConfiguration.Builder(1).build();
+ cb.onImsConfigurationChanged(config);
+ verify(mMockStateCallback).onImsConfigurationChanged(config);
+
+ DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
+ .addRegisteredFeatureTags(request.getFeatureTags()).build();
+ cb.onFeatureTagRegistrationChanged(regState);
+ verify(mMockStateCallback).onRegistrationStateChanged(regState);
+ }
+
+ private ISipDelegateStateCallback createDelegateCaptureStateCallback(
+ DelegateRequest r, SipDelegateBinderConnection c) throws Exception {
+ boolean isCreating = c.create(mMessageCallback, mMockCreatedCallback);
+ if (!isCreating) return null;
+ ArgumentCaptor<ISipDelegateStateCallback> stateCaptor =
+ ArgumentCaptor.forClass(ISipDelegateStateCallback.class);
+ verify(mMockTransport).createSipDelegate(eq(TEST_SUB_ID), eq(r), stateCaptor.capture(),
+ eq(mMessageCallback));
+ assertNotNull(stateCaptor.getValue());
+ return stateCaptor.getValue();
+ }
+
+ private void destroy(SipDelegateBinderConnection c, int reason) throws Exception {
+ c.destroy(reason, mMockDestroyedCallback);
+ verify(mMockTransport).destroySipDelegate(mMockDelegate, reason);
+ }
+
+ private DelegateRequest getDelegateRequest() {
+ ArraySet<String> featureTags = new ArraySet<>(2);
+ featureTags.add(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG);
+ featureTags.add(ImsSignallingUtils.GROUP_CHAT_TAG);
+ return new DelegateRequest(featureTags);
+ }
+
+ private ArraySet<FeatureTagState> getMmTelDeniedTag() {
+ ArraySet<FeatureTagState> deniedTags = new ArraySet<>();
+ deniedTags.add(new FeatureTagState(ImsSignallingUtils.MMTEL_TAG,
+ SipDelegateManager.DENIED_REASON_NOT_ALLOWED));
+ return deniedTags;
+ }
+}
diff --git a/tests/src/com/android/services/telephony/rcs/SipDelegateControllerTest.java b/tests/src/com/android/services/telephony/rcs/SipDelegateControllerTest.java
new file mode 100644
index 0000000..47b4808
--- /dev/null
+++ b/tests/src/com/android/services/telephony/rcs/SipDelegateControllerTest.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2020 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.services.telephony.rcs;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.aidl.ISipTransport;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+import com.android.TestExecutorService;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+@RunWith(AndroidJUnit4.class)
+public class SipDelegateControllerTest extends TelephonyTestBase {
+ private static final int TEST_SUB_ID = 1;
+
+ @Mock private ISipDelegate mMockSipDelegate;
+ @Mock private ISipTransport mMockSipTransport;
+ @Mock private MessageTransportStateTracker mMockMessageTracker;
+ @Mock private ISipDelegateMessageCallback mMockMessageCallback;
+ @Mock private DelegateStateTracker mMockDelegateStateTracker;
+ @Mock private DelegateBinderStateManager mMockBinderConnection;
+ @Captor private ArgumentCaptor<BiConsumer<ISipDelegate, Set<FeatureTagState>>> mCreatedCaptor;
+ @Captor private ArgumentCaptor<Consumer<Boolean>> mBooleanConsumerCaptor;
+ @Captor private ArgumentCaptor<Consumer<Integer>> mIntegerConsumerCaptor;
+
+ private ScheduledExecutorService mExecutorService;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ when(mMockMessageTracker.getMessageCallback()).thenReturn(mMockMessageCallback);
+ mExecutorService = new TestExecutorService();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mExecutorService.shutdownNow();
+ super.tearDown();
+ }
+
+ @SmallTest
+ @Test
+ public void testCreateDelegate() throws Exception {
+ DelegateRequest request = getBaseDelegateRequest();
+ SipDelegateController controller = getTestDelegateController(request,
+ Collections.emptySet());
+
+ doReturn(true).when(mMockBinderConnection).create(eq(mMockMessageCallback), any());
+ CompletableFuture<Boolean> future = controller.create(request.getFeatureTags(),
+ Collections.emptySet() /*denied tags*/);
+ BiConsumer<ISipDelegate, Set<FeatureTagState>> consumer =
+ verifyConnectionCreated(1);
+ assertNotNull(consumer);
+
+ assertFalse(future.isDone());
+ consumer.accept(mMockSipDelegate, Collections.emptySet());
+ assertTrue(future.get());
+ verify(mMockMessageTracker).openTransport(mMockSipDelegate, Collections.emptySet());
+ verify(mMockDelegateStateTracker).sipDelegateConnected(Collections.emptySet());
+ }
+
+ @SmallTest
+ @Test
+ public void testCreateDelegateTransportDied() throws Exception {
+ DelegateRequest request = getBaseDelegateRequest();
+ SipDelegateController controller = getTestDelegateController(request,
+ Collections.emptySet());
+
+ //Create operation fails
+ doReturn(false).when(mMockBinderConnection).create(eq(mMockMessageCallback), any());
+ CompletableFuture<Boolean> future = controller.create(request.getFeatureTags(),
+ Collections.emptySet() /*denied tags*/);
+
+ assertFalse(future.get());
+ }
+
+ @SmallTest
+ @Test
+ public void testDestroyDelegate() throws Exception {
+ DelegateRequest request = getBaseDelegateRequest();
+ SipDelegateController controller = getTestDelegateController(request,
+ Collections.emptySet());
+ createSipDelegate(request, controller);
+
+ CompletableFuture<Integer> pendingDestroy = controller.destroy(false /*force*/,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ assertFalse(pendingDestroy.isDone());
+ Consumer<Boolean> pendingClosedConsumer = verifyMessageTrackerCloseGracefully();
+ verify(mMockDelegateStateTracker).sipDelegateChanging(
+ DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING);
+
+ // verify we do not call destroy on the delegate until the message tracker releases the
+ // transport.
+ verify(mMockBinderConnection, never()).destroy(anyInt(), any());
+ pendingClosedConsumer.accept(true);
+ Consumer<Integer> pendingDestroyedConsumer = verifyBinderConnectionDestroy();
+ pendingDestroyedConsumer.accept(
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ verify(mMockDelegateStateTracker).sipDelegateDestroyed(
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ assertTrue(pendingDestroy.isDone());
+ assertEquals(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP,
+ pendingDestroy.get().intValue());
+ }
+
+ @SmallTest
+ @Test
+ public void testDestroyDelegateForce() throws Exception {
+ DelegateRequest request = getBaseDelegateRequest();
+ SipDelegateController controller = getTestDelegateController(request,
+ Collections.emptySet());
+ createSipDelegate(request, controller);
+
+ CompletableFuture<Integer> pendingDestroy = controller.destroy(true /*force*/,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ assertFalse(pendingDestroy.isDone());
+ // Do not wait for message transport close in this case.
+ verify(mMockMessageTracker).close(
+ SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED);
+ verify(mMockDelegateStateTracker, never()).sipDelegateChanging(
+ DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING);
+
+ //verify destroy is called
+ Consumer<Integer> pendingDestroyedConsumer = verifyBinderConnectionDestroy();
+ pendingDestroyedConsumer.accept(
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ verify(mMockDelegateStateTracker).sipDelegateDestroyed(
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ assertTrue(pendingDestroy.isDone());
+ assertEquals(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP,
+ pendingDestroy.get().intValue());
+ }
+
+ @SmallTest
+ @Test
+ public void testChangeSupportedFeatures() throws Exception {
+ DelegateRequest request = getBaseDelegateRequest();
+ SipDelegateController controller = getTestDelegateController(request,
+ Collections.emptySet());
+ createSipDelegate(request, controller);
+
+ Set<String> newFts = getBaseFTSet();
+ newFts.add(ImsSignallingUtils.GROUP_CHAT_TAG);
+ CompletableFuture<Boolean> pendingChange = controller.changeSupportedFeatureTags(
+ newFts, Collections.emptySet());
+ assertFalse(pendingChange.isDone());
+ // message tracker should close gracefully.
+ Consumer<Boolean> pendingClosedConsumer = verifyMessageTrackerCloseGracefully();
+ verify(mMockDelegateStateTracker).sipDelegateChanging(
+ DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING);
+ verify(mMockBinderConnection, never()).destroy(anyInt(), any());
+ pendingClosedConsumer.accept(true);
+ Consumer<Integer> pendingDestroyedConsumer = verifyBinderConnectionDestroy();
+ pendingDestroyedConsumer.accept(
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ verify(mMockDelegateStateTracker, never()).sipDelegateDestroyed(anyInt());
+
+ // This will cause any exceptions to be printed if something completed exceptionally.
+ assertNull(pendingChange.getNow(null));
+ BiConsumer<ISipDelegate, Set<FeatureTagState>> consumer =
+ verifyConnectionCreated(2);
+ assertNotNull(consumer);
+ consumer.accept(mMockSipDelegate, Collections.emptySet());
+ assertTrue(pendingChange.get());
+
+ verify(mMockMessageTracker, times(2)).openTransport(mMockSipDelegate,
+ Collections.emptySet());
+ verify(mMockDelegateStateTracker, times(2)).sipDelegateConnected(Collections.emptySet());
+ }
+
+ private void createSipDelegate(DelegateRequest request, SipDelegateController controller)
+ throws Exception {
+ doReturn(true).when(mMockBinderConnection).create(eq(mMockMessageCallback), any());
+ CompletableFuture<Boolean> future = controller.create(request.getFeatureTags(),
+ Collections.emptySet() /*denied tags*/);
+ BiConsumer<ISipDelegate, Set<FeatureTagState>> consumer =
+ verifyConnectionCreated(1);
+ assertNotNull(consumer);
+ consumer.accept(mMockSipDelegate, Collections.emptySet());
+ assertTrue(future.get());
+ }
+
+ private ArraySet<String> getBaseFTSet() {
+ ArraySet<String> request = new ArraySet<>();
+ request.add(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG);
+ return request;
+ }
+
+ private DelegateRequest getBaseDelegateRequest() {
+ return new DelegateRequest(getBaseFTSet());
+ }
+
+ private SipDelegateController getTestDelegateController(DelegateRequest request,
+ Set<FeatureTagState> deniedSet) {
+ return new SipDelegateController(TEST_SUB_ID, request, "", mMockSipTransport,
+ mExecutorService, mMockMessageTracker, mMockDelegateStateTracker,
+ (a, b, c, deniedFeatureSet, e, f) -> {
+ assertEquals(deniedSet, deniedFeatureSet);
+ return mMockBinderConnection;
+ });
+ }
+
+ private BiConsumer<ISipDelegate, Set<FeatureTagState>> verifyConnectionCreated(int numTimes) {
+ verify(mMockBinderConnection, times(numTimes)).create(eq(mMockMessageCallback),
+ mCreatedCaptor.capture());
+ return mCreatedCaptor.getValue();
+ }
+
+ private Consumer<Boolean> verifyMessageTrackerCloseGracefully() {
+ verify(mMockMessageTracker).closeGracefully(anyInt(), anyInt(),
+ mBooleanConsumerCaptor.capture());
+ return mBooleanConsumerCaptor.getValue();
+ }
+ private Consumer<Integer> verifyBinderConnectionDestroy() {
+ verify(mMockBinderConnection).destroy(anyInt(), mIntegerConsumerCaptor.capture());
+ return mIntegerConsumerCaptor.getValue();
+ }
+
+}
diff --git a/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java b/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java
new file mode 100644
index 0000000..8e10757
--- /dev/null
+++ b/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java
@@ -0,0 +1,844 @@
+/*
+ * Copyright (C) 2020 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.services.telephony.rcs;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+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 android.app.role.RoleManager;
+import android.os.IBinder;
+import android.os.UserHandle;
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.aidl.ISipTransport;
+import android.util.ArraySet;
+import android.util.Pair;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+import com.android.TestExecutorService;
+import com.android.ims.RcsFeatureManager;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+@RunWith(AndroidJUnit4.class)
+public class SipTransportControllerTest extends TelephonyTestBase {
+ private static final int TEST_SUB_ID = 1;
+ private static final String TEST_PACKAGE_NAME = "com.test_pkg";
+ private static final String TEST_PACKAGE_NAME_2 = "com.test_pkg2";
+ private static final int TIMEOUT_MS = 200;
+ private static final int THROTTLE_MS = 50;
+
+ private class SipDelegateControllerContainer {
+ public final int subId;
+ public final String packageName;
+ public final DelegateRequest delegateRequest;
+ public final SipDelegateController delegateController;
+ public final ISipDelegate mMockDelegate;
+ public final IBinder mMockDelegateBinder;
+
+ SipDelegateControllerContainer(int id, String name, DelegateRequest request) {
+ delegateController = mock(SipDelegateController.class);
+ mMockDelegate = mock(ISipDelegate.class);
+ mMockDelegateBinder = mock(IBinder.class);
+ doReturn(mMockDelegateBinder).when(mMockDelegate).asBinder();
+ doReturn(name).when(delegateController).getPackageName();
+ doReturn(request).when(delegateController).getInitialRequest();
+ doReturn(mMockDelegate).when(delegateController).getSipDelegateInterface();
+ subId = id;
+ packageName = name;
+ delegateRequest = request;
+ }
+ }
+
+ @Mock private RcsFeatureManager mRcsManager;
+ @Mock private ISipTransport mSipTransport;
+ @Mock private ISipDelegateConnectionStateCallback mMockStateCallback;
+ @Mock private ISipDelegateMessageCallback mMockMessageCallback;
+ @Mock private SipTransportController.SipDelegateControllerFactory
+ mMockDelegateControllerFactory;
+ @Mock private SipTransportController.RoleManagerAdapter mMockRoleManager;
+
+ private ScheduledExecutorService mExecutorService = null;
+ private final ArrayList<SipDelegateControllerContainer> mMockControllers = new ArrayList<>();
+ private final ArrayList<String> mSmsPackageName = new ArrayList<>(1);
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ doReturn(mSmsPackageName).when(mMockRoleManager).getRoleHolders(RoleManager.ROLE_SMS);
+ mSmsPackageName.add(TEST_PACKAGE_NAME);
+ doAnswer(invocation -> {
+ Integer subId = invocation.getArgument(0);
+ String packageName = invocation.getArgument(2);
+ DelegateRequest request = invocation.getArgument(1);
+ SipDelegateController c = getMockDelegateController(subId, packageName, request);
+ assertNotNull("create called with no corresponding controller set up", c);
+ return c;
+ }).when(mMockDelegateControllerFactory).create(anyInt(), any(), anyString(), any(),
+ any(), any(), any());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ boolean isShutdown = mExecutorService == null || mExecutorService.isShutdown();
+ if (!isShutdown) {
+ mExecutorService.shutdownNow();
+ }
+ }
+
+ @SmallTest
+ @Test
+ public void isSupportedRcsNotConnected() {
+ SipTransportController controller = createController(new TestExecutorService());
+ try {
+ controller.isSupported(TEST_SUB_ID);
+ fail();
+ } catch (ImsException e) {
+ assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
+ }
+ }
+
+ @SmallTest
+ @Test
+ public void isSupportedInvalidSubId() {
+ SipTransportController controller = createController(new TestExecutorService());
+ try {
+ controller.isSupported(TEST_SUB_ID + 1);
+ fail();
+ } catch (ImsException e) {
+ assertEquals(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION, e.getCode());
+ }
+ }
+
+ @SmallTest
+ @Test
+ public void isSupportedSubIdChanged() {
+ SipTransportController controller = createController(new TestExecutorService());
+ controller.onAssociatedSubscriptionUpdated(TEST_SUB_ID + 1);
+ try {
+ controller.isSupported(TEST_SUB_ID);
+ fail();
+ } catch (ImsException e) {
+ assertEquals(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION, e.getCode());
+ }
+ }
+
+ @SmallTest
+ @Test
+ public void isSupportedSipTransportAvailableRcsConnected() throws Exception {
+ SipTransportController controller = createController(new TestExecutorService());
+ doReturn(mSipTransport).when(mRcsManager).getSipTransport();
+ controller.onRcsConnected(mRcsManager);
+ try {
+ assertTrue(controller.isSupported(TEST_SUB_ID));
+ } catch (ImsException e) {
+ fail();
+ }
+ }
+
+ @SmallTest
+ @Test
+ public void isSupportedSipTransportNotAvailableRcsDisconnected() throws Exception {
+ SipTransportController controller = createController(new TestExecutorService());
+ doReturn(mSipTransport).when(mRcsManager).getSipTransport();
+ controller.onRcsConnected(mRcsManager);
+ controller.onRcsDisconnected();
+ try {
+ controller.isSupported(TEST_SUB_ID);
+ fail();
+ } catch (ImsException e) {
+ assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
+ }
+ }
+
+ @SmallTest
+ @Test
+ public void isSupportedSipTransportNotAvailableRcsConnected() throws Exception {
+ SipTransportController controller = createController(new TestExecutorService());
+ doReturn(null).when(mRcsManager).getSipTransport();
+ controller.onRcsConnected(mRcsManager);
+ try {
+ assertFalse(controller.isSupported(TEST_SUB_ID));
+ } catch (ImsException e) {
+ fail();
+ }
+ }
+
+ @SmallTest
+ @Test
+ public void isSupportedImsServiceNotAvailableRcsConnected() throws Exception {
+ SipTransportController controller = createController(new TestExecutorService());
+ doThrow(new ImsException("", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE))
+ .when(mRcsManager).getSipTransport();
+ controller.onRcsConnected(mRcsManager);
+ try {
+ controller.isSupported(TEST_SUB_ID);
+ fail();
+ } catch (ImsException e) {
+ assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
+ }
+ }
+
+ @SmallTest
+ @Test
+ public void createImsServiceAvailableSubIdIncorrect() throws Exception {
+ SipTransportController controller = createController(new TestExecutorService());
+ doReturn(mSipTransport).when(mRcsManager).getSipTransport();
+ controller.onRcsConnected(mRcsManager);
+ try {
+ controller.createSipDelegate(TEST_SUB_ID + 1,
+ new DelegateRequest(Collections.emptySet()), TEST_PACKAGE_NAME,
+ mMockStateCallback, mMockMessageCallback);
+ fail();
+ } catch (ImsException e) {
+ assertEquals(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION, e.getCode());
+ }
+ }
+
+ @SmallTest
+ @Test
+ public void createImsServiceDoesntSupportTransport() throws Exception {
+ SipTransportController controller = createController(new TestExecutorService());
+ doReturn(null).when(mRcsManager).getSipTransport();
+ controller.onRcsConnected(mRcsManager);
+ try {
+ controller.createSipDelegate(TEST_SUB_ID,
+ new DelegateRequest(Collections.emptySet()), TEST_PACKAGE_NAME,
+ mMockStateCallback, mMockMessageCallback);
+ fail();
+ } catch (ImsException e) {
+ assertEquals(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION, e.getCode());
+ }
+ }
+
+ @SmallTest
+ @Test
+ public void createImsServiceNotAvailable() throws Exception {
+ SipTransportController controller = createController(new TestExecutorService());
+ doThrow(new ImsException("", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE))
+ .when(mRcsManager).getSipTransport();
+ // No RCS connected message
+ try {
+ controller.createSipDelegate(TEST_SUB_ID,
+ new DelegateRequest(Collections.emptySet()), TEST_PACKAGE_NAME,
+ mMockStateCallback, mMockMessageCallback);
+ fail();
+ } catch (ImsException e) {
+ assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
+ }
+ }
+
+ @SmallTest
+ @Test
+ public void basicCreate() throws Exception {
+ SipTransportController controller = setupLiveTransportController();
+
+ DelegateRequest r = getBaseDelegateRequest();
+
+ SipDelegateController c = injectMockDelegateController(TEST_PACKAGE_NAME, r);
+ createDelegateAndVerify(controller, c, r, r.getFeatureTags(), Collections.emptySet(),
+ TEST_PACKAGE_NAME);
+ }
+
+ @SmallTest
+ @Test
+ public void basicCreateDestroy() throws Exception {
+ SipTransportController controller = setupLiveTransportController();
+
+ DelegateRequest r = getBaseDelegateRequest();
+ SipDelegateController c = injectMockDelegateController(TEST_PACKAGE_NAME, r);
+ createDelegateAndVerify(controller, c, r, r.getFeatureTags(), Collections.emptySet(),
+ TEST_PACKAGE_NAME);
+
+ destroyDelegateAndVerify(controller, c, false,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ }
+
+ @SmallTest
+ @Test
+ public void testCreateButNotInRole() throws Exception {
+ SipTransportController controller = setupLiveTransportController();
+
+ DelegateRequest r = getBaseDelegateRequest();
+ Set<FeatureTagState> getDeniedTags = getDeniedTagsForReason(r.getFeatureTags(),
+ SipDelegateManager.DENIED_REASON_NOT_ALLOWED);
+
+ // Try to create a SipDelegate for a package that is not the default sms role.
+ SipDelegateController c = injectMockDelegateController(TEST_PACKAGE_NAME_2, r);
+ createDelegateAndVerify(controller, c, r, Collections.emptySet(), getDeniedTags,
+ TEST_PACKAGE_NAME_2);
+ }
+
+ @SmallTest
+ @Test
+ public void createTwoAndDenyOverlappingTags() throws Exception {
+ SipTransportController controller = setupLiveTransportController();
+
+ // First delegate requests RCS message + File transfer
+ ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+ firstDelegate.remove(ImsSignallingUtils.GROUP_CHAT_TAG);
+ DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate);
+ SipDelegateController c1 = injectMockDelegateController(TEST_PACKAGE_NAME,
+ firstDelegateRequest);
+ createDelegateAndVerify(controller, c1, firstDelegateRequest, firstDelegate,
+ Collections.emptySet(), TEST_PACKAGE_NAME);
+
+ // First delegate requests RCS message + Group RCS message. For this delegate, single RCS
+ // message should be denied.
+ ArraySet<String> secondDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+ secondDelegate.remove(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG);
+ DelegateRequest secondDelegateRequest = new DelegateRequest(secondDelegate);
+ Pair<Set<String>, Set<FeatureTagState>> grantedAndDenied = getAllowedAndDeniedTagsForConfig(
+ secondDelegateRequest, SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE,
+ firstDelegate);
+ SipDelegateController c2 = injectMockDelegateController(TEST_PACKAGE_NAME,
+ secondDelegateRequest);
+ createDelegateAndVerify(controller, c2, secondDelegateRequest, grantedAndDenied.first,
+ grantedAndDenied.second, TEST_PACKAGE_NAME, 1);
+ }
+
+ @SmallTest
+ @Test
+ public void createTwoAndTriggerRoleChange() throws Exception {
+ SipTransportController controller = setupLiveTransportController();
+
+ DelegateRequest firstDelegateRequest = getBaseDelegateRequest();
+ Set<FeatureTagState> firstDeniedTags = getDeniedTagsForReason(
+ firstDelegateRequest.getFeatureTags(),
+ SipDelegateManager.DENIED_REASON_NOT_ALLOWED);
+ SipDelegateController c1 = injectMockDelegateController(TEST_PACKAGE_NAME,
+ firstDelegateRequest);
+ createDelegateAndVerify(controller, c1, firstDelegateRequest,
+ firstDelegateRequest.getFeatureTags(), Collections.emptySet(), TEST_PACKAGE_NAME);
+
+ DelegateRequest secondDelegateRequest = getBaseDelegateRequest();
+ Set<FeatureTagState> secondDeniedTags = getDeniedTagsForReason(
+ secondDelegateRequest.getFeatureTags(),
+ SipDelegateManager.DENIED_REASON_NOT_ALLOWED);
+ // Try to create a SipDelegate for a package that is not the default sms role.
+ SipDelegateController c2 = injectMockDelegateController(TEST_PACKAGE_NAME_2,
+ secondDelegateRequest);
+ createDelegateAndVerify(controller, c2, secondDelegateRequest, Collections.emptySet(),
+ secondDeniedTags, TEST_PACKAGE_NAME_2, 1);
+
+ // now swap the SMS role.
+ CompletableFuture<Boolean> pendingC1Change = setChangeSupportedFeatureTagsFuture(c1,
+ Collections.emptySet(), firstDeniedTags);
+ CompletableFuture<Boolean> pendingC2Change = setChangeSupportedFeatureTagsFuture(c2,
+ secondDelegateRequest.getFeatureTags(), Collections.emptySet());
+ setSmsRoleAndEvaluate(controller, TEST_PACKAGE_NAME_2);
+ // trigger completion stage to run
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ verify(c1).changeSupportedFeatureTags(Collections.emptySet(), firstDeniedTags);
+ // we should not get a change for c2 until pendingC1Change completes.
+ verify(c2, never()).changeSupportedFeatureTags(secondDelegateRequest.getFeatureTags(),
+ Collections.emptySet());
+ // ensure we are not blocking executor here
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ completePendingChange(pendingC1Change, true);
+ // trigger completion stage to run
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ verify(c2).changeSupportedFeatureTags(secondDelegateRequest.getFeatureTags(),
+ Collections.emptySet());
+ // ensure we are not blocking executor here
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ completePendingChange(pendingC2Change, true);
+ }
+
+ @SmallTest
+ @Test
+ public void createTwoAndDestroyOlder() throws Exception {
+ SipTransportController controller = setupLiveTransportController();
+
+ // First delegate requests RCS message + File transfer
+ ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+ firstDelegate.remove(ImsSignallingUtils.GROUP_CHAT_TAG);
+ DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate);
+ SipDelegateController c1 = injectMockDelegateController(TEST_PACKAGE_NAME,
+ firstDelegateRequest);
+ createDelegateAndVerify(controller, c1, firstDelegateRequest, firstDelegate,
+ Collections.emptySet(), TEST_PACKAGE_NAME);
+
+ // First delegate requests RCS message + Group RCS message. For this delegate, single RCS
+ // message should be denied.
+ ArraySet<String> secondDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+ secondDelegate.remove(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG);
+ DelegateRequest secondDelegateRequest = new DelegateRequest(secondDelegate);
+ Pair<Set<String>, Set<FeatureTagState>> grantedAndDenied = getAllowedAndDeniedTagsForConfig(
+ secondDelegateRequest, SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE,
+ firstDelegate);
+ SipDelegateController c2 = injectMockDelegateController(TEST_PACKAGE_NAME,
+ secondDelegateRequest);
+ createDelegateAndVerify(controller, c2, secondDelegateRequest, grantedAndDenied.first,
+ grantedAndDenied.second, TEST_PACKAGE_NAME, 1);
+
+ // Destroy the firstDelegate, which should now cause all previously denied tags to be
+ // granted to the new delegate.
+ CompletableFuture<Boolean> pendingC2Change = setChangeSupportedFeatureTagsFuture(c2,
+ secondDelegate, Collections.emptySet());
+ destroyDelegateAndVerify(controller, c1, false /*force*/,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ // wait for create to be processed.
+ assertTrue(waitForExecutorAction(mExecutorService, TIMEOUT_MS));
+ verify(c2).changeSupportedFeatureTags(secondDelegate, Collections.emptySet());
+ completePendingChange(pendingC2Change, true);
+ }
+
+ @SmallTest
+ @Test
+ public void testThrottling() throws Exception {
+ SipTransportController controller = setupLiveTransportController(THROTTLE_MS);
+
+ // First delegate requests RCS message + File transfer
+ ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+ firstDelegate.remove(ImsSignallingUtils.GROUP_CHAT_TAG);
+ DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate);
+ SipDelegateController c1 = injectMockDelegateController(TEST_PACKAGE_NAME,
+ firstDelegateRequest);
+ CompletableFuture<Boolean> pendingC1Change = createDelegate(controller, c1,
+ firstDelegateRequest, firstDelegate, Collections.emptySet(), TEST_PACKAGE_NAME);
+
+ // Request RCS message + group RCS Message. For this delegate, single RCS message should be
+ // denied.
+ ArraySet<String> secondDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+ secondDelegate.remove(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG);
+ DelegateRequest secondDelegateRequest = new DelegateRequest(secondDelegate);
+ Pair<Set<String>, Set<FeatureTagState>> grantedAndDeniedC2 =
+ getAllowedAndDeniedTagsForConfig(secondDelegateRequest,
+ SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE, firstDelegate);
+ SipDelegateController c2 = injectMockDelegateController(TEST_PACKAGE_NAME,
+ secondDelegateRequest);
+ CompletableFuture<Boolean> pendingC2Change = createDelegate(controller, c2,
+ secondDelegateRequest, grantedAndDeniedC2.first, grantedAndDeniedC2.second,
+ TEST_PACKAGE_NAME);
+
+ // Request group RCS message + file transfer. All should be denied at first
+ ArraySet<String> thirdDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+ thirdDelegate.remove(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG);
+ DelegateRequest thirdDelegateRequest = new DelegateRequest(thirdDelegate);
+ Pair<Set<String>, Set<FeatureTagState>> grantedAndDeniedC3 =
+ getAllowedAndDeniedTagsForConfig(thirdDelegateRequest,
+ SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE, firstDelegate,
+ grantedAndDeniedC2.first);
+ SipDelegateController c3 = injectMockDelegateController(TEST_PACKAGE_NAME,
+ thirdDelegateRequest);
+ CompletableFuture<Boolean> pendingC3Change = createDelegate(controller, c3,
+ thirdDelegateRequest, grantedAndDeniedC3.first, grantedAndDeniedC3.second,
+ TEST_PACKAGE_NAME);
+
+ assertTrue(scheduleDelayedWait(2 * THROTTLE_MS));
+ verifyDelegateChanged(c1, pendingC1Change, firstDelegate, Collections.emptySet(), 0);
+ verifyDelegateChanged(c2, pendingC2Change, grantedAndDeniedC2.first,
+ grantedAndDeniedC2.second, 0);
+ verifyDelegateChanged(c3, pendingC3Change, grantedAndDeniedC3.first,
+ grantedAndDeniedC3.second, 0);
+
+ // Destroy the first and second controller in quick succession, this should only generate
+ // one reevaluate for the third controller.
+ CompletableFuture<Boolean> pendingChangeC3 = setChangeSupportedFeatureTagsFuture(
+ c3, thirdDelegate, Collections.emptySet());
+ CompletableFuture<Integer> pendingDestroyC1 = destroyDelegate(controller, c1,
+ false /*force*/,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ CompletableFuture<Integer> pendingDestroyC2 = destroyDelegate(controller, c2,
+ false /*force*/,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ assertTrue(scheduleDelayedWait(2 * THROTTLE_MS));
+ verifyDestroyDelegate(controller, c1, pendingDestroyC1, false /*force*/,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ verifyDestroyDelegate(controller, c2, pendingDestroyC2, false /*force*/,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+
+ // All requested features should now be granted
+ completePendingChange(pendingChangeC3, true);
+ verify(c3).changeSupportedFeatureTags(thirdDelegate, Collections.emptySet());
+ // In total reeval should have only been called twice.
+ verify(c3, times(2)).changeSupportedFeatureTags(any(), any());
+ }
+
+ @SmallTest
+ @Test
+ public void testSubIdChangeDestroyTriggered() throws Exception {
+ SipTransportController controller = setupLiveTransportController();
+
+ ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+ DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate);
+ SipDelegateController c1 = injectMockDelegateController(TEST_PACKAGE_NAME,
+ firstDelegateRequest);
+ createDelegateAndVerify(controller, c1, firstDelegateRequest, firstDelegate,
+ Collections.emptySet(), TEST_PACKAGE_NAME);
+
+ CompletableFuture<Integer> pendingDestroy = setDestroyFuture(c1, true,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
+ controller.onAssociatedSubscriptionUpdated(TEST_SUB_ID + 1);
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ verifyDestroyDelegate(controller, c1, pendingDestroy, true /*force*/,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
+ }
+
+ @SmallTest
+ @Test
+ public void testRcsManagerGoneDestroyTriggered() throws Exception {
+ SipTransportController controller = setupLiveTransportController();
+
+ ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+ DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate);
+ SipDelegateController c1 = injectMockDelegateController(TEST_PACKAGE_NAME,
+ firstDelegateRequest);
+ createDelegateAndVerify(controller, c1, firstDelegateRequest, firstDelegate,
+ Collections.emptySet(), TEST_PACKAGE_NAME);
+
+ CompletableFuture<Integer> pendingDestroy = setDestroyFuture(c1, true,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD);
+ controller.onRcsDisconnected();
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ verifyDestroyDelegate(controller, c1, pendingDestroy, true /*force*/,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD);
+ }
+
+ @SmallTest
+ @Test
+ public void testDestroyTriggered() throws Exception {
+ SipTransportController controller = setupLiveTransportController();
+
+ ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+ DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate);
+ SipDelegateController c1 = injectMockDelegateController(TEST_PACKAGE_NAME,
+ firstDelegateRequest);
+ createDelegateAndVerify(controller, c1, firstDelegateRequest, firstDelegate,
+ Collections.emptySet(), TEST_PACKAGE_NAME);
+
+ CompletableFuture<Integer> pendingDestroy = setDestroyFuture(c1, true,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
+ controller.onDestroy();
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ // verify change was called.
+ verify(c1).destroy(true /*force*/,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
+ // ensure thread is not blocked while waiting for pending complete.
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ completePendingDestroy(pendingDestroy,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
+ }
+
+ @SmallTest
+ @Test
+ public void testTimingSubIdChangedAndCreateNewSubId() throws Exception {
+ SipTransportController controller = setupLiveTransportController(THROTTLE_MS);
+
+ ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags());
+ DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate);
+ SipDelegateController c1 = injectMockDelegateController(TEST_PACKAGE_NAME,
+ firstDelegateRequest);
+ CompletableFuture<Boolean> pendingC1Change = createDelegate(controller, c1,
+ firstDelegateRequest, firstDelegate, Collections.emptySet(), TEST_PACKAGE_NAME);
+ assertTrue(scheduleDelayedWait(2 * THROTTLE_MS));
+ verifyDelegateChanged(c1, pendingC1Change, firstDelegate, Collections.emptySet(), 0);
+
+
+ CompletableFuture<Integer> pendingDestroy = setDestroyFuture(c1, true,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
+ // triggers reeval now.
+ controller.onAssociatedSubscriptionUpdated(TEST_SUB_ID + 1);
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+
+ // mock a second delegate with the new subId associated with the slot.
+ ArraySet<String> secondDelegate = new ArraySet<>();
+ secondDelegate.add(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG);
+ secondDelegate.add(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG);
+ DelegateRequest secondDelegateRequest = new DelegateRequest(secondDelegate);
+ SipDelegateController c2 = injectMockDelegateController(TEST_SUB_ID + 1,
+ TEST_PACKAGE_NAME, secondDelegateRequest);
+ CompletableFuture<Boolean> pendingC2Change = createDelegate(controller, c2,
+ TEST_SUB_ID + 1, secondDelegateRequest, secondDelegate,
+ Collections.emptySet(), TEST_PACKAGE_NAME);
+ assertTrue(scheduleDelayedWait(THROTTLE_MS));
+
+ //trigger destroyed event
+ verifyDestroyDelegate(controller, c1, pendingDestroy, true /*force*/,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN);
+ assertTrue(scheduleDelayedWait(2 * THROTTLE_MS));
+ verifyDelegateChanged(c2, pendingC2Change, secondDelegate, Collections.emptySet(), 0);
+ }
+
+ @SafeVarargs
+ private final Pair<Set<String>, Set<FeatureTagState>> getAllowedAndDeniedTagsForConfig(
+ DelegateRequest r, int denyReason, Set<String>... previousRequestedTagSets) {
+ ArraySet<String> rejectedTags = new ArraySet<>(r.getFeatureTags());
+ ArraySet<String> grantedTags = new ArraySet<>(r.getFeatureTags());
+ Set<String> previousRequestedTags = new ArraySet<>();
+ for (Set<String> s : previousRequestedTagSets) {
+ previousRequestedTags.addAll(s);
+ }
+ rejectedTags.retainAll(previousRequestedTags);
+ grantedTags.removeAll(previousRequestedTags);
+ Set<FeatureTagState> deniedTags = getDeniedTagsForReason(rejectedTags, denyReason);
+ return new Pair<>(grantedTags, deniedTags);
+ }
+
+ private void completePendingChange(CompletableFuture<Boolean> change, boolean result) {
+ mExecutorService.execute(() -> change.complete(result));
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ }
+
+ private void completePendingDestroy(CompletableFuture<Integer> destroy, int result) {
+ mExecutorService.execute(() -> destroy.complete(result));
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ }
+
+ private SipTransportController setupLiveTransportController() throws Exception {
+ return setupLiveTransportController(0 /*throttleMs*/);
+ }
+
+ private SipTransportController setupLiveTransportController(int throttleMs) throws Exception {
+ mExecutorService = Executors.newSingleThreadScheduledExecutor();
+ SipTransportController controller = createControllerAndThrottle(mExecutorService,
+ throttleMs);
+ doReturn(mSipTransport).when(mRcsManager).getSipTransport();
+ controller.onAssociatedSubscriptionUpdated(TEST_SUB_ID);
+ controller.onRcsConnected(mRcsManager);
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ return controller;
+ }
+
+ private void createDelegateAndVerify(SipTransportController controller,
+ SipDelegateController delegateController, DelegateRequest r, Set<String> allowedTags,
+ Set<FeatureTagState> deniedTags, String packageName,
+ int numPreviousChanges) throws ImsException {
+
+ CompletableFuture<Boolean> pendingChange = createDelegate(controller, delegateController, r,
+ allowedTags, deniedTags, packageName);
+ verifyDelegateChanged(delegateController, pendingChange, allowedTags, deniedTags,
+ numPreviousChanges);
+ }
+
+ private void createDelegateAndVerify(SipTransportController controller,
+ SipDelegateController delegateController, DelegateRequest r, Set<String> allowedTags,
+ Set<FeatureTagState> deniedTags, String packageName) throws ImsException {
+ createDelegateAndVerify(controller, delegateController, r, allowedTags, deniedTags,
+ packageName, 0);
+ }
+
+ private CompletableFuture<Boolean> createDelegate(SipTransportController controller,
+ SipDelegateController delegateController, int subId, DelegateRequest r,
+ Set<String> allowedTags, Set<FeatureTagState> deniedTags, String packageName) {
+ CompletableFuture<Boolean> pendingChange = setChangeSupportedFeatureTagsFuture(
+ delegateController, allowedTags, deniedTags);
+ try {
+ controller.createSipDelegate(subId, r, packageName, mMockStateCallback,
+ mMockMessageCallback);
+ } catch (ImsException e) {
+ fail("ImsException thrown:" + e);
+ }
+ // move to internal & schedule eval
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ // reeval
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ return pendingChange;
+ }
+
+ private CompletableFuture<Boolean> createDelegate(SipTransportController controller,
+ SipDelegateController delegateController, DelegateRequest r, Set<String> allowedTags,
+ Set<FeatureTagState> deniedTags, String packageName) throws ImsException {
+ return createDelegate(controller, delegateController, TEST_SUB_ID, r, allowedTags,
+ deniedTags, packageName);
+ }
+
+ private void verifyDelegateChanged(SipDelegateController delegateController,
+ CompletableFuture<Boolean> pendingChange, Set<String> allowedTags,
+ Set<FeatureTagState> deniedTags, int numPreviousChangeStages) {
+ // empty the queue of pending changeSupportedFeatureTags before running the one we are
+ // interested in, since the reevaluate waits for one stage to complete before moving to the
+ // next.
+ for (int i = 0; i < numPreviousChangeStages + 1; i++) {
+ assertTrue(waitForExecutorAction(mExecutorService, TIMEOUT_MS));
+ }
+ // verify change was called.
+ verify(delegateController).changeSupportedFeatureTags(allowedTags, deniedTags);
+ // ensure thread is not blocked while waiting for pending complete.
+ assertTrue(waitForExecutorAction(mExecutorService, TIMEOUT_MS));
+ completePendingChange(pendingChange, true);
+ // process pending change.
+ assertTrue(waitForExecutorAction(mExecutorService, TIMEOUT_MS));
+ }
+
+ private void destroyDelegateAndVerify(SipTransportController controller,
+ SipDelegateController delegateController, boolean force, int reason) {
+ CompletableFuture<Integer> pendingDestroy = destroyDelegate(controller, delegateController,
+ force, reason);
+ verifyDestroyDelegate(controller, delegateController, pendingDestroy, force, reason);
+ }
+
+ private CompletableFuture<Integer> destroyDelegate(SipTransportController controller,
+ SipDelegateController delegateController, boolean force, int reason) {
+ CompletableFuture<Integer> pendingDestroy = setDestroyFuture(delegateController, force,
+ reason);
+ controller.destroySipDelegate(TEST_SUB_ID, delegateController.getSipDelegateInterface(),
+ reason);
+ // move to internal & schedule eval
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ // reeval
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ return pendingDestroy;
+ }
+
+ private void verifyDestroyDelegate(SipTransportController controller,
+ SipDelegateController delegateController, CompletableFuture<Integer> pendingDestroy,
+ boolean force, int reason) {
+ // verify destroy was called.
+ verify(delegateController).destroy(force, reason);
+ // ensure thread is not blocked while waiting for pending complete.
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ completePendingDestroy(pendingDestroy, reason);
+ }
+
+ private DelegateRequest getBaseDelegateRequest() {
+ Set<String> featureTags = new ArraySet<>();
+ featureTags.add(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG);
+ featureTags.add(ImsSignallingUtils.GROUP_CHAT_TAG);
+ featureTags.add(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG);
+ return new DelegateRequest(featureTags);
+ }
+
+ private Set<FeatureTagState> getBaseDeniedSet() {
+ Set<FeatureTagState> deniedTags = new ArraySet<>();
+ deniedTags.add(new FeatureTagState(ImsSignallingUtils.MMTEL_TAG,
+ SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE));
+ return deniedTags;
+ }
+
+ private Set<FeatureTagState> getDeniedTagsForReason(Set<String> deniedTags, int reason) {
+ return deniedTags.stream().map(t -> new FeatureTagState(t, reason))
+ .collect(Collectors.toSet());
+ }
+
+ private SipDelegateController injectMockDelegateController(String packageName,
+ DelegateRequest r) {
+ return injectMockDelegateController(TEST_SUB_ID, packageName, r);
+ }
+
+ private SipDelegateController injectMockDelegateController(int subId, String packageName,
+ DelegateRequest r) {
+ SipDelegateControllerContainer c = new SipDelegateControllerContainer(subId,
+ packageName, r);
+ mMockControllers.add(c);
+ return c.delegateController;
+ }
+
+ private SipDelegateController getMockDelegateController(int subId, String packageName,
+ DelegateRequest r) {
+ return mMockControllers.stream()
+ .filter(c -> c.subId == subId && c.packageName.equals(packageName)
+ && c.delegateRequest.equals(r))
+ .map(c -> c.delegateController).findFirst().orElse(null);
+ }
+
+ private CompletableFuture<Boolean> setChangeSupportedFeatureTagsFuture(SipDelegateController c,
+ Set<String> supportedSet, Set<FeatureTagState> deniedSet) {
+ CompletableFuture<Boolean> result = new CompletableFuture<>();
+ doReturn(result).when(c).changeSupportedFeatureTags(eq(supportedSet), eq(deniedSet));
+ return result;
+ }
+
+ private CompletableFuture<Integer> setDestroyFuture(SipDelegateController c, boolean force,
+ int destroyReason) {
+ CompletableFuture<Integer> result = new CompletableFuture<>();
+ doReturn(result).when(c).destroy(force, destroyReason);
+ return result;
+ }
+
+ private void setSmsRoleAndEvaluate(SipTransportController c, String packageName) {
+ verify(mMockRoleManager).addOnRoleHoldersChangedListenerAsUser(any(), any(), any());
+ mSmsPackageName.clear();
+ mSmsPackageName.add(packageName);
+ c.onRoleHoldersChanged(RoleManager.ROLE_SMS, UserHandle.SYSTEM);
+ // finish internal throttled re-evaluate
+ waitForExecutorAction(mExecutorService, TIMEOUT_MS);
+ }
+
+ private SipTransportController createController(ScheduledExecutorService e) {
+ return createControllerAndThrottle(e, 0 /*throttleMs*/);
+ }
+
+ private SipTransportController createControllerAndThrottle(ScheduledExecutorService e,
+ int throttleMs) {
+ return new SipTransportController(mContext, 0 /*slotId*/, TEST_SUB_ID,
+ mMockDelegateControllerFactory, mMockRoleManager,
+ // Remove delays for testing.
+ new SipTransportController.TimerAdapter() {
+ @Override
+ public int getReevaluateThrottleTimerMilliseconds() {
+ return throttleMs;
+ }
+
+ @Override
+ public int getUpdateRegistrationDelayMilliseconds() {
+ return 0;
+ }
+ }, e);
+ }
+
+ private boolean scheduleDelayedWait(long timeMs) {
+ CountDownLatch l = new CountDownLatch(1);
+ mExecutorService.schedule(l::countDown, timeMs, TimeUnit.MILLISECONDS);
+ while (l.getCount() > 0) {
+ try {
+ return l.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ // try again
+ }
+ }
+ return true;
+ }
+}
diff --git a/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java b/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
index cfb68b7..7a9f9e3 100644
--- a/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
+++ b/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
@@ -50,8 +50,10 @@
@Captor ArgumentCaptor<BroadcastReceiver> mReceiverCaptor;
@Mock TelephonyRcsService.FeatureFactory mFeatureFactory;
- @Mock UserCapabilityExchangeImpl mMockUceSlot0;
- @Mock UserCapabilityExchangeImpl mMockUceSlot1;
+ @Mock UceControllerManager mMockUceSlot0;
+ @Mock UceControllerManager mMockUceSlot1;
+ @Mock SipTransportController mMockSipTransportSlot0;
+ @Mock SipTransportController mMockSipTransportSlot1;
@Mock RcsFeatureController.RegistrationHelperFactory mRegistrationFactory;
@Mock RcsFeatureController.FeatureConnectorFactory<RcsFeatureManager> mFeatureConnectorFactory;
@Mock FeatureConnector<RcsFeatureManager> mFeatureConnector;
@@ -68,10 +70,14 @@
mFeatureControllerSlot1 = createFeatureController(1 /*slotId*/);
doReturn(mFeatureControllerSlot0).when(mFeatureFactory).createController(any(), eq(0));
doReturn(mFeatureControllerSlot1).when(mFeatureFactory).createController(any(), eq(1));
- doReturn(mMockUceSlot0).when(mFeatureFactory).createUserCapabilityExchange(any(), eq(0),
+ doReturn(mMockUceSlot0).when(mFeatureFactory).createUceControllerManager(any(), eq(0),
anyInt());
- doReturn(mMockUceSlot1).when(mFeatureFactory).createUserCapabilityExchange(any(), eq(1),
+ doReturn(mMockUceSlot1).when(mFeatureFactory).createUceControllerManager(any(), eq(1),
anyInt());
+ doReturn(mMockSipTransportSlot0).when(mFeatureFactory).createSipTransportController(any(),
+ eq(0), anyInt());
+ doReturn(mMockSipTransportSlot1).when(mFeatureFactory).createSipTransportController(any(),
+ eq(1), anyInt());
//set up default slot-> sub ID mappings.
setSlotToSubIdMapping(0 /*slotId*/, 1/*subId*/);
setSlotToSubIdMapping(1 /*slotId*/, 2/*subId*/);
@@ -83,18 +89,20 @@
}
@Test
- public void testUserCapabilityExchangePresenceConnected() {
- setCarrierConfig(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, true /*isEnabled*/);
+ public void testUceControllerPresenceConnected() {
+ setCarrierConfig(1 /*subId*/, CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL,
+ true /*isEnabled*/);
createRcsService(1 /*numSlots*/);
- verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UserCapabilityExchangeImpl.class);
+ verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class);
verify(mFeatureControllerSlot0).connect();
}
@Test
- public void testUserCapabilityExchangeOptionsConnected() {
- setCarrierConfig(CarrierConfigManager.KEY_USE_RCS_SIP_OPTIONS_BOOL, true /*isEnabled*/);
+ public void testUceControllerOptionsConnected() {
+ setCarrierConfig(1 /*subId*/, CarrierConfigManager.KEY_USE_RCS_SIP_OPTIONS_BOOL,
+ true /*isEnabled*/);
createRcsService(1 /*numSlots*/);
- verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UserCapabilityExchangeImpl.class);
+ verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class);
verify(mFeatureControllerSlot0).connect();
}
@@ -103,18 +111,67 @@
createRcsService(1 /*numSlots*/);
// No carrier config set for UCE.
verify(mFeatureControllerSlot0, never()).addFeature(mMockUceSlot0,
- UserCapabilityExchangeImpl.class);
+ UceControllerManager.class);
verify(mFeatureControllerSlot0, never()).connect();
}
@Test
+ public void testSipTransportConnected() {
+ createRcsService(1 /*numSlots*/);
+ verify(mFeatureControllerSlot0, never()).addFeature(mMockSipTransportSlot0,
+ SipTransportController.class);
+ verify(mFeatureControllerSlot0, never()).connect();
+
+
+ // Send carrier config update for each slot.
+ setCarrierConfig(1 /*subId*/,
+ CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL,
+ true /*isEnabled*/);
+ sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/);
+ verify(mFeatureControllerSlot0).addFeature(mMockSipTransportSlot0,
+ SipTransportController.class);
+ verify(mFeatureControllerSlot0).connect();
+ verify(mFeatureControllerSlot0).updateAssociatedSubscription(1);
+ }
+
+ @Test
+ public void testSipTransportConnectedOneSlot() {
+ createRcsService(2 /*numSlots*/);
+ verify(mFeatureControllerSlot0, never()).addFeature(mMockSipTransportSlot0,
+ SipTransportController.class);
+ verify(mFeatureControllerSlot0, never()).connect();
+ verify(mFeatureControllerSlot0, never()).addFeature(mMockSipTransportSlot1,
+ SipTransportController.class);
+ verify(mFeatureControllerSlot1, never()).connect();
+
+
+ // Send carrier config update for slot 0 only
+ setCarrierConfig(1 /*subId*/,
+ CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL,
+ true /*isEnabled*/);
+ setCarrierConfig(2 /*subId*/,
+ CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL,
+ false /*isEnabled*/);
+ sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/);
+ sendCarrierConfigChanged(1 /*slotId*/, 2 /*subId*/);
+ verify(mFeatureControllerSlot0).addFeature(mMockSipTransportSlot0,
+ SipTransportController.class);
+ verify(mFeatureControllerSlot1, never()).addFeature(mMockSipTransportSlot0,
+ SipTransportController.class);
+ verify(mFeatureControllerSlot0).connect();
+ verify(mFeatureControllerSlot1, never()).connect();
+ verify(mFeatureControllerSlot0).updateAssociatedSubscription(1);
+ verify(mFeatureControllerSlot1, never()).updateAssociatedSubscription(1);
+ }
+
+ @Test
public void testNoFeaturesEnabledCarrierConfigChanged() {
createRcsService(1 /*numSlots*/);
// No carrier config set for UCE.
sendCarrierConfigChanged(0, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
verify(mFeatureControllerSlot0, never()).addFeature(mMockUceSlot0,
- UserCapabilityExchangeImpl.class);
+ UceControllerManager.class);
verify(mFeatureControllerSlot0, never()).connect();
verify(mFeatureControllerSlot0, never()).updateAssociatedSubscription(anyInt());
}
@@ -122,27 +179,30 @@
@Test
public void testSlotUpdates() {
- setCarrierConfig(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, true /*isEnabled*/);
+ setCarrierConfig(1 /*subId*/, CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL,
+ true /*isEnabled*/);
+ setCarrierConfig(2 /*subId*/, CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL,
+ true /*isEnabled*/);
TelephonyRcsService service = createRcsService(1 /*numSlots*/);
- verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UserCapabilityExchangeImpl.class);
+ verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class);
verify(mFeatureControllerSlot0).connect();
// there should be no changes if the new num slots = old num
service.updateFeatureControllerSize(1 /*newNumSlots*/);
verify(mFeatureControllerSlot0, times(1)).addFeature(mMockUceSlot0,
- UserCapabilityExchangeImpl.class);
+ UceControllerManager.class);
verify(mFeatureControllerSlot0, times(1)).connect();
// Add a new slot.
verify(mFeatureControllerSlot1, never()).addFeature(mMockUceSlot1,
- UserCapabilityExchangeImpl.class);
+ UceControllerManager.class);
verify(mFeatureControllerSlot1, never()).connect();
service.updateFeatureControllerSize(2 /*newNumSlots*/);
// This shouldn't have changed for slot 0.
verify(mFeatureControllerSlot0, times(1)).addFeature(mMockUceSlot0,
- UserCapabilityExchangeImpl.class);
+ UceControllerManager.class);
verify(mFeatureControllerSlot0, times(1)).connect();
- verify(mFeatureControllerSlot1).addFeature(mMockUceSlot1, UserCapabilityExchangeImpl.class);
+ verify(mFeatureControllerSlot1).addFeature(mMockUceSlot1, UceControllerManager.class);
verify(mFeatureControllerSlot1, times(1)).connect();
// Remove a slot.
@@ -151,10 +211,10 @@
service.updateFeatureControllerSize(1 /*newNumSlots*/);
// addFeature/connect shouldn't have been called again
verify(mFeatureControllerSlot0, times(1)).addFeature(mMockUceSlot0,
- UserCapabilityExchangeImpl.class);
+ UceControllerManager.class);
verify(mFeatureControllerSlot0, times(1)).connect();
verify(mFeatureControllerSlot1, times(1)).addFeature(mMockUceSlot1,
- UserCapabilityExchangeImpl.class);
+ UceControllerManager.class);
verify(mFeatureControllerSlot1, times(1)).connect();
// Verify destroy is only called for slot 1.
verify(mFeatureControllerSlot0, never()).destroy();
@@ -163,10 +223,13 @@
@Test
public void testCarrierConfigUpdate() {
- setCarrierConfig(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, true /*isEnabled*/);
+ setCarrierConfig(1 /*subId*/, CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL,
+ true /*isEnabled*/);
+ setCarrierConfig(2 /*subId*/, CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL,
+ true /*isEnabled*/);
createRcsService(2 /*numSlots*/);
- verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UserCapabilityExchangeImpl.class);
- verify(mFeatureControllerSlot1).addFeature(mMockUceSlot1, UserCapabilityExchangeImpl.class);
+ verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class);
+ verify(mFeatureControllerSlot1).addFeature(mMockUceSlot1, UceControllerManager.class);
verify(mFeatureControllerSlot0).connect();
verify(mFeatureControllerSlot1).connect();
@@ -182,16 +245,38 @@
@Test
public void testCarrierConfigUpdateUceToNoUce() {
- setCarrierConfig(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, true /*isEnabled*/);
+ setCarrierConfig(1 /*subId*/, CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL,
+ true /*isEnabled*/);
createRcsService(1 /*numSlots*/);
- verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UserCapabilityExchangeImpl.class);
+ verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class);
verify(mFeatureControllerSlot0).connect();
// Send carrier config update for each slot.
- setCarrierConfig(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, false /*isEnabled*/);
+ setCarrierConfig(1 /*subId*/, CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL,
+ false /*isEnabled*/);
sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/);
- verify(mFeatureControllerSlot0).removeFeature(UserCapabilityExchangeImpl.class);
+ verify(mFeatureControllerSlot0).removeFeature(UceControllerManager.class);
+ verify(mFeatureControllerSlot0).updateAssociatedSubscription(1);
+ }
+
+ @Test
+ public void testCarrierConfigUpdateTransportToNoTransport() {
+ setCarrierConfig(1 /*subId*/,
+ CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL,
+ true /*isEnabled*/);
+ createRcsService(1 /*numSlots*/);
+ verify(mFeatureControllerSlot0).addFeature(mMockSipTransportSlot0,
+ SipTransportController.class);
+ verify(mFeatureControllerSlot0).connect();
+
+
+ // Send carrier config update for each slot.
+ setCarrierConfig(1 /*subId*/,
+ CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL,
+ false /*isEnabled*/);
+ sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/);
+ verify(mFeatureControllerSlot0).removeFeature(SipTransportController.class);
verify(mFeatureControllerSlot0).updateAssociatedSubscription(1);
}
@@ -199,14 +284,15 @@
public void testCarrierConfigUpdateNoUceToUce() {
createRcsService(1 /*numSlots*/);
verify(mFeatureControllerSlot0, never()).addFeature(mMockUceSlot0,
- UserCapabilityExchangeImpl.class);
+ UceControllerManager.class);
verify(mFeatureControllerSlot0, never()).connect();
// Send carrier config update for each slot.
- setCarrierConfig(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, true /*isEnabled*/);
+ setCarrierConfig(1 /*subId*/, CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL,
+ true /*isEnabled*/);
sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/);
- verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UserCapabilityExchangeImpl.class);
+ verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class);
verify(mFeatureControllerSlot0).connect();
verify(mFeatureControllerSlot0).updateAssociatedSubscription(1);
}
@@ -218,8 +304,8 @@
mReceiverCaptor.getValue().onReceive(mContext, intent);
}
- private void setCarrierConfig(String key, boolean value) {
- PersistableBundle bundle = mContext.getCarrierConfig();
+ private void setCarrierConfig(int subId, String key, boolean value) {
+ PersistableBundle bundle = mContext.getCarrierConfig(subId);
bundle.putBoolean(key, value);
}
diff --git a/tests/src/com/android/services/telephony/rcs/UceControllerManagerTest.java b/tests/src/com/android/services/telephony/rcs/UceControllerManagerTest.java
new file mode 100644
index 0000000..4148d13
--- /dev/null
+++ b/tests/src/com/android/services/telephony/rcs/UceControllerManagerTest.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2020 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.services.telephony.rcs;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import android.net.Uri;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.aidl.IRcsUceControllerCallback;
+import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+import com.android.TestExecutorService;
+import com.android.ims.RcsFeatureManager;
+import com.android.ims.rcs.uce.UceController;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+
+@RunWith(AndroidJUnit4.class)
+public class UceControllerManagerTest extends TelephonyTestBase {
+
+ @Mock private UceController mUceController;
+ @Mock private RcsFeatureManager mRcsFeatureManager;
+
+ private final ExecutorService mExecutorService = new TestExecutorService();
+
+ private int mSlotId = 1;
+ private int mSubId = 1;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ doReturn(mSubId).when(mUceController).getSubId();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @Test
+ public void testRcsConnected() throws Exception {
+ UceControllerManager controllerManager = getUceControllerManager();
+
+ controllerManager.onRcsConnected(mRcsFeatureManager);
+
+ verify(mUceController).onRcsConnected(mRcsFeatureManager);
+ }
+
+ @Test
+ public void testRcsDisconnected() throws Exception {
+ UceControllerManager uceCtrlManager = getUceControllerManager();
+
+ uceCtrlManager.onRcsDisconnected();
+
+ verify(mUceController).onRcsDisconnected();
+ }
+
+ @Test
+ public void testDestroy() throws Exception {
+ UceControllerManager uceCtrlManager = getUceControllerManager();
+
+ uceCtrlManager.onDestroy();
+
+ verify(mUceController).onDestroy();
+ }
+
+ @Test
+ public void testSubscriptionUpdated() throws Exception {
+ UceControllerManager uceCtrlManager = getUceControllerManager();
+
+ uceCtrlManager.onAssociatedSubscriptionUpdated(mSubId);
+
+ verify(mUceController).onDestroy();
+ }
+
+ @Test
+ public void testRequestCapabilitiesWithRcsUnavailable() throws Exception {
+ UceControllerManager uceCtrlManager = getUceControllerManager();
+ doReturn(true).when(mUceController).isUnavailable();
+ uceCtrlManager.onRcsDisconnected();
+
+ try {
+ List<Uri> contacts = Arrays.asList(Uri.fromParts("sip", "00000", null));
+ IRcsUceControllerCallback callback = Mockito.mock(IRcsUceControllerCallback.class);
+
+ uceCtrlManager.requestCapabilities(contacts, callback);
+
+ fail();
+ } catch (ImsException e) {
+ assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
+ return;
+ }
+ fail();
+ }
+
+ @Test
+ public void testRequestCapabilitiesWithRcsConnected() throws Exception {
+ UceControllerManager uceCtrlManager = getUceControllerManager();
+ doReturn(false).when(mUceController).isUnavailable();
+ uceCtrlManager.onRcsConnected(mRcsFeatureManager);
+
+ try {
+ List<Uri> contacts = Arrays.asList(Uri.fromParts("sip", "00000", null));
+ IRcsUceControllerCallback callback = Mockito.mock(IRcsUceControllerCallback.class);
+
+ uceCtrlManager.requestCapabilities(contacts, callback);
+
+ verify(mUceController).requestCapabilities(contacts, callback);
+ } catch (ImsException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void testRequestNetworkAvailability() throws Exception {
+ UceControllerManager uceCtrlManager = getUceControllerManager();
+ doReturn(false).when(mUceController).isUnavailable();
+ uceCtrlManager.onRcsConnected(mRcsFeatureManager);
+
+ Uri contact = Uri.fromParts("sip", "00000", null);
+ IRcsUceControllerCallback callback = Mockito.mock(IRcsUceControllerCallback.class);
+
+ uceCtrlManager.requestNetworkAvailability(contact, callback);
+
+ verify(mUceController).requestAvailability(contact, callback);
+ }
+
+ @Test
+ public void testRequestNetworkAvailabilityWithRcsUnavailable() throws Exception {
+ UceControllerManager uceCtrlManager = getUceControllerManager();
+ doReturn(true).when(mUceController).isUnavailable();
+ uceCtrlManager.onRcsDisconnected();
+
+ try {
+ Uri contact = Uri.fromParts("sip", "00000", null);
+ IRcsUceControllerCallback callback = Mockito.mock(IRcsUceControllerCallback.class);
+ uceCtrlManager.requestNetworkAvailability(contact, callback);
+ fail();
+ } catch (ImsException e) {
+ assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
+ return;
+ }
+ fail();
+ }
+
+ @Test
+ public void testGetPublishState() throws Exception {
+ UceControllerManager uceCtrlManager = getUceControllerManager();
+ doReturn(false).when(mUceController).isUnavailable();
+ uceCtrlManager.onRcsConnected(mRcsFeatureManager);
+
+ uceCtrlManager.getUcePublishState();
+
+ verify(mUceController).getUcePublishState();
+ }
+
+ @Test
+ public void testGetPublishStateWithRcsUnavailable() throws Exception {
+ UceControllerManager uceCtrlManager = getUceControllerManager();
+ doReturn(true).when(mUceController).isUnavailable();
+ uceCtrlManager.onRcsDisconnected();
+
+ try {
+ uceCtrlManager.getUcePublishState();
+ fail();
+ } catch (ImsException e) {
+ assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
+ return;
+ }
+ fail();
+ }
+
+ @Test
+ public void testRegisterPublishStateCallback() throws Exception {
+ UceControllerManager uceCtrlManager = getUceControllerManager();
+ IRcsUcePublishStateCallback callback = Mockito.mock(IRcsUcePublishStateCallback.class);
+
+ uceCtrlManager.registerPublishStateCallback(callback);
+
+ verify(mUceController).registerPublishStateCallback(callback);
+ }
+
+ @Test
+ public void testRegisterPublishStateCallbackWithRcsUnavailable() throws Exception {
+ UceControllerManager uceCtrlManager = getUceControllerManager();
+ doReturn(true).when(mUceController).isUnavailable();
+ uceCtrlManager.onRcsDisconnected();
+
+ try {
+ IRcsUcePublishStateCallback callback = Mockito.mock(IRcsUcePublishStateCallback.class);
+ uceCtrlManager.registerPublishStateCallback(callback);
+ fail();
+ } catch (ImsException e) {
+ assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
+ return;
+ }
+ fail();
+ }
+
+ @Test
+ public void testUnregisterPublishStateCallback() throws Exception {
+ UceControllerManager uceCtrlManager = getUceControllerManager();
+ IRcsUcePublishStateCallback callback = Mockito.mock(IRcsUcePublishStateCallback.class);
+
+ uceCtrlManager.unregisterPublishStateCallback(callback);
+
+ verify(mUceController).unregisterPublishStateCallback(callback);
+ }
+
+ private UceControllerManager getUceControllerManager() {
+ UceControllerManager manager = new UceControllerManager(mContext, mSlotId, mSubId,
+ mExecutorService);
+ manager.setUceController(mUceController);
+ return manager;
+ }
+}
diff --git a/tests/src/com/android/services/telephony/rcs/UserCapabilityExchangeImplTest.java b/tests/src/com/android/services/telephony/rcs/UserCapabilityExchangeImplTest.java
deleted file mode 100644
index 82ecd79..0000000
--- a/tests/src/com/android/services/telephony/rcs/UserCapabilityExchangeImplTest.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright (C) 2020 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.services.telephony.rcs;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyList;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.net.Uri;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.RemoteCallbackList;
-import android.telephony.ims.ImsManager;
-import android.telephony.ims.ImsMmTelManager;
-import android.telephony.ims.RcsContactUceCapability;
-import android.telephony.ims.RegistrationManager;
-import android.telephony.ims.aidl.IRcsUceControllerCallback;
-import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
-import android.telephony.ims.stub.RcsCapabilityExchange;
-import android.telephony.ims.stub.RcsPresenceExchangeImplBase;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.TelephonyTestBase;
-import com.android.ims.RcsFeatureManager;
-import com.android.ims.RcsFeatureManager.RcsFeatureCallbacks;
-import com.android.ims.ResultCode;
-import com.android.service.ims.presence.PresenceBase;
-import com.android.service.ims.presence.PresencePublication;
-import com.android.service.ims.presence.PresencePublisher;
-import com.android.service.ims.presence.PresenceSubscriber;
-import com.android.service.ims.presence.SubscribePublisher;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.Executor;
-
-@RunWith(AndroidJUnit4.class)
-public class UserCapabilityExchangeImplTest extends TelephonyTestBase {
-
- private int mSlotId = 0;
- private int mSubId = 1;
- private int mUpdatedSubId = 2;
-
- @Captor ArgumentCaptor<IRcsUcePublishStateCallback> mPublishStateCallbacksCaptor;
-
- @Mock PresencePublication mPresencePublication;
- @Mock PresenceSubscriber mPresenceSubscriber;
- @Mock RcsFeatureManager mRcsFeatureManager;
- @Mock ImsMmTelManager mImsMmTelManager;
- @Mock RemoteCallbackList<IRcsUcePublishStateCallback> mPublishStateCallbacks;
-
- private Looper mLooper;
-
- @Before
- public void setUp() throws Exception {
- super.setUp();
-
- ImsManager imsManager =
- (ImsManager) mContext.getSystemService(Context.TELEPHONY_IMS_SERVICE);
- when(imsManager.getImsMmTelManager(mSubId)).thenReturn(mImsMmTelManager);
- }
-
- @After
- public void tearDown() throws Exception {
- super.tearDown();
-
- if (mLooper != null) {
- mLooper.quit();
- mLooper = null;
- }
- }
-
- @Test
- public void testServiceConnected() throws Exception {
- UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
- uceImpl.onRcsConnected(mRcsFeatureManager);
-
- verify(mRcsFeatureManager).addFeatureListenerCallback(any(RcsFeatureCallbacks.class));
- verify(mPresencePublication).updatePresencePublisher(any(PresencePublisher.class));
- verify(mPresenceSubscriber).updatePresenceSubscriber(any(SubscribePublisher.class));
- }
-
- @Test
- public void testServiceDisconnected() throws Exception {
- UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
- uceImpl.onRcsDisconnected();
-
- verify(mPresencePublication).removePresencePublisher();
- verify(mPresenceSubscriber).removePresenceSubscriber();
- }
-
- @Test
- public void testSubscriptionUpdated() throws Exception {
- UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
- uceImpl.onAssociatedSubscriptionUpdated(mUpdatedSubId);
-
- verify(mImsMmTelManager).registerImsRegistrationCallback(any(Executor.class),
- any(RegistrationManager.RegistrationCallback.class));
- verify(mImsMmTelManager).registerMmTelCapabilityCallback(any(Executor.class),
- any(ImsMmTelManager.CapabilityCallback.class));
- verify(mPresencePublication).handleAssociatedSubscriptionChanged(mUpdatedSubId);
- verify(mPresenceSubscriber).handleAssociatedSubscriptionChanged(mUpdatedSubId);
- }
-
- @Test
- public void testUcePublishStateRetrieval() throws Exception {
- UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
- uceImpl.getUcePublishState();
-
- verify(mPresencePublication).getPublishState();
- }
-
- @Test
- public void testRegisterPublishStateCallbacks() throws Exception {
- UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
- uceImpl.registerPublishStateCallback(any(IRcsUcePublishStateCallback.class));
- verify(mPublishStateCallbacks).register(mPublishStateCallbacksCaptor.capture());
- }
-
- @Test
- public void testOnNotifyUpdateCapabilities() throws Exception {
- UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
- uceImpl.onRcsConnected(mRcsFeatureManager);
-
- int triggerType = RcsPresenceExchangeImplBase.CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN;
- uceImpl.mRcsFeatureCallback.onNotifyUpdateCapabilities(triggerType);
- waitForMs(1000);
-
- verify(mPresencePublication).onStackPublishRequested(triggerType);
- }
-
- @Test
- public void testRequestPublicationWithSuccessfulResponse() throws Exception {
- int taskId = 1;
- int sipResponse = 200;
- Uri contact = Uri.fromParts("sip", "test", null);
- RcsContactUceCapability.Builder builder = new RcsContactUceCapability.Builder(contact);
- RcsContactUceCapability capability = builder.build();
-
- UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
- uceImpl.onRcsConnected(mRcsFeatureManager);
-
- doAnswer(invocation -> {
- uceImpl.mRcsFeatureCallback.onCommandUpdate(RcsCapabilityExchange.COMMAND_CODE_SUCCESS,
- taskId);
- uceImpl.mRcsFeatureCallback.onNetworkResponse(sipResponse, null, taskId);
- return null;
- }).when(mRcsFeatureManager).requestPublication(capability, taskId);
-
- // Request publication
- int result = uceImpl.requestPublication(capability, contact.toString(), taskId);
-
- assertEquals(ResultCode.SUCCESS, result);
- verify(mPresencePublication).onCommandStatusUpdated(taskId, taskId, ResultCode.SUCCESS);
- verify(mPresencePublication).onSipResponse(taskId, sipResponse, null);
- }
-
- @Test
- public void testRequestPublicationWithFailedResponse() throws Exception {
- int taskId = 1;
- Uri contact = Uri.fromParts("sip", "test", null);
- RcsContactUceCapability.Builder builder = new RcsContactUceCapability.Builder(contact);
- RcsContactUceCapability capability = builder.build();
-
- UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
- uceImpl.onRcsConnected(mRcsFeatureManager);
-
- doAnswer(invocation -> {
- uceImpl.mRcsFeatureCallback.onCommandUpdate(
- RcsCapabilityExchange.COMMAND_CODE_GENERIC_FAILURE, taskId);
- return null;
- }).when(mRcsFeatureManager).requestPublication(capability, taskId);
-
- // Request publication
- int result = uceImpl.requestPublication(capability, contact.toString(), taskId);
-
- assertEquals(ResultCode.SUCCESS, result);
- verify(mPresencePublication).onCommandStatusUpdated(taskId, taskId,
- ResultCode.PUBLISH_GENERIC_FAILURE);
- }
-
- @Test
- public void testRequestCapability() throws Exception {
- int taskId = 1;
- int sipResponse = 200;
- List<RcsContactUceCapability> infos = new ArrayList<>();
- List<Uri> contacts = Arrays.asList(Uri.fromParts("sip", "00000", null));
- IRcsUceControllerCallback callback = Mockito.mock(IRcsUceControllerCallback.class);
-
- UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
- uceImpl.onRcsConnected(mRcsFeatureManager);
-
- when(mPresenceSubscriber.requestCapability(anyList(), any())).thenReturn(taskId);
-
- doAnswer(invocation -> {
- uceImpl.mRcsFeatureCallback.onCommandUpdate(RcsCapabilityExchange.COMMAND_CODE_SUCCESS,
- taskId);
- uceImpl.mRcsFeatureCallback.onNetworkResponse(sipResponse, null, taskId);
- uceImpl.mRcsFeatureCallback.onCapabilityRequestResponsePresence(infos, taskId);
- return null;
- }).when(mRcsFeatureManager).requestCapabilities(anyList(), anyInt());
-
- uceImpl.requestCapabilities(contacts, callback);
- uceImpl.requestCapability(new String[] {"00000"}, taskId);
-
- verify(mPresenceSubscriber).onCommandStatusUpdated(taskId, taskId, ResultCode.SUCCESS);
- verify(mPresenceSubscriber).onSipResponse(taskId, sipResponse, null);
- verify(mPresenceSubscriber).updatePresences(taskId, infos, true, null);
- }
-
- @Test
- public void testUpdatePublisherState() throws Exception {
- IRcsUcePublishStateCallback callback = Mockito.mock(IRcsUcePublishStateCallback.class);
- doAnswer(invocation -> {
- callback.onPublishStateChanged(anyInt());
- return null;
- }).when(mPublishStateCallbacks).broadcast(any());
-
- UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
- uceImpl.onRcsConnected(mRcsFeatureManager);
- uceImpl.registerPublishStateCallback(callback);
- uceImpl.updatePublisherState(PresenceBase.PUBLISH_STATE_200_OK);
-
- assertEquals(PresenceBase.PUBLISH_STATE_200_OK, uceImpl.getPublisherState());
- verify(callback).onPublishStateChanged(anyInt());
- }
-
- @Test
- public void testUnpublish() throws Exception {
- IRcsUcePublishStateCallback callback = Mockito.mock(IRcsUcePublishStateCallback.class);
- doAnswer(invocation -> {
- callback.onPublishStateChanged(anyInt());
- return null;
- }).when(mPublishStateCallbacks).broadcast(any());
-
- UserCapabilityExchangeImpl uceImpl = createUserCapabilityExchangeImpl();
- uceImpl.onRcsConnected(mRcsFeatureManager);
- uceImpl.mRcsFeatureCallback.onUnpublish();
- waitForMs(1000);
-
- verify(mPresencePublication).setPublishState(PresenceBase.PUBLISH_STATE_NOT_PUBLISHED);
- }
-
- private UserCapabilityExchangeImpl createUserCapabilityExchangeImpl() throws Exception {
- HandlerThread handlerThread = new HandlerThread("UceImplHandlerThread");
- handlerThread.start();
- mLooper = handlerThread.getLooper();
- UserCapabilityExchangeImpl uceImpl = new UserCapabilityExchangeImpl(mContext, mSlotId,
- mSubId, mLooper, mPresencePublication, mPresenceSubscriber,
- mPublishStateCallbacks);
- verify(mPresencePublication).handleAssociatedSubscriptionChanged(1);
- verify(mPresenceSubscriber).handleAssociatedSubscriptionChanged(1);
- waitForHandlerAction(uceImpl.getHandler(), 1000);
- verify(mImsMmTelManager, atLeast(1)).registerImsRegistrationCallback(
- any(Executor.class), any(RegistrationManager.RegistrationCallback.class));
- verify(mContext).registerReceiver(any(), any());
- return uceImpl;
- }
-}